diff --git a/setutil.go b/setutil.go index ec51cfc0..f290d460 100644 --- a/setutil.go +++ b/setutil.go @@ -296,21 +296,19 @@ func localintersect2by2( if (len(set1) == 0) || (len(set2) == 0) { return 0 } - k1 := 0 - k2 := 0 pos := 0 buffer = buffer[:cap(buffer)] - s1 := set1[k1] - s2 := set2[k2] + s1 := set1[0] + s2 := set2[0] mainwhile: for { if s2 < s1 { for { - k2++ - if k2 == len(set2) { + if len(set2) <= 1 { break mainwhile } - s2 = set2[k2] + set2 = set2[1:] + s2 = set2[0] if s2 >= s1 { break } @@ -318,29 +316,28 @@ mainwhile: } if s1 < s2 { for { - k1++ - if k1 == len(set1) { + if len(set1) <= 1 { break mainwhile } - s1 = set1[k1] + set1 = set1[1:] + s1 = set1[0] if s1 >= s2 { break } } } else { - // (set2[k2] == set1[k1]) buffer[pos] = s1 pos++ - k1++ - if k1 == len(set1) { + if len(set1) <= 1 { break } - s1 = set1[k1] - k2++ - if k2 == len(set2) { + set1 = set1[1:] + s1 = set1[0] + if len(set2) <= 1 { break } - s2 = set2[k2] + set2 = set2[1:] + s2 = set2[0] } } return pos @@ -354,20 +351,18 @@ func localintersect2by2Cardinality( if (len(set1) == 0) || (len(set2) == 0) { return 0 } - index1 := 0 - index2 := 0 pos := 0 - value1 := set1[index1] - value2 := set2[index2] + value1 := set1[0] + value2 := set2[0] mainwhile: for { if value2 < value1 { for { - index2++ - if index2 == len(set2) { + if len(set2) <= 1 { break mainwhile } - value2 = set2[index2] + set2 = set2[1:] + value2 = set2[0] if value2 >= value1 { break } @@ -375,28 +370,27 @@ mainwhile: } if value1 < value2 { for { - index1++ - if index1 == len(set1) { + if len(set1) <= 1 { break mainwhile } - value1 = set1[index1] + set1 = set1[1:] + value1 = set1[0] if value1 >= value2 { break } } } else { - // (set2[k2] == set1[k1]) pos++ - index1++ - if index1 == len(set1) { + if len(set1) <= 1 { break } - value1 = set1[index1] - index2++ - if index2 == len(set2) { + set1 = set1[1:] + value1 = set1[0] + if len(set2) <= 1 { break } - value2 = set2[index2] + set2 = set2[1:] + value2 = set2[0] } } return pos diff --git a/setutil_test.go b/setutil_test.go index 41275199..14da845d 100644 --- a/setutil_test.go +++ b/setutil_test.go @@ -390,3 +390,42 @@ func TestSetUtilUnionBy2Cardinality(t *testing.T) { }) } } + +func arrayIntersectionBenchmarkBitmaps() (*Bitmap, *Bitmap) { + left := New() + right := New() + for high := uint32(0); high < 4; high++ { + base := high << 16 + for low := uint32(0); low < 2*arrayDefaultMaxSize; low += 4 { + left.Add(base + low) + left.Add(base + low + 2) + right.Add(base + low) + right.Add(base + low + 1) + } + } + return left, right +} + +func BenchmarkArrayIntersection(b *testing.B) { + left, right := arrayIntersectionBenchmarkBitmaps() + var result *Bitmap + b.ReportAllocs() + for b.Loop() { + result = And(left, right) + } + if got, want := result.GetCardinality(), uint64(4*arrayDefaultMaxSize/2); got != want { + b.Fatalf("unexpected intersection cardinality: got %d, want %d", got, want) + } +} + +func BenchmarkArrayIntersectionCardinality(b *testing.B) { + left, right := arrayIntersectionBenchmarkBitmaps() + var result uint64 + b.ReportAllocs() + for b.Loop() { + result = left.AndCardinality(right) + } + if want := uint64(4 * arrayDefaultMaxSize / 2); result != want { + b.Fatalf("unexpected intersection cardinality: got %d, want %d", result, want) + } +}