-
Notifications
You must be signed in to change notification settings - Fork 4
/
bitmap.go
120 lines (96 loc) · 1.95 KB
/
bitmap.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
package container
type Bitmap []uint32
func (b *Bitmap) Init(maxNum uint32) {
needLen := b.calcNeedSize(maxNum)
*b = make([]uint32, needLen)
}
func (b *Bitmap) Exists(item uint32) bool {
index := b.calcIndex(item)
if len(*b) < int(index+1) {
return false
}
offsetItem := b.calcPosition(item)
return ((*b)[index] & (1 << offsetItem)) > 0
}
func (b *Bitmap) Set(item uint32) bool {
index := b.calcIndex(item)
if len(*b) < int(index+1) {
b.Grow(item)
}
offsetItem := b.calcPosition(item)
(*b)[index] = (*b)[index] | (1 << offsetItem)
return true
}
func (b *Bitmap) Sets(items []uint32) {
if len(items) == 0 {
return
}
max := uint32(0)
for _, item := range items {
max = b.MaxU(max, item)
}
index := b.calcIndex(max)
if len(*b) < int(index+1) {
b.Grow(max)
}
for _, item := range items {
b.Set(item)
}
}
func (b *Bitmap) MaxU(x, y uint32) uint32 {
if x > y {
return x
}
return y
}
func (b *Bitmap) Min(x, y int) int {
if x < y {
return x
}
return y
}
func (b *Bitmap) Union(b2 *Bitmap) *Bitmap {
var maxData *Bitmap
if len(*b) > len(*b2) {
maxData = b.Clone()
} else {
maxData = b2.Clone()
}
minLen := b.Min(len(*b), len(*b2))
for i := 0; i < minLen; i++ {
(*maxData)[i] = (*b)[i] | (*b2)[i]
}
return maxData
}
func (b *Bitmap) Clone() *Bitmap {
bLen := len(*b)
copyBitmap := make([]uint32, bLen)
for i := 0; i < bLen; i++ {
copyBitmap[i] = (*b)[i]
}
bitmap := Bitmap(copyBitmap)
return &bitmap
}
func (b *Bitmap) Inverse() {
bLen := len(*b)
for i := 0; i < bLen; i++ {
(*b)[i] = ^(*b)[i]
}
}
func (b *Bitmap) Grow(item uint32) {
needLen := b.calcNeedSize(item)
dataLen := uint32(len(*b))
if dataLen < needLen {
newData := make([]uint32, needLen-dataLen)
*b = append(*b, newData...)
}
}
func (b *Bitmap) calcIndex(i uint32) uint32 {
return i >> 5
}
func (b *Bitmap) calcPosition(i uint32) uint32 {
return i & 0x1F
}
func (b *Bitmap) calcNeedSize(i uint32) uint32 {
return b.calcIndex(i) + 1
}