github.com/balzaczyy/golucene@v0.0.0-20151210033525-d0be9ee89713/core/util/packed/packed64.go (about) 1 package packed 2 3 import ( 4 "fmt" 5 "github.com/balzaczyy/golucene/core/util" 6 ) 7 8 const ( 9 PACKED64_BLOCK_SIZE = 64 // 32 = int, 64 = long 10 PACKED64_BLOCK_BITS = 6 // The #bits representing BLOCK_SIZE 11 PACKED64_MOD_MASK = PACKED64_BLOCK_SIZE - 1 // x % BLOCK_SIZE 12 ) 13 14 type Packed64 struct { 15 *MutableImpl 16 blocks []int64 17 maskRight uint64 18 bpvMinusBlockSize int32 19 } 20 21 func newPacked64(valueCount int32, bitsPerValue uint32) *Packed64 { 22 longCount := PackedFormat(PACKED).longCount(VERSION_CURRENT, valueCount, bitsPerValue) 23 ans := &Packed64{ 24 blocks: make([]int64, longCount), 25 maskRight: uint64(^(int64(0))<<(PACKED64_BLOCK_SIZE-bitsPerValue)) >> (PACKED64_BLOCK_SIZE - bitsPerValue), 26 bpvMinusBlockSize: int32(bitsPerValue) - PACKED64_BLOCK_SIZE} 27 ans.MutableImpl = newMutableImpl(ans, int(valueCount), int(bitsPerValue)) 28 return ans 29 } 30 31 func newPacked64FromInput(version int32, in DataInput, valueCount int32, bitsPerValue uint32) (r PackedIntsReader, err error) { 32 ans := newPacked64(valueCount, bitsPerValue) 33 byteCount := PackedFormat(PACKED).ByteCount(version, valueCount, bitsPerValue) 34 longCount := PackedFormat(PACKED).longCount(VERSION_CURRENT, valueCount, bitsPerValue) 35 ans.blocks = make([]int64, longCount) 36 // read as many longs as we can 37 for i := int64(0); i < byteCount/8; i++ { 38 if ans.blocks[i], err = in.ReadLong(); err != nil { 39 break 40 } 41 } 42 if err == nil { 43 if remaining := int8(byteCount % 8); remaining != 0 { 44 // read the last bytes 45 var lastLong int64 46 for i := int8(0); i < remaining; i++ { 47 b, err := in.ReadByte() 48 if err != nil { 49 break 50 } 51 lastLong |= (int64(b) << uint8(56-i*8)) 52 } 53 if err == nil { 54 ans.blocks[len(ans.blocks)-1] = lastLong 55 } 56 } 57 } 58 return ans, err 59 } 60 61 func (p *Packed64) Get(index int) int64 { 62 // The abstract index in a bit stream 63 majorBitPos := int64(index) * int64(p.bitsPerValue) 64 // The index in the backing long-array 65 elementPos := int32(uint64(majorBitPos) >> PACKED64_BLOCK_BITS) 66 // The number of value-bits in the second long 67 endBits := (majorBitPos & PACKED64_MOD_MASK) + int64(p.bpvMinusBlockSize) 68 69 if endBits <= 0 { // Single block 70 return int64(uint64(p.blocks[elementPos])>>uint64(-endBits)) & int64(p.maskRight) 71 } 72 // Two blocks 73 return ((p.blocks[elementPos] << uint64(endBits)) | 74 int64(uint64(p.blocks[elementPos+1])>>(PACKED64_BLOCK_SIZE-uint64(endBits)))) & 75 int64(p.maskRight) 76 } 77 78 func (p *Packed64) getBulk(index int, arr []int64) int { 79 off, length := 0, len(arr) 80 assert2(length > 0, "len must be > 0 (got %v)", length) 81 assert(index >= 0 && index < p.valueCount) 82 if p.valueCount-index < length { 83 length = p.valueCount - index 84 } 85 86 originalIndex := index 87 decoder := newBulkOperation(PackedFormat(PACKED), uint32(p.bitsPerValue)) 88 89 // go to the next block where the value does not span across two blocks 90 offsetInBlocks := index % decoder.LongValueCount() 91 if offsetInBlocks != 0 { 92 panic("niy") 93 } 94 95 // bulk get 96 assert(index%decoder.LongValueCount() == 0) 97 blockIndex := int(uint64(int64(index)*int64(p.bitsPerValue)) >> PACKED64_BLOCK_BITS) 98 assert(((int64(index) * int64(p.bitsPerValue)) & PACKED64_MOD_MASK) == 0) 99 iterations := length / decoder.LongValueCount() 100 decoder.decodeLongToLong(p.blocks[blockIndex:], arr[off:], iterations) 101 gotValues := iterations * decoder.LongValueCount() 102 index += gotValues 103 length -= gotValues 104 assert(length >= 0) 105 106 if index > originalIndex { 107 // stay at the block boundry 108 return index - originalIndex 109 } 110 // no progress so far => already at a block boundry but no full block to get 111 assert(index == originalIndex) 112 return p.MutableImpl.getBulk(index, arr[off:off+length]) 113 } 114 115 func (p *Packed64) Set(index int, value int64) { 116 // The abstract index in a contiguous bit stream 117 majorBitPos := int64(index) * int64(p.bitsPerValue) 118 // The index int the backing long-array 119 elementPos := int(uint64(majorBitPos) >> PACKED64_BLOCK_BITS) // / BLOCK_SIZE 120 // The number of value-bits in the second long 121 endBits := (majorBitPos & PACKED64_MOD_MASK) + int64(p.bpvMinusBlockSize) 122 123 if endBits <= 0 { // single block 124 p.blocks[elementPos] = p.blocks[elementPos] & 125 ^int64(p.maskRight<<uint64(-endBits)) | 126 (value << uint64(-endBits)) 127 return 128 } 129 // two blocks 130 p.blocks[elementPos] = p.blocks[elementPos] & 131 ^int64(p.maskRight>>uint64(endBits)) | 132 int64(uint64(value)>>uint64(endBits)) 133 elementPos++ 134 p.blocks[elementPos] = p.blocks[elementPos]& 135 int64(^uint64(0)>>uint64(endBits)) | 136 (value << uint64(PACKED64_BLOCK_SIZE-endBits)) 137 } 138 139 func (p *Packed64) setBulk(index int, arr []int64) int { 140 off, length := 0, len(arr) 141 assert2(length > 0, "len must be > 0 (got %v)", length) 142 assert(index >= 0 && index < p.valueCount) 143 if p.valueCount-index < length { 144 length = p.valueCount - index 145 } 146 147 originalIndex := index 148 encoder := newBulkOperation(PackedFormat(PACKED), uint32(p.bitsPerValue)) 149 150 // go to the next block where the value does not span across two blocks 151 offsetInBlocks := index % encoder.LongValueCount() 152 if offsetInBlocks != 0 { 153 panic("niy") 154 } 155 156 // bulk set 157 assert(index%encoder.LongValueCount() == 0) 158 blockIndex := int(uint64(int64(index)*int64(p.bitsPerValue)) >> PACKED64_BLOCK_BITS) 159 assert(((int64(index) * int64(p.bitsPerValue)) & PACKED64_MOD_MASK) == 0) 160 iterations := length / encoder.LongValueCount() 161 encoder.encodeLongToLong(arr[off:], p.blocks[blockIndex:], iterations) 162 setValues := iterations * encoder.LongValueCount() 163 index += setValues 164 length -= setValues 165 assert(length >= 0) 166 167 if index > originalIndex { 168 // stay at the block boundry 169 return index - originalIndex 170 } 171 // no progress so far => already at a block boundry but no full block to get 172 assert(index == originalIndex) 173 return p.MutableImpl.setBulk(index, arr[off:off+length]) 174 } 175 176 func (p *Packed64) String() string { 177 return fmt.Sprintf("Packed64(bitsPerValue=%v, size=%v, elements.length=%v)", 178 p.bitsPerValue, p.Size(), len(p.blocks)) 179 } 180 181 func (p *Packed64) RamBytesUsed() int64 { 182 return util.AlignObjectSize( 183 util.NUM_BYTES_OBJECT_HEADER + 184 3*util.NUM_BYTES_INT + 185 util.NUM_BYTES_LONG + 186 util.NUM_BYTES_OBJECT_REF + 187 util.SizeOf(p.blocks)) 188 } 189 190 func (p *Packed64) fill(from, to int, val int64) { 191 panic("niy") 192 } 193 194 func (p *Packed64) Clear() { 195 panic("niy") 196 }