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

View File

@ -16,25 +16,18 @@ var (
type RLE struct { type RLE struct {
buf []byte buf []byte
changes []change
} }
type change struct { func FromBuf(buf []byte) (RLE, error) {
set bool rle := RLE{buf: buf}
reset bool
index uint64
}
func (c change) valid() bool {
return c.reset || c.set
}
func FromBuf(buf []byte) (*RLE, error) {
rle := &RLE{buf: buf}
if len(buf) > 0 && buf[0]&3 != Version { 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 return rle, nil
@ -45,7 +38,26 @@ func (rle *RLE) RunIterator() (RunIterator, error) {
return source, err 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 { if err != nil {
return nil, err return nil, err
} }

View File

@ -1,5 +1,11 @@
package rlepluslazy package rlepluslazy
import (
"math"
"golang.org/x/xerrors"
)
func Sum(a, b RunIterator) (RunIterator, error) { func Sum(a, b RunIterator) (RunIterator, error) {
it := addIt{a: a, b: b} it := addIt{a: a, b: b}
it.prep() it.prep()
@ -94,3 +100,21 @@ func (it *addIt) NextRun() (Run, error) {
next := it.next next := it.next
return next, it.prep() 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 N := 100
for i := 0; i < N; i++ { for i := 0; i < N; i++ {
abits := randomBits(1000, 2000) abits := randomBits(1000, 1500)
bbits := randomBits(1000, 2000) bbits := randomBits(1000, 1500)
sumbits := sum(abits, bbits) sumbits := sum(abits, bbits)
a, err := RunsFromSlice(abits) a, err := RunsFromSlice(abits)