-
Notifications
You must be signed in to change notification settings - Fork 79
/
bitfield.go
78 lines (69 loc) · 1.78 KB
/
bitfield.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
78
/*
Package bitfield provides a simple and efficient arbitrary size bit field implementation.
It doesn't attempt to cover everything that could be done with bit fields,
providing only things used by neo-go.
*/
package bitfield
// Field is a bit field represented as a slice of uint64 values.
type Field []uint64
// Bits and bytes count in a basic element of Field.
const elemBits = 64
// New creates a new bit field of the specified length. Actual field length
// can be rounded to the next multiple of 64, so it's a responsibility
// of the user to deal with that.
func New(n int) Field {
return make(Field, 1+(n-1)/elemBits)
}
// Set sets one bit at the specified offset. No bounds checking is done.
func (f Field) Set(i int) {
addr, offset := (i / elemBits), (i % elemBits)
f[addr] |= (1 << offset)
}
// IsSet returns true if the bit with the specified offset is set.
func (f Field) IsSet(i int) bool {
addr, offset := (i / elemBits), (i % elemBits)
return (f[addr] & (1 << offset)) != 0
}
// Copy makes a copy of the current Field.
func (f Field) Copy() Field {
fn := make(Field, len(f))
copy(fn, f)
return fn
}
// And implements logical AND between f's and m's bits saving the result into f.
func (f Field) And(m Field) {
l := len(m)
for i := range f {
if i >= l {
f[i] = 0
continue
}
f[i] &= m[i]
}
}
// Equals compares two Fields and returns true if they're equal.
func (f Field) Equals(o Field) bool {
if len(f) != len(o) {
return false
}
for i := range f {
if f[i] != o[i] {
return false
}
}
return true
}
// IsSubset returns true when f is a subset of o (only has bits set that are
// set in o).
func (f Field) IsSubset(o Field) bool {
if len(f) > len(o) {
return false
}
for i := range f {
r := f[i] & o[i]
if r != f[i] {
return false
}
}
return true
}