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 }