mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-10-11 05:17:54 +00:00
working
This commit is contained in:
parent
af3cb91a40
commit
30946a0372
2 changed files with 133 additions and 151 deletions
|
|
@ -406,9 +406,10 @@ func (b *Bitmap) Union(others ...*Bitmap) *Bitmap {
|
|||
// UnionInPlace returns the bitwise union of b and other, modifying
|
||||
// b in place.
|
||||
func (b *Bitmap) UnionInPlace(others ...*Bitmap) {
|
||||
for _, other := range others {
|
||||
b.unionIntoTarget(other, b)
|
||||
}
|
||||
b.unionIntoTarget(b, others...)
|
||||
// for _, other := range others {
|
||||
// b.unionIntoTarget(other, b)
|
||||
// }
|
||||
}
|
||||
|
||||
type wrapperIter struct {
|
||||
|
|
@ -421,17 +422,135 @@ type wrapperIter struct {
|
|||
// be left unchanged, but target will be modified in place. Used to share
|
||||
// the union logic between the copy-on-write and in-place functions.
|
||||
func (b *Bitmap) unionIntoTarget(target *Bitmap, others ...*Bitmap) {
|
||||
otherIters := make([]wrapperIter, 0, len(others))
|
||||
for _, other := range others {
|
||||
otherIter, _ := other.Containers.Iterator(0)
|
||||
fmt.Println("huh: ", len(others))
|
||||
otherIters := make([]wrapperIter, 0, len(others)+1)
|
||||
bIter, _ := b.Containers.Iterator(0)
|
||||
next := bIter.Next()
|
||||
if next {
|
||||
fmt.Println("Appending self")
|
||||
otherIters = append(otherIters, wrapperIter{
|
||||
iter: otherIter,
|
||||
iter: bIter,
|
||||
hasNext: true,
|
||||
handled: false,
|
||||
})
|
||||
}
|
||||
|
||||
for _, other := range others {
|
||||
otherIter, _ := other.Containers.Iterator(0)
|
||||
next := otherIter.Next()
|
||||
if next {
|
||||
otherIters = append(otherIters, wrapperIter{
|
||||
iter: otherIter,
|
||||
hasNext: true,
|
||||
handled: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Loop until we've exhausted every iter.
|
||||
for {
|
||||
hasNext := false
|
||||
hasNext := true
|
||||
fmt.Println(len(otherIters))
|
||||
for hasNext {
|
||||
// Loop until every iters current value has been handled.
|
||||
// for {
|
||||
for i, iIter := range otherIters {
|
||||
fmt.Println("copter")
|
||||
if !iIter.hasNext || iIter.handled {
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Println("here?")
|
||||
// Can store key-level statistics here
|
||||
iKey, iContainer := iIter.iter.Value()
|
||||
fmt.Println("iKey: ", iKey)
|
||||
fmt.Println("iContainer: ", iContainer)
|
||||
n := iContainer.n
|
||||
needsUnion := false
|
||||
hasMaxRange := iContainer.n == maxContainerVal+1
|
||||
for _, jIter := range otherIters[i:] {
|
||||
if hasMaxRange {
|
||||
continue
|
||||
}
|
||||
|
||||
// Calculate key-level statistics here
|
||||
jKey, jContainer := jIter.iter.Value()
|
||||
fmt.Println("jContainer.n: ", jContainer.n)
|
||||
|
||||
if iKey == jKey {
|
||||
needsUnion = true
|
||||
n += jContainer.n
|
||||
if !hasMaxRange {
|
||||
hasMaxRange = jContainer.n == maxContainerVal+1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !needsUnion {
|
||||
fmt.Println("Cloning")
|
||||
// TODO: Don't clone if sealed
|
||||
target.Containers.Put(iKey, iContainer.Clone())
|
||||
otherIters[i].handled = true
|
||||
continue
|
||||
}
|
||||
|
||||
// Need to union
|
||||
fmt.Println("ikey: ", iKey)
|
||||
if hasMaxRange {
|
||||
panic("maxRange")
|
||||
fmt.Println("maxRange")
|
||||
// Use the max range
|
||||
container := &Container{
|
||||
runs: []interval16{{start: 0, last: maxContainerVal}},
|
||||
containerType: containerRun,
|
||||
n: maxContainerVal + 1,
|
||||
}
|
||||
target.Containers.Put(iKey, container)
|
||||
} else {
|
||||
// TODO: Implement this
|
||||
// if n < ArrayMaxSize {
|
||||
// // Use an array
|
||||
// // container := &Container{
|
||||
// // containerType: containerArray,
|
||||
// // array: make([]uint16, 0, n),
|
||||
// // }
|
||||
// }
|
||||
// else {
|
||||
// Use a bitmap
|
||||
fmt.Println("bitmap")
|
||||
buf := make([]uint64, bitmapN)
|
||||
ob := buf[:bitmapN]
|
||||
container := &Container{
|
||||
bitmap: ob,
|
||||
n: 0,
|
||||
containerType: containerBitmap,
|
||||
}
|
||||
|
||||
for _, jIter := range otherIters {
|
||||
jKey, jContainer := jIter.iter.Value()
|
||||
|
||||
if iKey == jKey {
|
||||
if jContainer.isArray() {
|
||||
// panic("unionBitmapArrayInPlace")
|
||||
fmt.Println("array into bitmap")
|
||||
unionBitmapArrayInPlace(container, jContainer)
|
||||
fmt.Println("After union array: ", container.n)
|
||||
} else if jContainer.isRun() {
|
||||
// panic("unionBitmapRunInPlace")
|
||||
unionBitmapRunInPlace(container, jContainer)
|
||||
} else {
|
||||
fmt.Println("bitmap into bitmap")
|
||||
// panic("unionBitmapBitmapInPlace")
|
||||
unionBitmapBitmapInPlace(container, jContainer)
|
||||
fmt.Println("After union bitmap: ", container.n)
|
||||
}
|
||||
}
|
||||
}
|
||||
target.Containers.Put(iKey, container)
|
||||
}
|
||||
}
|
||||
// }
|
||||
|
||||
hasNext = false
|
||||
for i, otherIter := range otherIters {
|
||||
next := otherIter.iter.Next()
|
||||
otherIters[i].hasNext = next
|
||||
|
|
@ -445,149 +564,7 @@ func (b *Bitmap) unionIntoTarget(target *Bitmap, others ...*Bitmap) {
|
|||
// None of the iters had any more values, we're done.
|
||||
break
|
||||
}
|
||||
|
||||
// Loop until every iters current value has been handled.
|
||||
for {
|
||||
for i, iIter := range otherIters {
|
||||
if !iIter.hasNext || iIter.handled {
|
||||
continue
|
||||
}
|
||||
|
||||
// Can store key-level statistics here
|
||||
iKey, iContainer := iIter.iter.Value()
|
||||
n := iContainer.n
|
||||
needsUnion := false
|
||||
hasMaxRange := iContainer.n == maxContainerVal+1
|
||||
for _, jIter := range otherIters[i:] {
|
||||
if hasMaxRange {
|
||||
continue
|
||||
}
|
||||
|
||||
// Calculate key-level statistics here
|
||||
jKey, jContainer := jIter.iter.Value()
|
||||
|
||||
if iKey == jKey {
|
||||
needsUnion = true
|
||||
n += jContainer.n
|
||||
if !hasMaxRange {
|
||||
hasMaxRange = jContainer.n == maxContainerVal+1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !needsUnion {
|
||||
// TODO: Don't clone if sealed
|
||||
target.Containers.Put(iKey, iContainer.Clone())
|
||||
otherIters[i].handled = true
|
||||
continue
|
||||
}
|
||||
|
||||
// Need to union
|
||||
if hasMaxRange {
|
||||
// Use the max range
|
||||
container := &Container{
|
||||
runs: []interval16{{start: 0, last: maxContainerVal}},
|
||||
containerType: containerRun,
|
||||
n: maxContainerVal + 1,
|
||||
}
|
||||
target.Containers.Put(iKey, container)
|
||||
} else {
|
||||
// TODO: Implement this
|
||||
// if n < ArrayMaxSize {
|
||||
// // Use an array
|
||||
// // container := &Container{
|
||||
// // containerType: containerArray,
|
||||
// // array: make([]uint16, 0, n),
|
||||
// // }
|
||||
// }
|
||||
// else {
|
||||
// Use a bitmap
|
||||
buf := make([]uint64, bitmapN)
|
||||
ob := buf[:bitmapN]
|
||||
container := &Container{
|
||||
bitmap: ob,
|
||||
n: n,
|
||||
containerType: containerBitmap,
|
||||
}
|
||||
|
||||
for _, jIter := range otherIters {
|
||||
jKey, jContainer := jIter.iter.Value()
|
||||
|
||||
if iKey == jKey {
|
||||
if jContainer.isArray() {
|
||||
unionBitmapArrayInPlace(container, jContainer)
|
||||
} else if jContainer.isRun() {
|
||||
unionBitmapRunInPlace(container, jContainer)
|
||||
} else {
|
||||
unionBitmapBitmapInPlace(container, jContainer)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// iiter, _ := b.Containers.Iterator(0)
|
||||
// i := iiter.Next()
|
||||
// for i {
|
||||
// for _, otherIter := range otherIters {
|
||||
// jiter := otherIter
|
||||
// j := jiter.Next()
|
||||
// if !j {
|
||||
// continue
|
||||
// }
|
||||
|
||||
// ki, ci := iiter.Value()
|
||||
// kj, cj := jiter.Value()
|
||||
|
||||
// if i && (!j || ki < kj) {
|
||||
// // TODO: Don't clone if sealed
|
||||
// target.Containers.Put(ki, ci.Clone())
|
||||
// i = iiter.Next()
|
||||
// ki, ci = iiter.Value()
|
||||
// } else if j && (!i || ki > kj) {
|
||||
// // TODO: Don't clone if sealed
|
||||
// target.Containers.Put(kj, cj.Clone())
|
||||
// j = jiter.Next()
|
||||
// kj, cj = jiter.Value()
|
||||
// } else { // ki == kj
|
||||
// // TODO: unionIntoTarget?
|
||||
// target.Containers.Put(ki, union(ci, cj))
|
||||
// i, j = iiter.Next(), jiter.Next()
|
||||
// ki, ci = iiter.Value()
|
||||
// kj, cj = jiter.Value()
|
||||
// }
|
||||
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// for _, otherIter := range otherIters {
|
||||
// jiter := otherIter
|
||||
|
||||
// i, j := iiter.Next(), jiter.Next()
|
||||
// ki, ci := iiter.Value()
|
||||
// kj, cj := jiter.Value()
|
||||
// for i || j {
|
||||
// if i && (!j || ki < kj) {
|
||||
// // TODO: Don't clone if sealed
|
||||
// target.Containers.Put(ki, ci.Clone())
|
||||
// i = iiter.Next()
|
||||
// ki, ci = iiter.Value()
|
||||
// } else if j && (!i || ki > kj) {
|
||||
// // TODO: Don't clone if sealed
|
||||
// target.Containers.Put(kj, cj.Clone())
|
||||
// j = jiter.Next()
|
||||
// kj, cj = jiter.Value()
|
||||
// } else { // ki == kj
|
||||
// // TODO: unionIntoTarget?
|
||||
// target.Containers.Put(ki, union(ci, cj))
|
||||
// i, j = iiter.Next(), jiter.Next()
|
||||
// ki, ci = iiter.Value()
|
||||
// kj, cj = jiter.Value()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
// Difference returns the difference of b and other.
|
||||
|
|
@ -2714,6 +2691,7 @@ func unionBitmapArrayInPlace(a, b *Container) {
|
|||
if !a.bitmapContains(v) {
|
||||
a.bitmap[v/64] |= (1 << uint64(v%64))
|
||||
a.n++
|
||||
fmt.Println("added: ", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -411,10 +411,14 @@ func TestBitmap_UnionInPlace1(t *testing.T) {
|
|||
|
||||
result.UnionInPlace(bm0, bm1)
|
||||
if n := result.Count(); n != 2682675 {
|
||||
// for _, val := range result.Slice() {
|
||||
// fmt.Println(val)
|
||||
// }
|
||||
t.Fatalf("unexpected n: %d", n)
|
||||
}
|
||||
|
||||
bm := testBM()
|
||||
fmt.Println("bm.Count(): ", bm.Count())
|
||||
result = roaring.NewBitmap()
|
||||
result.UnionInPlace(bm, bm0)
|
||||
if n := result.Count(); n != 75009 {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue