Replace rleplus with rlepluslazy

License: MIT
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
This commit is contained in:
Jakub Sztandera 2019-12-07 15:47:36 +01:00
parent 353fef3ff6
commit 32a1940c57
No known key found for this signature in database
GPG Key ID: 9A9AF56F8B3879BA
4 changed files with 114 additions and 42 deletions

View File

@ -3,19 +3,24 @@ package types
import (
"fmt"
"io"
"sort"
"github.com/filecoin-project/lotus/extern/rleplus"
rlepluslazy "github.com/filecoin-project/lotus/lib/rlepluslazy"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
)
type BitField struct {
rle rlepluslazy.RLE
bits map[uint64]struct{}
}
func NewBitField() BitField {
return BitField{bits: make(map[uint64]struct{})}
rle, _ := rlepluslazy.FromBuf([]byte{})
return BitField{
rle: rle,
bits: make(map[uint64]struct{}),
}
}
func BitFieldFromSet(setBits []uint64) BitField {
@ -26,31 +31,59 @@ func BitFieldFromSet(setBits []uint64) BitField {
return res
}
func (bf BitField) sum() (rlepluslazy.RunIterator, error) {
if len(bf.bits) == 0 {
return bf.rle.RunIterator()
}
a, err := bf.rle.RunIterator()
if err != nil {
return nil, err
}
slc := make([]uint64, 0, len(bf.bits))
for b := range bf.bits {
slc = append(slc, b)
}
b, err := rlepluslazy.RunsFromSlice(slc)
if err != nil {
return nil, err
}
res, err := rlepluslazy.Sum(a, b)
if err != nil {
return nil, err
}
return res, nil
}
// Set ...s bit in the BitField
func (bf BitField) Set(bit uint64) {
bf.bits[bit] = struct{}{}
}
// Clear ...s bit in the BitField
func (bf BitField) Clear(bit uint64) {
delete(bf.bits, bit)
}
// Has checkes if bit is set in the BitField
func (bf BitField) Has(bit uint64) bool {
_, ok := bf.bits[bit]
return ok
func (bf BitField) Count() (uint64, error) {
s, err := bf.sum()
if err != nil {
return 0, err
}
return rlepluslazy.Count(s)
}
// All returns all set bits, in random order
func (bf BitField) All() []uint64 {
res := make([]uint64, 0, len(bf.bits))
for i := range bf.bits {
res = append(res, i)
func (bf BitField) All() ([]uint64, error) {
runs, err := bf.sum()
if err != nil {
return nil, err
}
sort.Slice(res, func(i, j int) bool { return res[i] < res[j] })
return res
res, err := rlepluslazy.SliceFromRuns(runs)
if err != nil {
return nil, err
}
return res, err
}
func (bf BitField) MarshalCBOR(w io.Writer) error {
@ -59,7 +92,12 @@ func (bf BitField) MarshalCBOR(w io.Writer) error {
ints = append(ints, i)
}
rle, _, err := rleplus.Encode(ints) // Encode sorts internally
s, err := bf.sum()
if err != nil {
return err
}
rle, err := rlepluslazy.EncodeRuns(s, []byte{})
if err != nil {
return err
}
@ -88,19 +126,17 @@ func (bf *BitField) UnmarshalCBOR(r io.Reader) error {
return fmt.Errorf("expected byte array")
}
rle := make([]byte, extra)
if _, err := io.ReadFull(br, rle); err != nil {
buf := make([]byte, extra)
if _, err := io.ReadFull(br, buf); err != nil {
return err
}
ints, err := rleplus.Decode(rle)
rle, err := rlepluslazy.FromBuf(buf)
if err != nil {
return xerrors.Errorf("could not decode rle+: %w", err)
}
bf.rle = rle
bf.bits = make(map[uint64]struct{})
for _, i := range ints {
bf.bits[i] = struct{}{}
}
return nil
}

View File

@ -16,25 +16,18 @@ var (
type RLE struct {
buf []byte
changes []change
}
type change struct {
set bool
reset bool
index uint64
}
func (c change) valid() bool {
return c.reset || c.set
}
func FromBuf(buf []byte) (*RLE, error) {
rle := &RLE{buf: buf}
func FromBuf(buf []byte) (RLE, error) {
rle := RLE{buf: buf}
if len(buf) > 0 && buf[0]&3 != Version {
return nil, xerrors.Errorf("could not create RLE+ for a buffer: %w", ErrWrongVersion)
return RLE{}, xerrors.Errorf("could not create RLE+ for a buffer: %w", ErrWrongVersion)
}
_, err := rle.Count()
if err != nil {
return RLE{}, err
}
return rle, nil
@ -45,7 +38,26 @@ func (rle *RLE) RunIterator() (RunIterator, error) {
return source, err
}
func (rle *RLE) Count() (uint64, error) {
it, err := rle.RunIterator()
if err != nil {
return 0, err
}
return Count(it)
}
/*
type change struct {
set bool
reset bool
index uint64
}
func (c change) valid() bool {
return c.reset || c.set
}
func (rle *RLE) RunIterator() (RunIterator, error) {
if err != nil {
return nil, err
}

View File

@ -1,5 +1,11 @@
package rlepluslazy
import (
"math"
"golang.org/x/xerrors"
)
func Sum(a, b RunIterator) (RunIterator, error) {
it := addIt{a: a, b: b}
it.prep()
@ -94,3 +100,21 @@ func (it *addIt) NextRun() (Run, error) {
next := it.next
return next, it.prep()
}
func Count(ri RunIterator) (uint64, error) {
var count uint64
for ri.HasNext() {
r, err := ri.NextRun()
if err != nil {
return 0, err
}
if r.Val {
if math.MaxUint64-r.Len > count {
return 0, xerrors.New("RLE+ overflows")
}
count += r.Len
}
}
return count, nil
}

View File

@ -76,8 +76,8 @@ func TestSumRandom(t *testing.T) {
N := 100
for i := 0; i < N; i++ {
abits := randomBits(1000, 2000)
bbits := randomBits(1000, 2000)
abits := randomBits(1000, 1500)
bbits := randomBits(1000, 1500)
sumbits := sum(abits, bbits)
a, err := RunsFromSlice(abits)