1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package bitutils_test
18
19 import (
20 "testing"
21
22 "github.com/apache/arrow/go/v15/arrow/bitutil"
23 "github.com/apache/arrow/go/v15/arrow/memory"
24 "github.com/apache/arrow/go/v15/internal/bitutils"
25 "github.com/stretchr/testify/assert"
26 "golang.org/x/exp/rand"
27 )
28
29 const kWordSize = 64
30
31 func create(nbytes, offset, length int64) (*memory.Buffer, *bitutils.BitBlockCounter) {
32 buf := memory.NewResizableBuffer(memory.DefaultAllocator)
33 buf.Resize(int(nbytes))
34 return buf, bitutils.NewBitBlockCounter(buf.Bytes(), offset, length)
35 }
36
37 func TestOneWordBasics(t *testing.T) {
38 const nbytes = 1024
39
40 buf, counter := create(nbytes, 0, nbytes*8)
41 defer buf.Release()
42
43 var bitsScanned int64
44 for i := 0; i < nbytes/8; i++ {
45 block := counter.NextWord()
46 assert.EqualValues(t, kWordSize, block.Len)
47 assert.EqualValues(t, 0, block.Popcnt)
48 bitsScanned += int64(block.Len)
49 }
50 assert.EqualValues(t, 1024*8, bitsScanned)
51
52 block := counter.NextWord()
53 assert.Zero(t, block.Len)
54 assert.Zero(t, block.Popcnt)
55 assert.True(t, block.NoneSet())
56 }
57
58 func TestFourWordsBasics(t *testing.T) {
59 const nbytes = 1024
60
61 buf, counter := create(nbytes, 0, nbytes*8)
62 defer buf.Release()
63
64 var bitsScanned int64
65 for i := 0; i < nbytes/32; i++ {
66 block := counter.NextFourWords()
67 assert.EqualValues(t, 4*kWordSize, block.Len)
68 assert.EqualValues(t, 0, block.Popcnt)
69 bitsScanned += int64(block.Len)
70 }
71 assert.EqualValues(t, 1024*8, bitsScanned)
72
73 block := counter.NextFourWords()
74 assert.Zero(t, block.Len)
75 assert.Zero(t, block.Popcnt)
76 }
77
78 func TestOneWordWithOffsets(t *testing.T) {
79 checkWithOffset := func(offset int64) {
80 const (
81 nwords int64 = 4
82 totalBytes = nwords*8 + 1
83 )
84
85
86
87 buf, counter := create(totalBytes, offset, nwords*kWordSize-offset-1)
88 defer buf.Release()
89
90 memory.Set(buf.Bytes(), byte(0xFF))
91
92 block := counter.NextWord()
93 assert.EqualValues(t, kWordSize, block.Len)
94 assert.EqualValues(t, 64, block.Popcnt)
95
96
97 bitutil.SetBitTo(buf.Bytes(), kWordSize+int(offset), false)
98 block = counter.NextWord()
99 assert.EqualValues(t, 64, block.Len)
100 assert.EqualValues(t, 63, block.Popcnt)
101
102
103 bitutil.SetBitsTo(buf.Bytes(), 2*kWordSize+offset, kWordSize, false)
104
105 block = counter.NextWord()
106 assert.EqualValues(t, 64, block.Len)
107 assert.Zero(t, block.Popcnt)
108
109 block = counter.NextWord()
110 assert.EqualValues(t, kWordSize-offset-1, block.Len)
111 assert.EqualValues(t, block.Len, block.Popcnt)
112 assert.True(t, block.AllSet())
113
114
115 block = counter.NextWord()
116 assert.Zero(t, block.Len)
117 assert.Zero(t, block.Popcnt)
118 }
119
120 for offsetI := int64(0); offsetI < 8; offsetI++ {
121 checkWithOffset(offsetI)
122 }
123 }
124
125 func TestFourWordsWithOffsets(t *testing.T) {
126 checkWithOffset := func(offset int64) {
127 const (
128 nwords = 17
129 totalBytes = nwords*8 + 1
130 )
131
132
133
134 buf, counter := create(totalBytes, offset, nwords*kWordSize-offset-1)
135
136
137 memory.Set(buf.Bytes(), 0xFF)
138
139 block := counter.NextFourWords()
140 assert.EqualValues(t, 4*kWordSize, block.Len)
141 assert.EqualValues(t, block.Len, block.Popcnt)
142
143
144 bitutil.ClearBit(buf.Bytes(), int(4*kWordSize+offset))
145 bitutil.ClearBit(buf.Bytes(), int(5*kWordSize+offset))
146 bitutil.ClearBit(buf.Bytes(), int(6*kWordSize+offset))
147
148 block = counter.NextFourWords()
149 assert.EqualValues(t, 4*kWordSize, block.Len)
150 assert.EqualValues(t, 253, block.Popcnt)
151
152
153 bitutil.SetBitsTo(buf.Bytes(), 8*kWordSize+offset, 2*kWordSize, false)
154
155
156 block = counter.NextFourWords()
157 assert.EqualValues(t, 4*kWordSize, block.Len)
158 assert.EqualValues(t, 128, block.Popcnt)
159
160
161 block = counter.NextFourWords()
162 assert.EqualValues(t, 4*kWordSize, block.Len)
163 assert.EqualValues(t, block.Len, block.Popcnt)
164
165
166 block = counter.NextFourWords()
167 assert.EqualValues(t, kWordSize-offset-1, block.Len)
168 assert.EqualValues(t, block.Len, block.Popcnt)
169
170
171 block = counter.NextFourWords()
172 assert.Zero(t, block.Len)
173 assert.Zero(t, block.Popcnt)
174 }
175
176 for offsetI := int64(0); offsetI < 8; offsetI++ {
177 checkWithOffset(offsetI)
178 }
179 }
180
181 func TestFourWordsRandomData(t *testing.T) {
182 const (
183 nbytes = 1024
184 )
185
186 buf := make([]byte, nbytes)
187 r := rand.New(rand.NewSource(0))
188 r.Read(buf)
189
190 checkWithOffset := func(offset int64) {
191 counter := bitutils.NewBitBlockCounter(buf, offset, nbytes*8-offset)
192 for i := 0; i < nbytes/32; i++ {
193 block := counter.NextFourWords()
194 assert.EqualValues(t, bitutil.CountSetBits(buf, i*256+int(offset), int(block.Len)), block.Popcnt)
195 }
196 }
197
198 for offsetI := int64(0); offsetI < 8; offsetI++ {
199 checkWithOffset(offsetI)
200 }
201 }
202
View as plain text