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  }