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

     1  package packed
     2  
     3  import (
     4  	"github.com/balzaczyy/golucene/core/util"
     5  	"reflect"
     6  )
     7  
     8  // util/packed/PackedLongValues.java
     9  
    10  const DEFAULT_PAGE_SIZE = 1024
    11  const MIN_PAGE_SIZE = 64
    12  const MAX_PAGE_SIZE = 1 << 20
    13  
    14  type PackedLongValues interface {
    15  	Size() int64
    16  	Iterator() func() (interface{}, bool)
    17  }
    18  
    19  type PackedLongValuesBuilder interface {
    20  	util.Accountable
    21  	Build() PackedLongValues
    22  	Size() int64
    23  	Add(int64) PackedLongValuesBuilder
    24  }
    25  
    26  func DeltaPackedBuilder(acceptableOverheadRatio float32) PackedLongValuesBuilder {
    27  	return NewDeltaPackedLongValuesBuilder(DEFAULT_PAGE_SIZE, acceptableOverheadRatio)
    28  }
    29  
    30  type PackedLongValuesImpl struct {
    31  	values              []PackedIntsReader
    32  	pageShift, pageMask int
    33  	size                int64
    34  	ramBytesUsed        int64
    35  }
    36  
    37  func newPackedLongValues(pageShift, pageMask int,
    38  	values []PackedIntsReader,
    39  	size, ramBytesUsed int64) *PackedLongValuesImpl {
    40  
    41  	return &PackedLongValuesImpl{
    42  		pageShift:    pageShift,
    43  		pageMask:     pageMask,
    44  		values:       values,
    45  		size:         size,
    46  		ramBytesUsed: ramBytesUsed,
    47  	}
    48  }
    49  
    50  func (p *PackedLongValuesImpl) Size() int64 {
    51  	return p.size
    52  }
    53  
    54  func (p *PackedLongValuesImpl) decodeBlock(block int, dest []int64) int {
    55  	vals := p.values[block]
    56  	size := vals.Size()
    57  	for k := 0; k < size; {
    58  		k += vals.getBulk(k, dest[k:size])
    59  	}
    60  	return size
    61  }
    62  
    63  func (p *PackedLongValuesImpl) Iterator() func() (interface{}, bool) {
    64  	currentValues := make([]int64, p.pageMask+1)
    65  	vOff := 0
    66  	pOff := 0
    67  	currentCount := 0
    68  	fillBlock := func() {
    69  		if vOff == len(p.values) {
    70  			currentCount = 0
    71  		} else {
    72  			currentCount = p.decodeBlock(vOff, currentValues)
    73  			assert(currentCount > 0)
    74  		}
    75  	}
    76  	fillBlock()
    77  	return func() (v interface{}, ok bool) {
    78  		if pOff < currentCount {
    79  			v = currentValues[pOff]
    80  			if pOff++; pOff == currentCount {
    81  				vOff++
    82  				pOff = 0
    83  				fillBlock()
    84  			}
    85  		}
    86  		return v, pOff < currentCount
    87  	}
    88  }
    89  
    90  const INITIAL_PAGE_COUNT = 16
    91  
    92  type PackedLongValuesBuilderImpl struct {
    93  	pageShift, pageMask     int
    94  	acceptableOverheadRatio float32
    95  	pending                 []int64
    96  	size                    int64
    97  
    98  	values       []PackedIntsReader
    99  	ramBytesUsed int64
   100  	valuesOff    int
   101  	pendingOff   int
   102  }
   103  
   104  func newPackedLongValuesBuilder(pageSize int,
   105  	acceptableOverheadRatio float32) *PackedLongValuesBuilderImpl {
   106  
   107  	ans := &PackedLongValuesBuilderImpl{
   108  		pageShift:               checkBlockSize(pageSize, MIN_PAGE_SIZE, MAX_PAGE_SIZE),
   109  		pageMask:                pageSize - 1,
   110  		acceptableOverheadRatio: acceptableOverheadRatio,
   111  		values:                  make([]PackedIntsReader, INITIAL_PAGE_COUNT),
   112  		pending:                 make([]int64, pageSize),
   113  	}
   114  	ans.ramBytesUsed = util.ShallowSizeOfInstance(reflect.TypeOf(&PackedLongValuesBuilderImpl{})) +
   115  		util.SizeOf(ans.pending) + util.ShallowSizeOf(ans.values)
   116  	return ans
   117  }
   118  
   119  /*
   120  Build a PackedLongValues instance that contains values that have been
   121  added to this builder. This operation is destructive.
   122  */
   123  func (b *PackedLongValuesBuilderImpl) Build() PackedLongValues {
   124  	b.finish()
   125  	b.pending = nil
   126  	values := make([]PackedIntsReader, b.valuesOff)
   127  	copy(values, b.values[:b.valuesOff])
   128  	ramBytesUsed := util.ShallowSizeOfInstance(reflect.TypeOf(&PackedLongValuesImpl{})) +
   129  		util.SizeOf(values)
   130  	return newPackedLongValues(b.pageShift, b.pageMask, values, b.size, ramBytesUsed)
   131  }
   132  
   133  func (b *PackedLongValuesBuilderImpl) RamBytesUsed() int64 {
   134  	return b.ramBytesUsed
   135  }
   136  
   137  /* Return the number of elements that have been added to this builder */
   138  func (b *PackedLongValuesBuilderImpl) Size() int64 {
   139  	return b.size
   140  }
   141  
   142  /* Add a new element to this builder. */
   143  func (b *PackedLongValuesBuilderImpl) Add(l int64) PackedLongValuesBuilder {
   144  	assert2(b.pending != nil, "Cannot be reused after build()")
   145  	if b.pendingOff == len(b.pending) { // check size
   146  		if b.valuesOff == len(b.values) {
   147  			newLength := util.Oversize(b.valuesOff+1, 8)
   148  			b.grow(newLength)
   149  		}
   150  		b.pack()
   151  	}
   152  	b.pending[b.pendingOff] = l
   153  	b.pendingOff++
   154  	b.size++
   155  	return b
   156  }
   157  
   158  func (b *PackedLongValuesBuilderImpl) finish() {
   159  	if b.pendingOff > 0 {
   160  		if len(b.values) == b.valuesOff {
   161  			b.grow(b.valuesOff + 1)
   162  		}
   163  		b.pack()
   164  	}
   165  }
   166  
   167  func (b *PackedLongValuesBuilderImpl) pack() {
   168  	b.packFrom(b.pending[:b.pendingOff], b.valuesOff, b.acceptableOverheadRatio)
   169  	b.ramBytesUsed += b.values[b.valuesOff].RamBytesUsed()
   170  	b.valuesOff++
   171  	b.pendingOff = 0 // reset pending buffer
   172  }
   173  
   174  func (b *PackedLongValuesBuilderImpl) packFrom(values []int64,
   175  	block int, acceptableOverheadRatio float32) {
   176  
   177  	assert(len(values) > 0)
   178  
   179  	// compute max delta
   180  	minValue := values[0]
   181  	maxValue := values[0]
   182  	for _, v := range values[1:] {
   183  		if v < minValue {
   184  			minValue = v
   185  		} else if v > maxValue {
   186  			maxValue = v
   187  		}
   188  	}
   189  
   190  	// build a new packed reader
   191  	if minValue == 0 && maxValue == 0 {
   192  		b.values[block] = newNilReader(len(values))
   193  	} else {
   194  		bitsRequired := 64
   195  		if minValue >= 0 {
   196  			bitsRequired = BitsRequired(maxValue)
   197  		}
   198  		mutable := MutableFor(len(values), bitsRequired, acceptableOverheadRatio)
   199  		for i := 0; i < len(values); i++ {
   200  			i += mutable.setBulk(i, values[i:])
   201  		}
   202  		b.values[block] = mutable
   203  	}
   204  }
   205  
   206  func (b *PackedLongValuesBuilderImpl) grow(newBlockCount int) {
   207  	panic("niy")
   208  }
   209  
   210  // util/packed/DeltaPackedLongValues.java
   211  
   212  type DeltaPackedLongValuesBuilderImpl struct {
   213  	*PackedLongValuesBuilderImpl
   214  	mins []int64
   215  }
   216  
   217  func NewDeltaPackedLongValuesBuilder(pageSize int,
   218  	acceptableOverheadRatio float32) *DeltaPackedLongValuesBuilderImpl {
   219  
   220  	super := newPackedLongValuesBuilder(pageSize, acceptableOverheadRatio)
   221  	ans := &DeltaPackedLongValuesBuilderImpl{
   222  		PackedLongValuesBuilderImpl: super,
   223  		mins: make([]int64, len(super.values)),
   224  	}
   225  	ans.ramBytesUsed += util.ShallowSizeOfInstance(reflect.TypeOf(&DeltaPackedLongValuesBuilderImpl{})) +
   226  		util.SizeOf(ans.mins)
   227  	return ans
   228  }