lotus/lib/rlepluslazy/runs.go

97 lines
1.5 KiB
Go
Raw Normal View History

package rlepluslazy
func Sum(a, b RunIterator) (RunIterator, error) {
it := addIt{a: a, b: b}
it.prep()
return &it, nil
}
type addIt struct {
a RunIterator
b RunIterator
next Run
arun Run
brun Run
}
func (it *addIt) prep() error {
var err error
fetch := func() error {
if !it.arun.Valid() && it.a.HasNext() {
it.arun, err = it.a.NextRun()
if err != nil {
return err
}
}
if !it.brun.Valid() && it.b.HasNext() {
it.brun, err = it.b.NextRun()
if err != nil {
return err
}
}
return nil
}
if err := fetch(); err != nil {
return err
}
// one is not valid
if !it.arun.Valid() {
it.next = it.brun
it.brun.Len = 0
return nil
}
if !it.brun.Valid() {
it.next = it.arun
it.arun.Len = 0
return nil
}
if !it.arun.Val && !it.brun.Val {
min := it.arun.Len
if it.brun.Len < min {
min = it.brun.Len
}
it.next = Run{Val: it.arun.Val, Len: min}
it.arun.Len -= it.next.Len
it.brun.Len -= it.next.Len
return nil
}
it.next = Run{Val: true}
// different vals, 'true' wins
for (it.arun.Val && it.arun.Valid()) || (it.brun.Val && it.brun.Valid()) {
min := it.arun.Len
if it.brun.Len < min && it.brun.Valid() || !it.arun.Valid() {
min = it.brun.Len
}
it.next.Len += min
if it.arun.Valid() {
it.arun.Len -= min
}
if it.brun.Valid() {
it.brun.Len -= min
}
if err := fetch(); err != nil {
return err
}
}
return nil
}
func (it *addIt) HasNext() bool {
return it.next.Valid()
}
func (it *addIt) NextRun() (Run, error) {
next := it.next
return next, it.prep()
}