Implement differenceRunRun and add difference test shells

This commit is contained in:
Alan Bernstein 2017-06-09 11:57:12 -05:00 • committed by Matt Jaffee
parent 7e9fc3953d
commit ff9d97e4be
2 changed files with 206 additions and 7 deletions

View file

@ -2321,24 +2321,90 @@ func differenceArrayArray(a, b *container) *container {
}
func differenceArrayRun(a, b *container) *container {
// TODO
return nil
// func (ac *arrayContainer) iandNotRun16(rc *runContainer16) container {
output := &container{array: make([]uint32, 0, a.n)}
// cardinality upper bound: card(A)
return output
}
func differenceRunArray(a, b *container) *container {
// TODO
return nil
output := &container{runs: make([]interval32, 0, a.n)}
return output
}
func differenceRunBitmap(a, b *container) *container {
// TODO
return nil
output := &container{runs: make([]interval32, 0, a.n)}
return output
}
func differenceBitmapRun(a, b *container) *container {
// TODO
return nil
output := &container{bitmap: make([]uint64, bitmapN)}
return output
}
func differenceRunRun(a, b *container) *container {
// TODO
return nil
// (rc *runContainer32) AndNotRunContainer32(b *runContainer32) *runContainer32 {
if a.n == 0 || b.n == 0 {
return a
}
apos := 0 // current a-run index
bpos := 0 // current b-run index
astart := a.runs[apos].start
alast := a.runs[apos].last
bstart := b.runs[bpos].start
blast := b.runs[bpos].last
alen := len(a.runs)
blen := len(b.runs)
output := &container{runs: make([]interval32, 0, alen+blen)} // TODO allocate max then truncate? or something else
// cardinality upper bound: sum of number of runs
// each B-run could split an A-run in two, up to len(b.runs) times
for apos < alen && bpos < blen {
switch {
case alast < bstart:
// current A-run entirely preceeds current B-run: keep full A-run, advance to next A-run
output.runs = append(output.runs, interval32{start: uint32(astart), last: uint32(alast)})
apos++
if apos < alen {
astart = a.runs[apos].start
alast = a.runs[apos].last
}
case blast < astart:
// current B-run entirely preceeds current A-run: advance to next B-run
bpos++
if bpos < blen {
bstart = b.runs[bpos].start
blast = b.runs[bpos].last
}
default:
// overlap
if astart < bstart {
output.runs = append(output.runs, interval32{start: uint32(astart), last: uint32(bstart - 1)})
}
if alast > blast {
astart = blast + 1
} else {
apos++
if apos < alen {
astart = a.runs[apos].start
alast = a.runs[apos].last
}
}
}
}
if apos < alen {
output.runs = append(output.runs, interval32{start: uint32(astart), last: uint32(alast)})
apos++
if apos < alen {
output.runs = append(output.runs, a.runs[apos:]...)
}
}
return output
}
func differenceArrayBitmap(a, b *container) *container {

View file

@ -1087,6 +1087,139 @@ func TestArrayCountRuns(t *testing.T) {
}
}
func TestDifferenceArrayRun(t *testing.T) {
a := &container{}
b := &container{}
tests := []struct {
array []uint32
runs []interval32
exp []uint32
}{
{
array: []uint32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12},
runs: []interval32{{start: 5, last: 10}},
exp: []uint32{0, 1, 2, 3, 4, 11, 12},
},
}
for i, test := range tests {
a.array = test.array
b.runs = test.runs
b.n = b.runCountRange(0, 100)
ret := differenceArrayRun(a, b)
if !reflect.DeepEqual(ret.array, test.exp) {
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.array)
}
}
}
func TestDifferenceRunArray(t *testing.T) {
a := &container{}
b := &container{}
tests := []struct {
runs []interval32
array []uint32
exp []interval32
}{
{
runs: []interval32{{start: 0, last: 12}},
array: []uint32{5, 6, 7, 8, 9, 10},
exp: []interval32{{start: 0, last: 4}, {start: 11, last: 12}},
},
}
for i, test := range tests {
a.runs = test.runs
a.n = a.runCountRange(0, 100)
b.array = test.array
ret := differenceRunArray(a, b)
if !reflect.DeepEqual(ret.array, test.exp) {
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.array)
}
}
}
func TestDifferenceRunBitmap(t *testing.T) {
a := &container{}
b := &container{bitmap: make([]uint64, bitmapN)}
tests := []struct {
runs []interval32
bitmap []uint64
exp []interval32
}{
{
runs: []interval32{{start: 0, last: 63}},
bitmap: []uint64{0x0000FFFF000000F0},
exp: []interval32{{start: 0, last: 3}, {start: 8, last: 31}, {start: 48, last: 63}},
},
}
for i, test := range tests {
a.runs = test.runs
a.n = a.runCountRange(0, 100)
for i, v := range test.bitmap {
b.bitmap[i] = v
}
ret := differenceRunBitmap(a, b)
if !reflect.DeepEqual(ret.runs, test.exp) {
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.runs)
}
}
}
func TestDifferenceBitmapRun(t *testing.T) {
a := &container{bitmap: make([]uint64, bitmapN)}
b := &container{}
tests := []struct {
bitmap []uint64
runs []interval32
exp []uint64
}{
{
bitmap: []uint64{0xFFFFFFFFFFFFFFFF},
runs: []interval32{{start: 4, last: 7}, {start: 32, last: 47}},
exp: []uint64{0xFFFF0000FFFFFF0F},
},
}
for i, test := range tests {
for i, v := range test.bitmap {
a.bitmap[i] = v
}
b.runs = test.runs
b.n = b.runCountRange(0, 100)
ret := differenceBitmapRun(a, b)
if !reflect.DeepEqual(ret.bitmap[:len(test.exp)], test.exp) {
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.bitmap[:len(test.exp)])
}
}
}
func TestDifferenceRunRun(t *testing.T) {
a := &container{}
b := &container{}
tests := []struct {
aruns []interval32
bruns []interval32
exp []interval32
}{
{
// this tests all six overlap combinations
// A [ ] [ ] [ ] [ ] [ ] [ ]
// B [ ] [ ] [ ] [ ] [ ] [ ]
aruns: []interval32{{start: 3, last: 6}, {start: 13, last: 16}, {start: 24, last: 26}, {start: 33, last: 38}, {start: 43, last: 46}, {start: 53, last: 56}},
bruns: []interval32{{start: 1, last: 8}, {start: 11, last: 14}, {start: 21, last: 23}, {start: 35, last: 37}, {start: 44, last: 48}, {start: 57, last: 59}},
exp: []interval32{{start: 15, last: 16}, {start: 24, last: 26}, {start: 33, last: 34}, {start: 38, last: 38}, {start: 43, last: 43}, {start: 53, last: 56}},
},
}
for i, test := range tests {
a.runs = test.aruns
a.n = a.runCountRange(0, 100)
b.runs = test.bruns
b.n = b.runCountRange(0, 100)
ret := differenceRunRun(a, b)
if !reflect.DeepEqual(ret.runs, test.exp) {
t.Fatalf("test #%v expected %v, but got %v", i, test.exp, ret.runs)
}
}
}
func TestWriteReadArray(t *testing.T) {
ca := &container{array: []uint32{1, 10, 100, 1000}, n: 4}
ba := &Bitmap{keys: []uint64{0}, containers: []*container{ca}}