mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-10-06 19:07:50 +00:00
The third attempt to implement unionRunRunInPlace
This commit is contained in:
parent
eddbb7d0b0
commit
443f2d8f7c
2 changed files with 333 additions and 545 deletions
|
|
@ -4726,116 +4726,186 @@ func unionRunRunInPlace(a, b *Container) *Container {
|
|||
return a
|
||||
}
|
||||
|
||||
// unionInterval16InPlace merges two slice of intervals in place (in a).
|
||||
// The main concept is to go value by value (instead of interval by interval)
|
||||
// and count `.start` and `.last` points.
|
||||
// If we get the `state == 0` it means we just built a new interval (`val`),
|
||||
// and we can set it in `a` at the possition `off`
|
||||
func unionInterval16InPlace(a, b []interval16) ([]interval16, int32) {
|
||||
n := int32(0)
|
||||
|
||||
an, bn := len(a), len(b)
|
||||
i, j, k := 0, 0, 0
|
||||
|
||||
var (
|
||||
// ai - index of a, aii - subindex (0: a[ai].start, 1: a[ai].last).
|
||||
ai, aii int = 0, 0
|
||||
|
||||
// bi - index of b, bii - subindex (0: b[bi].start, 1: b[bi].last).
|
||||
bi, bii int = 0, 0
|
||||
|
||||
// Offset of a - next available index to set.
|
||||
off int = 0
|
||||
// Value to set/append to a at off
|
||||
val interval16
|
||||
|
||||
// Current state - state equals 0 means we are clear (out of intervals)
|
||||
// When we start a new interval we add +1 when we get out of interval we add -1.
|
||||
state int
|
||||
|
||||
// subindex (ii) to state mapping
|
||||
// .start: [0] -> 1
|
||||
// .last: [1] -> -1
|
||||
iiMap = [2]int{1, -1}
|
||||
|
||||
// If fromB is equal 2 it means that both val.start and val.last come from b,
|
||||
// so we need to extend a, first
|
||||
fromB int8
|
||||
|
||||
// eval functions evaluates global state and value
|
||||
eval = func(arr [2]uint16, ii int, onlyB bool) {
|
||||
if state == 0 && ii == 0 {
|
||||
// we are clear and start a new interval
|
||||
val.start = arr[ii]
|
||||
if onlyB {
|
||||
fromB++
|
||||
}
|
||||
}
|
||||
|
||||
state += iiMap[ii]
|
||||
|
||||
if state == 0 {
|
||||
// we just got out of interval
|
||||
// ii == 1
|
||||
val.last = arr[ii]
|
||||
if onlyB {
|
||||
fromB++
|
||||
}
|
||||
}
|
||||
}
|
||||
// eval2 function is a special variant for eval function
|
||||
// it's only used when two interval endings are equal, e.g.:
|
||||
// a: ------------------|
|
||||
// b: -----------|
|
||||
// the most important part is to change the global for both endings
|
||||
// before we check if we're getting out of interval and start the new one.
|
||||
eval2 = func(arr [2]uint16, i1, i2 int) {
|
||||
if state == 0 && (i1 == 0 || i2 == 0) {
|
||||
// we are clear and start a new interval
|
||||
val.start = arr[i1]
|
||||
|
||||
}
|
||||
|
||||
state += iiMap[i1]
|
||||
state += iiMap[i2]
|
||||
|
||||
if state == 0 {
|
||||
// (i1 == 1 || i2 == 1)
|
||||
// we just got out of interval
|
||||
val.last = arr[i1]
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
for {
|
||||
var (
|
||||
v interval16
|
||||
local *interval16
|
||||
)
|
||||
// av, bv reflects a[ai] and b[bi] intervals as an array,
|
||||
// so we can internally iterate over values (points).
|
||||
var av, bv [2]uint16
|
||||
|
||||
if i < an && j < bn {
|
||||
if a[i].start <= b[j].start {
|
||||
v = a[i]
|
||||
i++
|
||||
} else {
|
||||
v = b[j]
|
||||
j++
|
||||
if ai < an && bi < bn {
|
||||
av[0], av[1] = a[ai].start, a[ai].last
|
||||
bv[0], bv[1] = b[bi].start, b[bi].last
|
||||
|
||||
if av[aii] < bv[bii] {
|
||||
// a: |-------------------
|
||||
// b: |-------------------
|
||||
|
||||
eval(av, aii, false)
|
||||
aii++
|
||||
} else if av[aii] == bv[bii] {
|
||||
// a: |-------------------
|
||||
// b: |-------------------
|
||||
// or
|
||||
// a: ------------------|
|
||||
// b: |-------------------
|
||||
// or
|
||||
// a: ------------------|
|
||||
// b: |------------|
|
||||
// ...
|
||||
|
||||
eval2(av, aii, bii)
|
||||
aii++
|
||||
bii++
|
||||
} else { // bv[bii] < av[aii]
|
||||
// a: |-------------------
|
||||
// b: |-------------------
|
||||
|
||||
eval(bv, bii, true)
|
||||
bii++
|
||||
}
|
||||
} else if ai < an { // only a left
|
||||
av[0], av[1] = a[ai].start, a[ai].last
|
||||
eval(av, aii, false)
|
||||
aii++
|
||||
} else if bi < bn { // only b left
|
||||
bv[0], bv[1] = b[bi].start, b[bi].last
|
||||
eval(bv, bii, false)
|
||||
bii++
|
||||
} else {
|
||||
if i < an {
|
||||
v = a[i]
|
||||
i++
|
||||
} else if j < bn {
|
||||
v = b[j]
|
||||
j++
|
||||
} else {
|
||||
break
|
||||
break
|
||||
}
|
||||
|
||||
if state == 0 {
|
||||
if fromB == 2 {
|
||||
// val.start and val.last come from b, so we need to extend a, first
|
||||
a = append(a, interval16{})
|
||||
copy(a[off+1:], a[off:])
|
||||
ai++
|
||||
an++
|
||||
}
|
||||
fromB = 0
|
||||
a, off = appendInterval16At(a, val, off)
|
||||
n += int32(val.last-val.start) + 1
|
||||
}
|
||||
|
||||
reeval:
|
||||
if k == an {
|
||||
// append what's left and try to optimize it later
|
||||
a = append(a, v)
|
||||
an++
|
||||
continue
|
||||
if aii == 2 {
|
||||
// move to the next a's interval
|
||||
aii = 0
|
||||
ai++
|
||||
}
|
||||
|
||||
// locally unioned interval
|
||||
if local == nil {
|
||||
local = &a[k]
|
||||
}
|
||||
|
||||
if v.last < local.start {
|
||||
// [---- v ----][---- local ----]
|
||||
// prepend v into a
|
||||
a = append(a, interval16{})
|
||||
copy(a[i+1:], a[i:])
|
||||
a[i] = v
|
||||
an++
|
||||
i++
|
||||
continue
|
||||
}
|
||||
|
||||
if v.start > local.last {
|
||||
// [---- local ----][---- v ----]
|
||||
|
||||
// check if we can optimize run and combine neighbours
|
||||
if int32(v.start-local.last) <= 1 {
|
||||
local.last = v.last
|
||||
continue
|
||||
}
|
||||
|
||||
// set already unioned interval and reevaluate v
|
||||
a[k] = *local
|
||||
k++
|
||||
n += int32(local.last-local.start) + 1
|
||||
local = &v
|
||||
goto reeval
|
||||
}
|
||||
|
||||
if v.start < local.start {
|
||||
if v.last >= local.start && v.last <= local.last {
|
||||
// [---- local ----]
|
||||
// [---- v ----]
|
||||
local.start = v.start
|
||||
} else if v.last > local.last {
|
||||
// [- local -]
|
||||
// [---- v ----]
|
||||
*local = v
|
||||
}
|
||||
} else if v.start <= local.last {
|
||||
if v.last <= local.last {
|
||||
// [---- local ----]
|
||||
// [-- v --]
|
||||
|
||||
// this assignment overwrites the first available position to set - a[k]
|
||||
// it's done to "swallow" many nested intervals, e.g.:
|
||||
// [a1] [a2] [a3] [a4]
|
||||
// [------ b ------]
|
||||
// will give us:
|
||||
// [ ----- a1 -----] [a4]
|
||||
a[k] = *local
|
||||
} else if v.last > local.last {
|
||||
// [---- local ----]
|
||||
// [---- v ----]
|
||||
local.last = v.last
|
||||
}
|
||||
if bii == 2 {
|
||||
// move to the next b's interval
|
||||
bii = 0
|
||||
bi++
|
||||
}
|
||||
}
|
||||
|
||||
if len(a) > 0 {
|
||||
// count the latest interval
|
||||
n += int32(a[k].last-a[k].start) + 1
|
||||
a = a[:k+1]
|
||||
a = a[:off]
|
||||
}
|
||||
return a, n
|
||||
}
|
||||
|
||||
// appendInterval16At appends or sets val in a at off position
|
||||
// The function returns modified a ([]interval16) and new offset (off)
|
||||
func appendInterval16At(a []interval16, val interval16, off int) ([]interval16, int) {
|
||||
|
||||
if off > 0 && int32(val.start)-int32(a[off-1].last) <= 1 {
|
||||
a[off-1].last = val.last
|
||||
return a, off
|
||||
}
|
||||
|
||||
if off == len(a) {
|
||||
a = append(a, val)
|
||||
off++
|
||||
return a, off
|
||||
}
|
||||
|
||||
a[off] = val
|
||||
off++
|
||||
|
||||
return a, off
|
||||
}
|
||||
|
||||
func difference(a, b *Container) *Container {
|
||||
if a.N() == 0 || b.N() == maxContainerVal+1 {
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -722,467 +722,185 @@ func TestUnionMixed(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestUnionInterval16InPlace(t *testing.T) {
|
||||
t.Run("single overlap", func(t *testing.T) {
|
||||
a := []interval16{interval16{1, 10}, interval16{21, 28}}
|
||||
b := []interval16{interval16{8, 12}}
|
||||
bb := make([]interval16, len(b))
|
||||
copy(bb, b)
|
||||
tests := []struct {
|
||||
name string
|
||||
a []interval16
|
||||
b []interval16
|
||||
expected []interval16
|
||||
expectedN int32
|
||||
}{
|
||||
{
|
||||
name: "firstBitUnset lastBitSet",
|
||||
a: []interval16{interval16{1, 10}},
|
||||
b: []interval16{interval16{10, 10}},
|
||||
expected: []interval16{interval16{1, 10}},
|
||||
expectedN: 10,
|
||||
},
|
||||
{
|
||||
name: "single overlap",
|
||||
a: []interval16{interval16{1, 10}, interval16{21, 28}},
|
||||
b: []interval16{interval16{8, 12}},
|
||||
expected: []interval16{interval16{1, 12}, interval16{21, 28}},
|
||||
expectedN: 20,
|
||||
},
|
||||
{
|
||||
name: "nested intervals",
|
||||
a: []interval16{interval16{3, 13}, interval16{17, 20}},
|
||||
b: []interval16{interval16{1, 4}, interval16{6, 7}, interval16{8, 9}, interval16{10, 11}, interval16{14, 17}},
|
||||
expected: []interval16{interval16{1, 20}},
|
||||
expectedN: 20,
|
||||
},
|
||||
{
|
||||
name: "no overlap",
|
||||
a: []interval16{interval16{3, 4}, interval16{7, 8}},
|
||||
b: []interval16{interval16{1, 2}, interval16{5, 6}, interval16{9, 10}},
|
||||
expected: []interval16{interval16{1, 10}},
|
||||
expectedN: 10,
|
||||
},
|
||||
{
|
||||
name: "b in a",
|
||||
a: []interval16{interval16{1, 10}},
|
||||
b: []interval16{interval16{5, 7}},
|
||||
expected: []interval16{interval16{1, 10}},
|
||||
expectedN: 10,
|
||||
},
|
||||
{
|
||||
name: "a eq b",
|
||||
a: []interval16{interval16{1, 10}},
|
||||
b: []interval16{interval16{1, 10}},
|
||||
expected: []interval16{interval16{1, 10}},
|
||||
expectedN: 10,
|
||||
},
|
||||
{
|
||||
name: "a in b",
|
||||
a: []interval16{interval16{5, 7}},
|
||||
b: []interval16{interval16{1, 10}},
|
||||
expected: []interval16{interval16{1, 10}},
|
||||
expectedN: 10,
|
||||
},
|
||||
{
|
||||
name: "a ahead b",
|
||||
a: []interval16{interval16{1, 2}, interval16{3, 4}, interval16{5, 7}},
|
||||
b: []interval16{interval16{10, 11}, interval16{12, 13}, interval16{14, 15}},
|
||||
expected: []interval16{interval16{1, 7}, interval16{10, 15}},
|
||||
expectedN: 13,
|
||||
},
|
||||
{
|
||||
name: "b ahead a",
|
||||
a: []interval16{interval16{10, 11}, interval16{12, 13}, interval16{14, 15}},
|
||||
b: []interval16{interval16{1, 2}, interval16{3, 4}, interval16{5, 7}},
|
||||
expected: []interval16{interval16{1, 7}, interval16{10, 15}},
|
||||
expectedN: 13,
|
||||
},
|
||||
{
|
||||
name: "empty a and b",
|
||||
a: []interval16{},
|
||||
b: []interval16{},
|
||||
expected: []interval16{},
|
||||
expectedN: 0,
|
||||
},
|
||||
{
|
||||
name: "empty a",
|
||||
a: []interval16{},
|
||||
b: []interval16{interval16{1, 2}, interval16{3, 4}, interval16{5, 7}},
|
||||
expected: []interval16{interval16{1, 7}},
|
||||
expectedN: 7,
|
||||
},
|
||||
{
|
||||
name: "empty b",
|
||||
a: []interval16{interval16{1, 2}, interval16{3, 4}, interval16{5, 7}},
|
||||
b: []interval16{},
|
||||
expected: []interval16{interval16{1, 7}},
|
||||
expectedN: 7,
|
||||
},
|
||||
{
|
||||
name: "single a",
|
||||
a: []interval16{interval16{1, 2}},
|
||||
b: []interval16{},
|
||||
expected: []interval16{interval16{1, 2}},
|
||||
expectedN: 2,
|
||||
},
|
||||
{
|
||||
name: "single b",
|
||||
a: []interval16{},
|
||||
b: []interval16{interval16{1, 2}},
|
||||
expected: []interval16{interval16{1, 2}},
|
||||
expectedN: 2,
|
||||
},
|
||||
{
|
||||
name: "single a single b",
|
||||
a: []interval16{interval16{3, 4}},
|
||||
b: []interval16{interval16{1, 2}},
|
||||
expected: []interval16{interval16{1, 4}},
|
||||
expectedN: 4,
|
||||
},
|
||||
{
|
||||
name: "oddBitsSet lastBitUnset",
|
||||
a: []interval16{interval16{1, 1}, interval16{3, 3}, interval16{5, 5}},
|
||||
b: []interval16{interval16{0, 4}},
|
||||
expected: []interval16{interval16{0, 5}},
|
||||
expectedN: 6,
|
||||
},
|
||||
{
|
||||
name: "all bits",
|
||||
a: []interval16{interval16{1, 1}, interval16{3, 3}, interval16{5, 5}},
|
||||
b: []interval16{interval16{0, 0}, interval16{2, 2}, interval16{4, 4}},
|
||||
expected: []interval16{interval16{0, 5}},
|
||||
expectedN: 6,
|
||||
},
|
||||
{
|
||||
name: "short a long b",
|
||||
a: []interval16{interval16{5, 5}, interval16{7, 7}, interval16{9, 10}, interval16{12, 12}, interval16{15, 17}, interval16{19, 20}},
|
||||
b: []interval16{interval16{1, 10}, interval16{12, 12}, interval16{14, 18}},
|
||||
expected: []interval16{interval16{1, 10}, interval16{12, 12}, interval16{14, 20}},
|
||||
expectedN: 18,
|
||||
},
|
||||
{
|
||||
name: "common endings",
|
||||
a: []interval16{interval16{1, 5}, interval16{15, 20}, interval16{25, 35}},
|
||||
b: []interval16{interval16{1, 10}, interval16{15, 20}, interval16{30, 35}},
|
||||
expected: []interval16{interval16{1, 10}, interval16{15, 20}, interval16{25, 35}},
|
||||
expectedN: 27,
|
||||
},
|
||||
{
|
||||
name: "common endings and overlap",
|
||||
a: []interval16{interval16{1, 5}, interval16{10, 15}},
|
||||
b: []interval16{interval16{5, 10}, interval16{12, 17}},
|
||||
expected: []interval16{interval16{1, 17}},
|
||||
expectedN: 17,
|
||||
},
|
||||
{
|
||||
name: "no common endings and overlap",
|
||||
a: []interval16{interval16{5, 10}, interval16{12, 17}},
|
||||
b: []interval16{interval16{0, 11}, interval16{15, 20}},
|
||||
expected: []interval16{interval16{0, 20}},
|
||||
expectedN: 21,
|
||||
},
|
||||
}
|
||||
|
||||
runs, n := unionInterval16InPlace(a, b)
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
bb := make([]interval16, len(tc.b))
|
||||
copy(bb, tc.b)
|
||||
|
||||
expected := []interval16{interval16{1, 12}, interval16{21, 28}}
|
||||
for i, v := range expected {
|
||||
if runs[i] != v {
|
||||
t.Fatalf("runs expected: %+v, got: %+v", expected, runs)
|
||||
runs, n := unionInterval16InPlace(tc.a, tc.b)
|
||||
|
||||
for i, v := range tc.expected {
|
||||
if runs[i] != v {
|
||||
t.Fatalf("runs expected: %+v, got: %+v", tc.expected, runs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const expectedN = 20
|
||||
if n != expectedN {
|
||||
t.Fatalf("N expected: %d, got: %d", expectedN, n)
|
||||
}
|
||||
|
||||
for i, v := range bb {
|
||||
if b[i] != v {
|
||||
t.Fatalf("b changed - runs expected: %+v, got: %+v", bb, b)
|
||||
if n != tc.expectedN {
|
||||
t.Fatalf("N expected: %d, got: %d", tc.expectedN, n)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("nested intervals", func(t *testing.T) {
|
||||
a := []interval16{interval16{3, 13}, interval16{17, 20}}
|
||||
b := []interval16{interval16{1, 4}, interval16{6, 7}, interval16{8, 9}, interval16{10, 11}, interval16{14, 17}}
|
||||
bb := make([]interval16, len(b))
|
||||
copy(bb, b)
|
||||
|
||||
runs, n := unionInterval16InPlace(a, b)
|
||||
|
||||
expected := []interval16{interval16{1, 20}}
|
||||
for i, v := range expected {
|
||||
if runs[i] != v {
|
||||
t.Fatalf("runs expected: %+v, got: %+v", expected, runs)
|
||||
for i, v := range bb {
|
||||
if tc.b[i] != v {
|
||||
t.Fatalf("b changed - runs expected: %+v, got: %+v", bb, tc.b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const expectedN = 20
|
||||
if n != expectedN {
|
||||
t.Fatalf("N expected: %d, got: %d", expectedN, n)
|
||||
}
|
||||
|
||||
for i, v := range bb {
|
||||
if b[i] != v {
|
||||
t.Fatalf("b changed - runs expected: %+v, got: %+v", bb, b)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("no overlap", func(t *testing.T) {
|
||||
a := []interval16{interval16{3, 4}, interval16{7, 8}}
|
||||
b := []interval16{interval16{1, 2}, interval16{5, 6}, interval16{9, 10}}
|
||||
bb := make([]interval16, len(b))
|
||||
copy(bb, b)
|
||||
|
||||
runs, n := unionInterval16InPlace(a, b)
|
||||
|
||||
expected := []interval16{interval16{1, 10}}
|
||||
for i, v := range expected {
|
||||
if runs[i] != v {
|
||||
t.Fatalf("runs expected: %+v, got: %+v", expected, runs)
|
||||
}
|
||||
}
|
||||
|
||||
const expectedN = 10
|
||||
if n != expectedN {
|
||||
t.Fatalf("N expected: %d, got: %d", expectedN, n)
|
||||
}
|
||||
|
||||
for i, v := range bb {
|
||||
if b[i] != v {
|
||||
t.Fatalf("b changed - runs expected: %+v, got: %+v", bb, b)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("b in a", func(t *testing.T) {
|
||||
a := []interval16{interval16{1, 10}}
|
||||
b := []interval16{interval16{5, 7}}
|
||||
bb := make([]interval16, len(b))
|
||||
copy(bb, b)
|
||||
|
||||
runs, n := unionInterval16InPlace(a, b)
|
||||
|
||||
expected := []interval16{interval16{1, 10}}
|
||||
for i, v := range expected {
|
||||
if runs[i] != v {
|
||||
t.Fatalf("runs expected: %+v, got: %+v", expected, runs)
|
||||
}
|
||||
}
|
||||
|
||||
const expectedN = 10
|
||||
if n != expectedN {
|
||||
t.Fatalf("N expected: %d, got: %d", expectedN, n)
|
||||
}
|
||||
|
||||
for i, v := range bb {
|
||||
if b[i] != v {
|
||||
t.Fatalf("b changed - runs expected: %+v, got: %+v", bb, b)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("a eq b", func(t *testing.T) {
|
||||
a := []interval16{interval16{1, 10}}
|
||||
b := []interval16{interval16{1, 10}}
|
||||
bb := make([]interval16, len(b))
|
||||
copy(bb, b)
|
||||
|
||||
runs, n := unionInterval16InPlace(a, b)
|
||||
|
||||
expected := []interval16{interval16{1, 10}}
|
||||
for i, v := range expected {
|
||||
if runs[i] != v {
|
||||
t.Fatalf("runs expected: %+v, got: %+v", expected, runs)
|
||||
}
|
||||
}
|
||||
|
||||
const expectedN = 10
|
||||
if n != expectedN {
|
||||
t.Fatalf("N expected: %d, got: %d", expectedN, n)
|
||||
}
|
||||
|
||||
for i, v := range bb {
|
||||
if b[i] != v {
|
||||
t.Fatalf("b changed - runs expected: %+v, got: %+v", bb, b)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("a in b", func(t *testing.T) {
|
||||
a := []interval16{interval16{5, 7}}
|
||||
b := []interval16{interval16{1, 10}}
|
||||
bb := make([]interval16, len(b))
|
||||
copy(bb, b)
|
||||
|
||||
runs, n := unionInterval16InPlace(a, b)
|
||||
|
||||
expected := []interval16{interval16{1, 10}}
|
||||
for i, v := range expected {
|
||||
if runs[i] != v {
|
||||
t.Fatalf("runs expected: %+v, got: %+v", expected, runs)
|
||||
}
|
||||
}
|
||||
|
||||
const expectedN = 10
|
||||
if n != expectedN {
|
||||
t.Fatalf("N expected: %d, got: %d", expectedN, n)
|
||||
}
|
||||
|
||||
for i, v := range bb {
|
||||
if b[i] != v {
|
||||
t.Fatalf("b changed - runs expected: %+v, got: %+v", bb, b)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("a ahead b", func(t *testing.T) {
|
||||
a := []interval16{interval16{1, 2}, interval16{3, 4}, interval16{5, 7}}
|
||||
b := []interval16{interval16{10, 11}, interval16{12, 13}, interval16{14, 15}}
|
||||
bb := make([]interval16, len(b))
|
||||
copy(bb, b)
|
||||
|
||||
runs, n := unionInterval16InPlace(a, b)
|
||||
|
||||
expected := []interval16{
|
||||
interval16{1, 7},
|
||||
interval16{10, 15},
|
||||
}
|
||||
for i, v := range expected {
|
||||
if runs[i] != v {
|
||||
t.Fatalf("runs expected: %+v, got: %+v", expected, runs)
|
||||
}
|
||||
}
|
||||
|
||||
const expectedN = 13
|
||||
if n != expectedN {
|
||||
t.Fatalf("N expected: %d, got: %d", expectedN, n)
|
||||
}
|
||||
|
||||
for i, v := range bb {
|
||||
if b[i] != v {
|
||||
t.Fatalf("b changed - runs expected: %+v, got: %+v", bb, b)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("b ahead a", func(t *testing.T) {
|
||||
a := []interval16{interval16{10, 11}, interval16{12, 13}, interval16{14, 15}}
|
||||
b := []interval16{interval16{1, 2}, interval16{3, 4}, interval16{5, 7}}
|
||||
bb := make([]interval16, len(b))
|
||||
copy(bb, b)
|
||||
|
||||
runs, n := unionInterval16InPlace(a, b)
|
||||
|
||||
expected := []interval16{
|
||||
interval16{1, 7},
|
||||
interval16{10, 15},
|
||||
}
|
||||
for i, v := range expected {
|
||||
if runs[i] != v {
|
||||
t.Fatalf("runs expected: %+v, got: %+v", expected, runs)
|
||||
}
|
||||
}
|
||||
|
||||
const expectedN = 13
|
||||
if n != expectedN {
|
||||
t.Fatalf("N expected: %d, got: %d", expectedN, n)
|
||||
}
|
||||
|
||||
for i, v := range bb {
|
||||
if b[i] != v {
|
||||
t.Fatalf("b changed - runs expected: %+v, got: %+v", bb, b)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("empty a and b", func(t *testing.T) {
|
||||
a := []interval16{}
|
||||
b := []interval16{}
|
||||
bb := make([]interval16, len(b))
|
||||
copy(bb, b)
|
||||
|
||||
runs, n := unionInterval16InPlace(a, b)
|
||||
|
||||
expected := []interval16{}
|
||||
for i, v := range expected {
|
||||
if runs[i] != v {
|
||||
t.Fatalf("runs expected: %+v, got: %+v", expected, runs)
|
||||
}
|
||||
}
|
||||
|
||||
const expectedN = 0
|
||||
if n != expectedN {
|
||||
t.Fatalf("N expected: %d, got: %d", expectedN, n)
|
||||
}
|
||||
|
||||
for i, v := range bb {
|
||||
if b[i] != v {
|
||||
t.Fatalf("b changed - runs expected: %+v, got: %+v", bb, b)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("empty a", func(t *testing.T) {
|
||||
a := []interval16{}
|
||||
b := []interval16{interval16{1, 2}, interval16{3, 4}, interval16{5, 7}}
|
||||
bb := make([]interval16, len(b))
|
||||
copy(bb, b)
|
||||
|
||||
runs, n := unionInterval16InPlace(a, b)
|
||||
|
||||
expected := []interval16{interval16{1, 7}}
|
||||
for i, v := range expected {
|
||||
if runs[i] != v {
|
||||
t.Fatalf("runs expected: %+v, got: %+v", expected, runs)
|
||||
}
|
||||
}
|
||||
|
||||
const expectedN = 7
|
||||
if n != expectedN {
|
||||
t.Fatalf("N expected: %d, got: %d", expectedN, n)
|
||||
}
|
||||
|
||||
for i, v := range bb {
|
||||
if b[i] != v {
|
||||
t.Fatalf("b changed - runs expected: %+v, got: %+v", bb, b)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("empty b", func(t *testing.T) {
|
||||
a := []interval16{interval16{1, 2}, interval16{3, 4}, interval16{5, 7}}
|
||||
b := []interval16{}
|
||||
bb := make([]interval16, len(b))
|
||||
copy(bb, b)
|
||||
|
||||
runs, n := unionInterval16InPlace(a, b)
|
||||
|
||||
expected := []interval16{interval16{1, 7}}
|
||||
for i, v := range expected {
|
||||
if runs[i] != v {
|
||||
t.Fatalf("runs expected: %+v, got: %+v", expected, runs)
|
||||
}
|
||||
}
|
||||
|
||||
const expectedN = 7
|
||||
if n != expectedN {
|
||||
t.Fatalf("N expected: %d, got: %d", expectedN, n)
|
||||
}
|
||||
|
||||
for i, v := range bb {
|
||||
if b[i] != v {
|
||||
t.Fatalf("b changed - runs expected: %+v, got: %+v", bb, b)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("single a", func(t *testing.T) {
|
||||
a := []interval16{interval16{1, 2}}
|
||||
b := []interval16{}
|
||||
bb := make([]interval16, len(b))
|
||||
copy(bb, b)
|
||||
|
||||
runs, n := unionInterval16InPlace(a, b)
|
||||
|
||||
expected := []interval16{interval16{1, 2}}
|
||||
for i, v := range expected {
|
||||
if runs[i] != v {
|
||||
t.Fatalf("runs expected: %+v, got: %+v", expected, runs)
|
||||
}
|
||||
}
|
||||
|
||||
const expectedN = 2
|
||||
if n != expectedN {
|
||||
t.Fatalf("N expected: %d, got: %d", expectedN, n)
|
||||
}
|
||||
|
||||
for i, v := range bb {
|
||||
if b[i] != v {
|
||||
t.Fatalf("b changed - runs expected: %+v, got: %+v", bb, b)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("single b", func(t *testing.T) {
|
||||
a := []interval16{}
|
||||
b := []interval16{interval16{1, 2}}
|
||||
bb := make([]interval16, len(b))
|
||||
copy(bb, b)
|
||||
|
||||
runs, n := unionInterval16InPlace(a, b)
|
||||
|
||||
expected := []interval16{interval16{1, 2}}
|
||||
for i, v := range expected {
|
||||
if runs[i] != v {
|
||||
t.Fatalf("runs expected: %+v, got: %+v", expected, runs)
|
||||
}
|
||||
}
|
||||
|
||||
const expectedN = 2
|
||||
if n != expectedN {
|
||||
t.Fatalf("N expected: %d, got: %d", expectedN, n)
|
||||
}
|
||||
|
||||
for i, v := range bb {
|
||||
if b[i] != v {
|
||||
t.Fatalf("b changed - runs expected: %+v, got: %+v", bb, b)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("single a single b", func(t *testing.T) {
|
||||
a := []interval16{interval16{3, 4}}
|
||||
b := []interval16{interval16{1, 2}}
|
||||
bb := make([]interval16, len(b))
|
||||
copy(bb, b)
|
||||
|
||||
runs, n := unionInterval16InPlace(a, b)
|
||||
|
||||
expected := []interval16{interval16{1, 4}}
|
||||
for i, v := range expected {
|
||||
if runs[i] != v {
|
||||
t.Fatalf("runs expected: %+v, got: %+v", expected, runs)
|
||||
}
|
||||
}
|
||||
|
||||
const expectedN = 4
|
||||
if n != expectedN {
|
||||
t.Fatalf("N expected: %d, got: %d", expectedN, n)
|
||||
}
|
||||
|
||||
for i, v := range bb {
|
||||
if b[i] != v {
|
||||
t.Fatalf("b changed - runs expected: %+v, got: %+v", bb, b)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("oddBitsSet lastBitUnset", func(t *testing.T) {
|
||||
a := []interval16{interval16{1, 1}, interval16{3, 3}, interval16{5, 5}}
|
||||
b := []interval16{interval16{0, 4}}
|
||||
bb := make([]interval16, len(b))
|
||||
copy(bb, b)
|
||||
|
||||
runs, n := unionInterval16InPlace(a, b)
|
||||
|
||||
expected := []interval16{interval16{0, 5}}
|
||||
for i, v := range expected {
|
||||
if runs[i] != v {
|
||||
t.Fatalf("runs expected: %+v, got: %+v", expected, runs)
|
||||
}
|
||||
}
|
||||
const expectedN = 6
|
||||
if n != expectedN {
|
||||
t.Fatalf("N expected: %d, got: %d", expectedN, n)
|
||||
}
|
||||
|
||||
for i, v := range bb {
|
||||
if b[i] != v {
|
||||
t.Fatalf("b changed - runs expected: %+v, got: %+v", bb, b)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("all bits", func(t *testing.T) {
|
||||
a := []interval16{interval16{1, 1}, interval16{3, 3}, interval16{5, 5}}
|
||||
b := []interval16{interval16{0, 0}, interval16{2, 2}, interval16{4, 4}}
|
||||
bb := make([]interval16, len(b))
|
||||
copy(bb, b)
|
||||
|
||||
runs, n := unionInterval16InPlace(a, b)
|
||||
|
||||
expected := []interval16{interval16{0, 5}}
|
||||
for i, v := range expected {
|
||||
if runs[i] != v {
|
||||
t.Fatalf("runs expected: %+v, got: %+v", expected, runs)
|
||||
}
|
||||
}
|
||||
const expectedN = 6
|
||||
if n != expectedN {
|
||||
t.Fatalf("N expected: %d, got: %d", expectedN, n)
|
||||
}
|
||||
|
||||
for i, v := range bb {
|
||||
if b[i] != v {
|
||||
t.Fatalf("b changed - runs expected: %+v, got: %+v", bb, b)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("short a long b", func(t *testing.T) {
|
||||
a := []interval16{interval16{5, 5}, interval16{7, 7}, interval16{9, 10}, interval16{12, 12}, interval16{15, 17}, interval16{19, 20}}
|
||||
b := []interval16{interval16{1, 10}, interval16{12, 12}, interval16{14, 18}}
|
||||
bb := make([]interval16, len(b))
|
||||
copy(bb, b)
|
||||
|
||||
runs, n := unionInterval16InPlace(a, b)
|
||||
|
||||
expected := []interval16{interval16{1, 10}, interval16{12, 12}, interval16{14, 20}}
|
||||
for i, v := range expected {
|
||||
if runs[i] != v {
|
||||
t.Fatalf("runs expected: %+v, got: %+v", expected, runs)
|
||||
}
|
||||
}
|
||||
const expectedN = 18
|
||||
if n != expectedN {
|
||||
t.Fatalf("N expected: %d, got: %d", expectedN, n)
|
||||
}
|
||||
|
||||
for i, v := range bb {
|
||||
if b[i] != v {
|
||||
t.Fatalf("b changed - runs expected: %+v, got: %+v", bb, b)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntersectMixed(t *testing.T) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue