github.com/dgraph-io/sroar@v0.0.0-20220527172339-b92b7eaaf6e0/iterator.go (about)

     1  /*
     2   * Copyright 2021 Dgraph Labs, Inc. and Contributors
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package sroar
    18  
    19  import (
    20  	"math/bits"
    21  )
    22  
    23  type Iterator struct {
    24  	bm *Bitmap
    25  
    26  	keys   []uint64
    27  	keyIdx int
    28  
    29  	contIdx int
    30  
    31  	bitmapIdx int
    32  	bitset    uint16
    33  }
    34  
    35  func (bm *Bitmap) NewRangeIterators(numRanges int) []*Iterator {
    36  	keyn := bm.keys.numKeys()
    37  	iters := make([]*Iterator, numRanges)
    38  	width := keyn / numRanges
    39  	rem := keyn % numRanges
    40  	cnt := 0
    41  
    42  	// This loop distributes the key equally to the ranges. For example: If numRanges = 3
    43  	// and keyn = 8 then it will be distributes as [3, 3, 2]
    44  	for i := 0; i < numRanges; i++ {
    45  		iters[i] = bm.NewIterator()
    46  		n := width
    47  		if i < rem {
    48  			n = width + 1
    49  		}
    50  		iters[i].keys = iters[i].keys[cnt : cnt+2*n]
    51  		cnt = cnt + 2*n
    52  	}
    53  	return iters
    54  }
    55  
    56  func (bm *Bitmap) NewIterator() *Iterator {
    57  	return &Iterator{
    58  		bm:        bm,
    59  		keys:      bm.keys[indexNodeStart : indexNodeStart+bm.keys.numKeys()*2],
    60  		keyIdx:    0,
    61  		contIdx:   -1,
    62  		bitmapIdx: -1,
    63  	}
    64  }
    65  
    66  func (it *Iterator) Next() uint64 {
    67  	if len(it.keys) == 0 {
    68  		return 0
    69  	}
    70  
    71  	key := it.keys[it.keyIdx]
    72  	off := it.keys[it.keyIdx+1]
    73  	cont := it.bm.getContainer(off)
    74  	card := getCardinality(cont)
    75  
    76  	// Loop until we find a container on which next operation is possible. When such a container
    77  	// is found, reset the variables responsible for container iteration.
    78  	for card == 0 || it.contIdx+1 >= card {
    79  		if it.keyIdx+2 >= len(it.keys) {
    80  			return 0
    81  		}
    82  		// jump by 2 because key is followed by a value
    83  		it.keyIdx += 2
    84  		it.contIdx = -1
    85  		it.bitmapIdx = -1
    86  		it.bitset = 0
    87  		key = it.keys[it.keyIdx]
    88  		off = it.keys[it.keyIdx+1]
    89  		cont = it.bm.getContainer(off)
    90  		card = getCardinality(cont)
    91  	}
    92  
    93  	//  The above loop assures that we can do next in this container.
    94  	it.contIdx++
    95  	switch cont[indexType] {
    96  	case typeArray:
    97  		return key | uint64(cont[int(startIdx)+it.contIdx])
    98  	case typeBitmap:
    99  		// A bitmap container is an array of uint16s.
   100  		// If the container is bitmap, go to the index which has a non-zero value.
   101  		for it.bitset == 0 && it.bitmapIdx+1 < len(cont[startIdx:]) {
   102  			it.bitmapIdx++
   103  			it.bitset = cont[int(startIdx)+it.bitmapIdx]
   104  		}
   105  		assert(it.bitset > 0)
   106  
   107  		// msbIdx is the index of most-significant bit. In this iteration we choose this set bit
   108  		// and make it zero.
   109  		msbIdx := uint16(bits.LeadingZeros16(it.bitset))
   110  		msb := 1 << (16 - msbIdx - 1)
   111  		it.bitset ^= uint16(msb)
   112  		return key | uint64(it.bitmapIdx*16+int(msbIdx))
   113  	}
   114  	return 0
   115  }
   116  
   117  type ManyItr struct {
   118  	index int
   119  	arr   []uint64
   120  }
   121  
   122  // TODO: See if this is needed, we should remove this
   123  func (r *Bitmap) ManyIterator() *ManyItr {
   124  	return &ManyItr{
   125  		arr: r.ToArray(),
   126  	}
   127  
   128  }
   129  
   130  func (itr *ManyItr) NextMany(buf []uint64) int {
   131  	count := 0
   132  	for i := 0; i < len(buf); i++ {
   133  		if itr.index == len(itr.arr) {
   134  			break
   135  		}
   136  		buf[i] = itr.arr[itr.index]
   137  		itr.index++
   138  		count++
   139  	}
   140  	return count
   141  }