github.com/balzaczyy/golucene@v0.0.0-20151210033525-d0be9ee89713/core/util/openBitSet.go (about)

     1  package util
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  )
     7  
     8  type OpenBitSet struct {
     9  	bits    []int64
    10  	wlen    int   // number of words (elements) used in the array
    11  	numBits int64 // for assert only
    12  }
    13  
    14  /* Constructs an OpenBitSet large enough to hold numBits. */
    15  func NewOpenBitSetOf(numBits int64) *OpenBitSet {
    16  	assert(numBits > 0)
    17  	bits := make([]int64, bits2words(numBits))
    18  	return &OpenBitSet{
    19  		numBits: numBits,
    20  		bits:    bits,
    21  		wlen:    len(bits),
    22  	}
    23  }
    24  
    25  func NewOpenBitSet() *OpenBitSet {
    26  	return NewOpenBitSetOf(64)
    27  }
    28  
    29  /* Returns true if there are no set bits */
    30  func (b *OpenBitSet) IsEmpty() bool {
    31  	return b.Cardinality() == 0
    32  }
    33  
    34  /* Returns true or false for the specified bit index */
    35  func (b *OpenBitSet) Get(index int64) bool {
    36  	i := int(index >> 6) // div 64
    37  	if i >= len(b.bits) {
    38  		return false
    39  	}
    40  	bitmask := int64(1) << uint(index&0x3f)
    41  	return (b.bits[i] & bitmask) != 0
    42  }
    43  
    44  /* Sets a bit, expanding the set size if necessary */
    45  func (b *OpenBitSet) Set(index int64) {
    46  	wordNum := b.expandingWordNum(index)
    47  	bitmask := int64(1) << uint64(index&0x3f)
    48  	b.bits[wordNum] |= bitmask
    49  }
    50  
    51  func (b *OpenBitSet) expandingWordNum(index int64) int {
    52  	wordNum := int(index >> 6)
    53  	if wordNum >= b.wlen {
    54  		b.ensureCapacity(index + 1)
    55  	}
    56  	return wordNum
    57  }
    58  
    59  /* Clears a bit, allowing access beyond the current set size without changing the size. */
    60  func (b *OpenBitSet) Clear(index int64) {
    61  	wordNum := int(index >> 6) // div 64
    62  	if wordNum >= b.wlen {
    63  		return
    64  	}
    65  	bitmask := int64(1) << uint64(index)
    66  	b.bits[wordNum] &= ^bitmask
    67  }
    68  
    69  // L553
    70  /* Return the number of set bits */
    71  func (b *OpenBitSet) Cardinality() int64 {
    72  	return int64(pop_array(b.bits[:b.wlen]))
    73  }
    74  
    75  // L606
    76  
    77  /*
    78  Returns the index of the first set bit starting at the index specified.
    79  - is returned if there are no more set bits.
    80  */
    81  func (b *OpenBitSet) NextSetBit(index int64) int64 {
    82  	assert(index >= 0)
    83  	i := int(uint64(index) >> 6)
    84  	if i >= b.wlen {
    85  		return -1
    86  	}
    87  	subIndex := int(index & 0x3f)                      // index within the word
    88  	word := int64(uint64(b.bits[i]) >> uint(subIndex)) // skip all the bits to the right of index
    89  
    90  	if word != 0 {
    91  		return (int64(i) << 6) + int64(subIndex) + int64(NumberOfTrailingZeros(word))
    92  	}
    93  
    94  	for i++; i < b.wlen; i++ {
    95  		word = b.bits[i]
    96  		if word != 0 {
    97  			return (int64(i) << 6) + int64(NumberOfTrailingZeros(word))
    98  		}
    99  	}
   100  
   101  	return -1
   102  }
   103  
   104  /* Returns the number of 64 bit words it would take to hold numBits */
   105  func bits2words(numBits int64) int {
   106  	return int((uint64(numBits-1) >> 6) + 1)
   107  }
   108  
   109  /* Expert: returns the []int64 storing the bits */
   110  // func (b *OpenBitSet) RealBits() []int64 { return b.bits }
   111  
   112  // L724
   113  
   114  func (b *OpenBitSet) intersect(other *OpenBitSet) {
   115  	newLen := b.wlen
   116  	if other.wlen < newLen {
   117  		newLen = other.wlen
   118  	}
   119  	thisArr := b.bits
   120  	otherArr := other.bits
   121  	// testing against zero can be more efficient
   122  	for pos := newLen - 1; pos >= 0; pos-- {
   123  		thisArr[pos] &= otherArr[pos]
   124  	}
   125  	if b.wlen > newLen {
   126  		// fill zeros from the new shorter length to the old length
   127  		for i := newLen; i < b.wlen; i++ {
   128  			b.bits[i] = 0
   129  		}
   130  	}
   131  	b.wlen = newLen
   132  }
   133  
   134  //L760
   135  
   136  func (b *OpenBitSet) remove(other *OpenBitSet) {
   137  	idx := b.wlen
   138  	if other.wlen < idx {
   139  		idx = other.wlen
   140  	}
   141  	thisArr := b.bits
   142  	otherArr := other.bits
   143  	for pos := idx - 1; pos >= 0; pos-- {
   144  		thisArr[pos] &= ^otherArr[pos]
   145  	}
   146  }
   147  
   148  func (b *OpenBitSet) And(other *OpenBitSet) {
   149  	b.intersect(other)
   150  }
   151  
   152  func (b *OpenBitSet) AndNot(other *OpenBitSet) {
   153  	b.remove(other)
   154  }
   155  
   156  /* Expand the []int64 with the size given as a number of words (64 bits long). */
   157  func (b *OpenBitSet) ensureCapacityWords(numWords int) {
   158  	if len(b.bits) < numWords {
   159  		arr := make([]int64, numWords)
   160  		copy(arr, b.bits)
   161  		b.bits = arr
   162  	}
   163  	b.wlen = numWords
   164  	if n := int64(numWords) << 6; n > b.numBits {
   165  		b.numBits = n
   166  	}
   167  }
   168  
   169  /* Ensure that the []int64 is big enough to hold numBits, expanding it if necessary. */
   170  func (b *OpenBitSet) ensureCapacity(numBits int64) {
   171  	b.ensureCapacityWords(bits2words(numBits))
   172  	// ensureCapacityWords sets numBits to a multiple of 64, but we
   173  	// want to set it to exactly what the app asked.
   174  	if numBits > b.numBits {
   175  		b.numBits = numBits
   176  	}
   177  }
   178  
   179  func (b *OpenBitSet) String() string {
   180  	var buf bytes.Buffer
   181  	buf.WriteRune('{')
   182  	i := b.NextSetBit(0)
   183  	if i >= 0 {
   184  		fmt.Fprintf(&buf, "%v", i)
   185  		for {
   186  			if i = b.NextSetBit(i + 1); i < 0 {
   187  				break
   188  			}
   189  			fmt.Fprintf(&buf, ", %v", i)
   190  		}
   191  	}
   192  	buf.WriteRune('}')
   193  	return buf.String()
   194  }