-
Notifications
You must be signed in to change notification settings - Fork 0
/
bitmap_8.go
173 lines (145 loc) · 3.06 KB
/
bitmap_8.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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
package bitmap
import (
"math/bits"
"strconv"
"strings"
)
type Bitmap8 []uint8
// Set set n-th bit to 1
func (b *Bitmap8) Set(n uint32) {
block, bit := n>>3, n%8
b.grow(block)
(*b)[block] |= (1 << bit)
}
// Remove set n-th bit to 0
func (b *Bitmap8) Remove(n uint32) {
block, bit := n>>3, n%8
if uint32(len(*b)) <= block {
return
}
(*b)[block] &= ^(1 << bit)
}
// Xor invert n-th bit
func (b *Bitmap8) Xor(n uint32) {
block, val := n>>3, n%8
b.grow(block)
(*b)[block] ^= (1 << val)
}
// IsEmpty check if the bitmap has any bit set to 1
func (b *Bitmap8) IsEmpty() bool {
for i := range *b {
if (*b)[i] > 0 {
return false
}
}
return true
}
// Has check if n-th bit is set to 1
func (b *Bitmap8) Has(n uint32) bool {
block, val := n>>3, n%8
if uint32(len(*b)) <= block {
return false
}
return (*b)[block]&(1<<val) > 0
}
// CountDiff count different bits in two bitmaps
func (b *Bitmap8) CountDiff(b2 Bitmap8) int {
diff := 0
max := len(*b)
if len(b2) > max {
max = len(b2)
}
for i := 0; i < max; i++ {
if len(b2) <= i {
diff += bits.OnesCount8((*b)[i])
continue
}
if len(*b) <= i {
diff += bits.OnesCount8((b2)[i])
continue
}
diff += bits.OnesCount8((*b)[i] ^ b2[i])
}
return diff
}
// Or in-place OR operation with another bitmap
func (b *Bitmap8) Or(b2 Bitmap8) {
b.grow(uint32(len(b2) - 1))
for i := 0; i < len(b2); i++ {
if b2[i] == 0 {
continue
}
(*b)[i] |= b2[i]
}
}
// And in-place And operation with another bitmap
func (b *Bitmap8) And(b2 Bitmap8) {
for i := 0; i < len(b2) && i < len(*b); i++ {
(*b)[i] &= b2[i]
}
}
// Shrink remove zero elements at the end of the map
func (b *Bitmap8) Shrink() {
shrinkedIndex := len(*b)
for i := len(*b) - 1; i >= 0; i-- {
if (*b)[i] != 0 {
shrinkedIndex = i + 1
break
}
}
if shrinkedIndex != len(*b) {
newSlice := make(Bitmap8, shrinkedIndex)
copy(newSlice, (*b)[:shrinkedIndex])
*b = newSlice
}
}
// Clone create a copy of the bitmap
func (b *Bitmap8) Clone() Bitmap8 {
clone := make(Bitmap8, len(*b))
copy(clone, *b)
return clone
}
// Range call the passed callback with all bits set to 1.
// If the callback returns false, the method exits
func (b *Bitmap8) Range(f func(n uint32) bool) {
for i, block := range *b {
for block != 0 {
tz := bits.TrailingZeros8(block)
bitIndex := uint32(i*8 + tz)
if !f(bitIndex) {
return
}
block &= block - 1
}
}
}
func (b *Bitmap8) String() string {
var sb strings.Builder
for i := range *b {
sb.WriteString(strconv.FormatUint(uint64((*b)[i]), 10))
if i != len(*b)-1 {
sb.WriteString("|")
}
}
return sb.String()
}
func FromString8(str string) (Bitmap8, error) {
if str == "" {
return Bitmap8{}, nil
}
nums := strings.Split(str, "|")
result := make(Bitmap8, 0, len(nums))
for _, num := range nums {
v, err := strconv.ParseUint(num, 10, 8)
if err != nil {
return nil, err
}
result = append(result, uint8(v))
}
return result, nil
}
func (b *Bitmap8) grow(length uint32) {
if length+1 > uint32(len(*b)) {
*b = append(*b, make(Bitmap8, length+1-uint32(len(*b)))...)
}
}