-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathquartileindex.go
137 lines (122 loc) · 2.95 KB
/
quartileindex.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
package k2tree
import "fmt"
type quartileIndex struct {
bits bitarray
offsets [3]int
counts [3]int
}
var _ bitarray = (*quartileIndex)(nil)
func newQuartileIndex(bits bitarray) *quartileIndex {
q := &quartileIndex{
bits: bits,
offsets: [3]int{
bits.Len() / 4,
bits.Len() / 2,
(bits.Len()/2 + bits.Len()/4),
},
}
q.counts[0] = bits.Count(0, q.offsets[0])
q.counts[1] = bits.Count(q.offsets[0], q.offsets[1]) + q.counts[1]
q.counts[2] = bits.Count(q.offsets[0], q.offsets[2]) + q.counts[2]
return q
}
// Len returns the number of bits in the bitarray.
func (q *quartileIndex) Len() int {
return q.bits.Len()
}
// Set sets the bit at an index `at` to the value `val`.
func (q *quartileIndex) Set(at int, val bool) {
cur := q.bits.Get(at)
if cur && val {
return
}
if !cur && !val {
return
}
q.bits.Set(at, val)
var delta int
if val {
delta = 1
} else {
delta = -1
}
for i, o := range q.offsets {
if at < o {
q.counts[i] += delta
}
}
}
// Get returns the value stored at `at`.
func (q *quartileIndex) Get(at int) bool {
return q.bits.Get(at)
}
// Count returns the number of set bits in the interval [from, to).
func (q *quartileIndex) Count(from int, to int) int {
if from == 0 {
return q.zeroCount(to)
}
return q.zeroCount(to) - q.zeroCount(from)
}
// zeroCount computes the count from zero to the given value.
func (q *quartileIndex) zeroCount(to int) int {
prevoff := 0
prevcount := 0
for i, off := range q.offsets {
if to < off {
if off-to < to-prevoff {
return q.counts[i] - q.bits.Count(to, off)
} else {
return q.bits.Count(prevoff, to) + prevcount
}
}
prevoff = off
prevcount = q.counts[i]
}
if q.bits.Len()-to < to-prevoff {
return q.bits.Total() - q.bits.Count(to, q.bits.Len())
} else {
return q.bits.Count(prevoff, to) + prevcount
}
}
// Total returns the total number of set bits.
func (q *quartileIndex) Total() int {
return q.bits.Total()
}
// Insert extends the bitarray by `n` bits. The bits are zeroed
// and start at index `at`. Example:
// Initial string: 11101
// Insert(3, 2)
// Resulting string: 11000101
func (q *quartileIndex) Insert(n int, at int) error {
if n%4 != 0 {
panic("can only extend by nibbles (multiples of 4)")
}
err := q.bits.Insert(n, at)
if err != nil {
return err
}
newlen := q.bits.Len()
for i := 0; i < 3; i++ {
q.adjust(i, n, at, (newlen * (i + 1) / 4))
}
return nil
}
func (q *quartileIndex) adjust(i, n, at, newi int) {
oldi := q.offsets[i]
assert(newi >= oldi, "Inserting shrunk the array?")
q.offsets[i] = newi
if (n + at) < oldi {
// Entire span below me, adjust for loss.
q.counts[i] -= q.bits.Count(newi, oldi+n)
} else if at >= oldi {
// Entire span above me, adjust for gain.
q.counts[i] += q.bits.Count(oldi, newi)
} else {
// Span intersects me.
// Stupid answer:
q.counts[i] = q.bits.Count(0, newi)
}
}
func (q *quartileIndex) debug() string {
return fmt.Sprintf("Quartile:\n internal: %s, %#v", q.bits.debug(), q)
}