-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbitvec.go
77 lines (67 loc) · 1.71 KB
/
bitvec.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// Package bitvec is bit-vector with atomic and non-atomic access
package bitvec
import (
"errors"
)
const (
nbits = 6 // 64 bits in a uint64
ws = 1 << nbits // constant 64
mask = ws - 1 // all ones
allSet = ^uint64(0)
)
func offset(k uint64) (bucket, bit uint64) {
return k >> nbits, 1 << (k & mask)
}
// BitVec is a nonatomic bit vector.
type BitVec struct {
buckets []uint64
capacity uint64
}
// New creates a non-atomic bitvector with a given size.
func New(size uint64) BitVec {
nints := size / ws
if size-(nints*ws) != 0 {
nints++
}
return BitVec{make([]uint64, nints), size}
}
// TrySet will try to set the bit and will return true if set
// is successful, false if bit is already set.
func (bv BitVec) TrySet(k uint64) bool {
if k >= bv.capacity {
return false
}
bucket, bit := offset(k)
old := bv.buckets[bucket]
if old&bit != 0 {
return false
}
bv.buckets[bucket] = old | bit
return true
}
// Get will return true if the bit is set; false otherwise.
func (bv BitVec) Get(k uint64) (bool, error) {
if k >= bv.capacity {
return false, errors.New("Attempt to access element beyond vector bounds")
}
bucket, bit := offset(k)
return bv.buckets[bucket]&bit != 0, nil
}
// Set sets bit `k` to true unconditionally.
func (bv BitVec) Set(k uint64) error {
if k >= bv.capacity {
return errors.New("Attempt to access element beyond vector bounds")
}
bucket, bit := offset(k)
bv.buckets[bucket] |= bit
return nil
}
// Clear sets bit `k` to false unconditionally.
func (bv BitVec) Clear(k uint64) error {
if k >= bv.capacity {
return errors.New("Attempt to access element beyond vector bounds")
}
bucket, bit := offset(k)
bv.buckets[bucket] &= (allSet ^ bit)
return nil
}