~pierrec/giox

ca3812d2755e57629649620f9cd43ef46fc9b3c4 — pierre 9 months ago 790e8d9
added internal/bitmap package

Signed-off-by: pierre <pierre.curto@gmail.com>
2 files changed, 101 insertions(+), 0 deletions(-)

A internal/bitmap/bitmap.go
A internal/bitmap/bitmap_test.go
A internal/bitmap/bitmap.go => internal/bitmap/bitmap.go +40 -0
@@ 0,0 1,40 @@
// Package bitmap implements a simple bitmap.
package bitmap

type Bitmap struct {
	data []uint64
	num  int
}

func (b *Bitmap) Set(idx int) {
	o, x := idx/64, idx%64
	if n := len(b.data); o >= n {
		b.data = append(b.data, make([]uint64, o-n+1)...)
	}
	if b.data[o]&(1<<x) == 0 {
		b.data[o] |= 1 << x
		b.num++
	}
}

func (b *Bitmap) Unset(idx int) {
	if o := idx / 64; o < len(b.data) {
		x := idx % 64
		if b.data[o]&(1<<x) > 0 {
			b.data[o] &^= 1 << x
			b.num--
		}
	}
}

func (b *Bitmap) Has(idx int) bool {
	if o := idx / 64; o < len(b.data) {
		x := idx % 64
		return b.data[o]&(1<<x) > 0
	}
	return false
}

func (b *Bitmap) Len() int {
	return b.num
}

A internal/bitmap/bitmap_test.go => internal/bitmap/bitmap_test.go +61 -0
@@ 0,0 1,61 @@
package bitmap

import (
	"fmt"
	"testing"
)

func _i(v ...int) []int { return v }

func dedup(s []int) []int {
	var ss []int
next:
	for _, x := range s {
		for _, xx := range ss {
			if x == xx {
				continue next
			}
		}
		ss = append(ss, x)
	}
	return ss
}

func TestBitmap(t *testing.T) {
	for _, tc := range []struct {
		in []int
	}{
		{},
		{in: _i(1, 2)},
		{in: _i(1, 20)},
		{in: _i(1, 128)},
		{in: _i(1, 140)},
		{in: _i(1, 128, 128, 140)},
	} {
		t.Run(fmt.Sprintf("%v", tc.in), func(t *testing.T) {
			var bm Bitmap
			for _, x := range tc.in {
				bm.Set(x)
			}

			in := dedup(tc.in)
			if got, want := bm.Len(), len(in); got != want {
				t.Fatalf("got %d; want %d", got, want)
			}

			for _, x := range in {
				if !bm.Has(x) {
					t.Errorf("%d missing", x)
				}
				bm.Unset(x)
				if bm.Has(x) {
					t.Errorf("%d not deleted", x)
				}
			}

			if bm.Len() != 0 {
				t.Errorf("non empty bitmap: %d", bm.Len())
			}
		})
	}
}