-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4ec8e4d
commit b57da1e
Showing
2 changed files
with
156 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package bitset | ||
|
||
const word = uint64(64) | ||
const logword = uint(6) | ||
|
||
type BitSet struct { | ||
length uint64 | ||
bits []uint64 | ||
} | ||
|
||
func getSize(length uint64) uint64 { | ||
return uint64((length + word - 1) / word) | ||
} | ||
|
||
func New(length uint64) *BitSet { | ||
size := getSize(length) | ||
return &BitSet{length, make([]uint64, size)} | ||
} | ||
|
||
func getIndex(pos uint64) (q uint64, r uint) { | ||
q = pos >> logword | ||
r = uint(pos & (word - 1)) | ||
return | ||
} | ||
|
||
func (b *BitSet) Length() uint64 { | ||
return b.length | ||
} | ||
|
||
func (b *BitSet) Get(pos uint64) bool { | ||
q, r := getIndex(pos) | ||
bit := (b.bits[q] >> r) & 1 | ||
return bit != 0 | ||
} | ||
|
||
func (b *BitSet) Set(pos uint64) bool { | ||
current := b.Get(pos) | ||
q, r := getIndex(pos) | ||
b.bits[q] |= (1 << r) | ||
return current | ||
} | ||
|
||
func (b *BitSet) Clear(pos uint64) bool { | ||
current := b.Get(pos) | ||
q, r := getIndex(pos) | ||
b.bits[q] &= ^(1 << r) | ||
return current | ||
} | ||
|
||
func (b *BitSet) Flip(pos uint64) bool { | ||
current := b.Get(pos) | ||
q, r := getIndex(pos) | ||
b.bits[q] ^= (1 << r) | ||
return current | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
package bitset | ||
|
||
import ( | ||
"testing" | ||
) | ||
|
||
func TestInit(t *testing.T) { | ||
bs := New(1000) | ||
// initially all bits should be zero | ||
for i := uint64(0); i < 1000; i++ { | ||
if bs.Get(i) { | ||
t.Errorf("Bit %d is set when it should not be", i) | ||
} | ||
} | ||
} | ||
|
||
func TestGetSet(t *testing.T) { | ||
bs := New(1000) | ||
if bs.Set(0) == true { | ||
t.Error("Set on bit %d returned true when it should return false", 0) | ||
} | ||
|
||
if bs.Get(0) == false { | ||
t.Errorf("Bit %d is not set when it should be", 0) | ||
} | ||
|
||
if bs.Set(0) == false { | ||
t.Errorf("Set on bit %d returned false when it should return true", 0) | ||
} | ||
} | ||
|
||
func TestLargeSetGet(t *testing.T) { | ||
size := uint64(1) << 35 | ||
bs := New(size) | ||
|
||
positions := []uint64{0, 1, 10, 1000, 1 << 32, size - 1} | ||
for _, position := range positions { | ||
if bs.Get(position) { | ||
t.Errorf("Bit %d should be false but is true", position) | ||
} | ||
|
||
bs.Set(position) | ||
|
||
if !bs.Get(position) { | ||
t.Errorf("Bit %d should be true but is false", position) | ||
} | ||
} | ||
} | ||
|
||
func TestLength(t *testing.T) { | ||
|
||
sizes := []uint64{0, 1, 10, 1000, 1 << 32, 1 << 33} | ||
for _, size := range sizes { | ||
bs := New(size) | ||
if bs.Length() != size { | ||
t.Errorf("Length should be %d", size) | ||
} | ||
} | ||
} | ||
|
||
func TestClear(t *testing.T) { | ||
bs := New(1000) | ||
pos := uint64(1) | ||
bs.Set(pos) | ||
|
||
if !bs.Get(pos) { | ||
t.Errorf("Bit %d should be set when it is not", pos) | ||
} | ||
|
||
if !bs.Clear(pos) { | ||
t.Error("Clearing bit %d should have returned true", pos) | ||
} | ||
|
||
if bs.Get(pos) { | ||
t.Errorf("Bit %d should have been cleared when it is not", pos) | ||
} | ||
} | ||
|
||
func TestFlip(t *testing.T) { | ||
bs := New(1000) | ||
pos := uint64(1) | ||
|
||
if bs.Get(pos) { | ||
t.Errorf("Bit %d should be clear when it is not", pos) | ||
} | ||
|
||
if bs.Flip(pos) { | ||
t.Error("Flipping bit %d should have returned false, but it did not", pos) | ||
} | ||
|
||
if !bs.Get(pos) { | ||
t.Errorf("Bit %d should have been set when it is not", pos) | ||
} | ||
if !bs.Flip(pos) { | ||
t.Error("Flipping bit %d should have returned true, but it did not", pos) | ||
} | ||
|
||
if bs.Get(pos) { | ||
t.Errorf("Bit %d should have been clear when it is not", pos) | ||
} | ||
} |