...
1 package bitpack
2
3 import (
4 "math"
5 )
6
7
8
9 type OffsetArray interface {
10
11
12
13 Index(i int) uint64
14
15
16
17 Len() int
18 }
19
20
21
22
23 func OffsetArrayLen(array OffsetArray) int {
24 if array != nil {
25 return array.Len()
26 }
27 return 0
28 }
29
30
31
32
33
34
35
36
37
38
39
40
41 func NewOffsetArray(values []uint64) OffsetArray {
42 if len(values) == 0 {
43 return emptyOffsetArray{}
44 }
45 if len(values) <= smallOffsetArrayCapacity {
46 return newSmallOffsetArray(values)
47 }
48
49 maxDelta := uint64(0)
50 lastValue := values[0]
51
52
53 for _, value := range values[1:] {
54 if delta := value - lastValue; delta > maxDelta {
55 maxDelta = delta
56 }
57 lastValue = value
58 }
59
60 switch {
61 case maxDelta > math.MaxUint32:
62 return newOffsetArray(values)
63 case maxDelta > math.MaxUint16:
64 return newDeltaArray[uint32](values)
65 case maxDelta > math.MaxUint8:
66 return newDeltaArray[uint16](values)
67 case maxDelta > 15:
68 return newDeltaArray[uint8](values)
69 default:
70 return newDeltaArrayUint4(values)
71 }
72 }
73
74 type offsetArray struct {
75 values []uint64
76 }
77
78 func newOffsetArray(values []uint64) *offsetArray {
79 a := &offsetArray{
80 values: make([]uint64, len(values)),
81 }
82 copy(a.values, values)
83 return a
84 }
85
86 func (a *offsetArray) Index(i int) uint64 {
87 return a.values[i]
88 }
89
90 func (a *offsetArray) Len() int {
91 return len(a.values)
92 }
93
94 type emptyOffsetArray struct{}
95
96 func (emptyOffsetArray) Index(int) uint64 {
97 panic("index out of bounds")
98 }
99
100 func (emptyOffsetArray) Len() int {
101 return 0
102 }
103
104 const smallOffsetArrayCapacity = 7
105
106 type smallOffsetArray struct {
107 length int
108 values [smallOffsetArrayCapacity]uint64
109 }
110
111 func newSmallOffsetArray(values []uint64) *smallOffsetArray {
112 a := &smallOffsetArray{length: len(values)}
113 copy(a.values[:], values)
114 return a
115 }
116
117 func (a *smallOffsetArray) Index(i int) uint64 {
118 if i < 0 || i >= a.length {
119 panic("index out of bounds")
120 }
121 return a.values[i]
122 }
123
124 func (a *smallOffsetArray) Len() int {
125 return a.length
126 }
127
128 type uintType interface {
129 uint8 | uint16 | uint32 | uint64
130 }
131
132 type deltaArray[T uintType] struct {
133 deltas []T
134 firstValue uint64
135 }
136
137 func newDeltaArray[T uintType](values []uint64) *deltaArray[T] {
138 a := &deltaArray[T]{
139 deltas: make([]T, len(values)-1),
140 firstValue: values[0],
141 }
142 lastValue := values[0]
143 for i, value := range values[1:] {
144 a.deltas[i] = T(value - lastValue)
145 lastValue = value
146 }
147 return a
148 }
149
150 func (a *deltaArray[T]) Index(i int) uint64 {
151 if i < 0 || i >= a.Len() {
152 panic("index out of bounds")
153 }
154 value := a.firstValue
155
156
157 for _, delta := range a.deltas[:i] {
158 value += uint64(delta)
159 }
160 return value
161 }
162
163 func (a *deltaArray[T]) Len() int {
164 return len(a.deltas) + 1
165 }
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180 type deltaArrayUint4 struct {
181 deltas []byte
182 numValues int
183 firstValue uint64
184 }
185
186 func newDeltaArrayUint4(values []uint64) *deltaArrayUint4 {
187 a := &deltaArrayUint4{
188 deltas: make([]byte, len(values)/2+1),
189 numValues: len(values),
190 firstValue: values[0],
191 }
192 lastValue := values[0]
193 for i, value := range values[1:] {
194 a.assign(i, value-lastValue)
195 lastValue = value
196 }
197 return a
198 }
199
200 func (a *deltaArrayUint4) assign(i int, v uint64) {
201 index, shift := uint(i)>>1, 4*(uint(i)&1)
202 a.deltas[index] &= ^(0xF << shift)
203 a.deltas[index] |= byte(v) << shift
204 }
205
206 func (a *deltaArrayUint4) index(i int) uint64 {
207 index, shift := uint(i)>>1, 4*(uint(i)&1)
208 return uint64((a.deltas[index] >> shift) & 0xF)
209 }
210
211 func (a *deltaArrayUint4) Index(i int) uint64 {
212 if i < 0 || i >= a.Len() {
213 panic("index out of bounds")
214 }
215 value := a.firstValue
216 for j := 0; j < i; j++ {
217 value += a.index(j)
218 }
219 return value
220 }
221
222 func (a *deltaArrayUint4) Len() int {
223 return a.numValues
224 }
225
View as plain text