Blender V5.0
BLI_bit_span_test.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include <array>
6
7#include "BLI_bit_span.hh"
8#include "BLI_bit_span_ops.hh"
10#include "BLI_bit_vector.hh"
11#include "BLI_timeit.hh"
12#include "BLI_vector.hh"
13
14#include "testing/testing.h"
15
16namespace blender::bits::tests {
17
18TEST(bit_span, DefaultConstructor)
19{
20 {
21 char buffer[sizeof(BitSpan)];
22 memset(buffer, 0xff, sizeof(BitSpan));
23 BitSpan &span = *new (buffer) BitSpan();
24 EXPECT_TRUE(span.is_empty());
25 EXPECT_EQ(span.size(), 0);
26 }
27 {
28 char buffer[sizeof(MutableBitSpan)];
29 memset(buffer, 0xff, sizeof(MutableBitSpan));
30 MutableBitSpan &span = *new (buffer) MutableBitSpan();
31 EXPECT_TRUE(span.is_empty());
32 EXPECT_EQ(span.size(), 0);
33 }
34}
35
36TEST(bit_span, Iteration)
37{
38 uint64_t data = (1 << 2) | (1 << 3);
39 const BitSpan span(&data, 30);
40 EXPECT_EQ(span.size(), 30);
41 int index = 0;
42 for (const BitRef bit : span) {
43 EXPECT_EQ(bit.test(), ELEM(index, 2, 3));
44 index++;
45 }
46}
47
48TEST(bit_span, MutableIteration)
49{
50 uint64_t data = 0;
51 MutableBitSpan span(&data, 40);
52 EXPECT_EQ(span.size(), 40);
53 int index = 0;
54 for (MutableBitRef bit : span) {
55 bit.set(index % 4 == 0);
56 index++;
57 }
59 0b0000'0000'0000'0000'0000'0000'0001'0001'0001'0001'0001'0001'0001'0001'0001'0001);
60}
61
62TEST(bit_span, SubscriptOperator)
63{
64 uint64_t data[2] = {0, 0};
65 MutableBitSpan mutable_span(data, 128);
66 BitSpan span = mutable_span;
67
68 EXPECT_EQ(mutable_span.data(), data);
69 EXPECT_EQ(mutable_span.bit_range(), IndexRange(128));
70 EXPECT_EQ(span.data(), data);
71 EXPECT_EQ(span.bit_range(), IndexRange(128));
72
73 EXPECT_FALSE(mutable_span[5].test());
74 EXPECT_FALSE(span[5].test());
75 mutable_span[5].set(true);
76 EXPECT_TRUE(mutable_span[5].test());
77 EXPECT_TRUE(span[5].test());
78
79 EXPECT_FALSE(mutable_span[120].test());
80 EXPECT_FALSE(span[120].test());
81 mutable_span[120].set(true);
82 EXPECT_TRUE(mutable_span[120].test());
83 EXPECT_TRUE(span[120].test());
84
85 EXPECT_EQ(data[0],
86 0b0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0010'0000);
87 EXPECT_EQ(data[1],
88 0b0000'0001'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000);
89}
90
91TEST(bit_span, RangeConstructor)
92{
93 uint64_t data = 0;
94 MutableBitSpan mutable_span(&data, IndexRange(4, 3));
95 BitSpan span = mutable_span;
96
97 EXPECT_FALSE(mutable_span[1].test());
98 EXPECT_FALSE(span[1].test());
99 mutable_span[0].set(true);
100 mutable_span[1].set(true);
101 mutable_span[2].set(true);
102 mutable_span[0].set(false);
103 mutable_span[2].set(false);
104 EXPECT_TRUE(mutable_span[1].test());
105 EXPECT_TRUE(span[1].test());
106
108 0b0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0010'0000);
109}
110
111TEST(bit_span, Set)
112{
113 uint64_t data = 0;
114 MutableBitSpan(&data, 64).set_all(true);
115 EXPECT_EQ(data, uint64_t(-1));
116 MutableBitSpan(&data, 64).set_all(false);
118
119 MutableBitSpan(&data, IndexRange(4, 8)).set_all(true);
121 0b0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'1111'1111'0000);
122 MutableBitSpan(&data, IndexRange(8, 30)).set_all(false);
123
125 0b0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'1111'0000);
126}
127
128TEST(bit_span, SetEmpty)
129{
130 MutableBitSpan().set_all(true);
131 MutableBitSpan().set_all(false);
132}
133
134TEST(bit_span, SetSliced)
135{
136 std::array<uint64_t, 10> data;
137 memset(data.data(), 0, sizeof(data));
138 MutableBitSpan span{data.data(), 640};
139 span.slice(IndexRange(5, 500)).set_all(true);
140
141 for (const int64_t i : IndexRange(640)) {
142 EXPECT_EQ(span[i], i >= 5 && i < 505);
143 }
144
145 span.slice(IndexRange(10, 190)).set_all(false);
146
147 for (const int64_t i : IndexRange(640)) {
148 EXPECT_EQ(span[i], (i >= 5 && i < 10) || (i >= 200 && i < 505));
149 }
150}
151
152TEST(bit_span, IsBounded)
153{
154 std::array<uint64_t, 10> data;
155
156 EXPECT_TRUE(is_bounded_span(BitSpan(data.data(), 0)));
157 EXPECT_TRUE(is_bounded_span(BitSpan(data.data(), 1)));
158 EXPECT_TRUE(is_bounded_span(BitSpan(data.data(), 50)));
159 EXPECT_TRUE(is_bounded_span(BitSpan(data.data(), 63)));
160 EXPECT_TRUE(is_bounded_span(BitSpan(data.data(), 64)));
161 EXPECT_TRUE(is_bounded_span(BitSpan(data.data(), 65)));
162 EXPECT_TRUE(is_bounded_span(BitSpan(data.data(), 100)));
163 EXPECT_TRUE(is_bounded_span(BitSpan(data.data(), 400)));
164
165 EXPECT_TRUE(is_bounded_span(BitSpan(data.data(), IndexRange(0, 3))));
166 EXPECT_TRUE(is_bounded_span(BitSpan(data.data(), IndexRange(1, 3))));
167 EXPECT_TRUE(is_bounded_span(BitSpan(data.data(), IndexRange(10, 20))));
168 EXPECT_TRUE(is_bounded_span(BitSpan(data.data(), IndexRange(63, 1))));
169 EXPECT_TRUE(is_bounded_span(BitSpan(data.data(), IndexRange(10, 54))));
170
171 EXPECT_FALSE(is_bounded_span(BitSpan(data.data(), IndexRange(1, 64))));
172 EXPECT_FALSE(is_bounded_span(BitSpan(data.data(), IndexRange(10, 64))));
173 EXPECT_FALSE(is_bounded_span(BitSpan(data.data(), IndexRange(10, 200))));
174 EXPECT_FALSE(is_bounded_span(BitSpan(data.data(), IndexRange(60, 5))));
175 EXPECT_FALSE(is_bounded_span(BitSpan(data.data(), IndexRange(64, 0))));
176 EXPECT_FALSE(is_bounded_span(BitSpan(data.data(), IndexRange(70, 5))));
177}
178
179TEST(bit_span, CopyFrom)
180{
181 std::array<uint64_t, 30> src_data;
182 uint64_t i = 0;
183 for (uint64_t &value : src_data) {
184 value = i;
185 i += 234589766883;
186 }
187 const BitSpan src(src_data.data(), src_data.size() * BitsPerInt);
188
189 std::array<uint64_t, 4> dst_data;
190 dst_data.fill(-1);
191 MutableBitSpan dst(dst_data.data(), 100);
192 dst.copy_from(src.slice({401, 100}));
193
194 for (const int i : dst.index_range()) {
195 EXPECT_TRUE(dst[i].test() == src[401 + i].test());
196 }
197}
198
199TEST(bit_span, InPlaceOr)
200{
201 std::array<uint64_t, 100> data_1;
202 MutableBitSpan span_1(data_1.data(), data_1.size() * BitsPerInt);
203 for (const int i : span_1.index_range()) {
204 span_1[i].set(i % 2 == 0);
205 }
206
207 std::array<uint64_t, 100> data_2;
208 MutableBitSpan span_2(data_2.data(), data_2.size() * BitsPerInt);
209 for (const int i : span_2.index_range()) {
210 span_2[i].set(i % 2 != 0);
211 }
212
213 span_1 |= span_2;
214 for (const int i : span_1.index_range()) {
215 EXPECT_TRUE(span_1[i].test());
216 }
217}
218
219TEST(bit_span, InPlaceAnd)
220{
221 std::array<uint64_t, 100> data_1{};
222 MutableBitSpan span_1(data_1.data(), data_1.size() * BitsPerInt);
223 for (const int i : span_1.index_range()) {
224 span_1[i].set(i % 2 == 0);
225 }
226
227 std::array<uint64_t, 100> data_2{};
228 MutableBitSpan span_2(data_2.data(), data_2.size() * BitsPerInt);
229 for (const int i : span_2.index_range()) {
230 span_2[i].set(i % 2 != 0);
231 }
232
233 span_1 &= span_2;
234 for (const int i : span_1.index_range()) {
235 EXPECT_FALSE(span_1[i].test());
236 }
237}
238
239TEST(bit_span, ForEach1)
240{
241 std::array<uint64_t, 2> data{};
242 MutableBitSpan span(data.data(), data.size() * BitsPerInt);
243 for (const int i : {1, 28, 37, 86}) {
244 span[i].set();
245 }
246
247 Vector<int> indices_test;
248 foreach_1_index(span.slice({4, span.size() - 4}), [&](const int i) { indices_test.append(i); });
249
250 EXPECT_EQ(indices_test.as_span(), Span({24, 33, 82}));
251}
252
253TEST(bit_span, ForEach1Cancel)
254{
255 BitVector<> vec(100, false);
256 vec[4].set();
257 vec[10].set();
258 vec[20].set();
259 {
261 foreach_1_index(vec, [&](const int i) {
262 indices.append(i);
263 return i < 5;
264 });
265 EXPECT_EQ(indices.as_span(), Span({4, 10}));
266 }
267 {
269 foreach_1_index(vec, [&](const int i) {
270 indices.append(i);
271 return i < 15;
272 });
273 EXPECT_EQ(indices.as_span(), Span({4, 10, 20}));
274 }
275 {
277 foreach_1_index(vec, [&](const int i) {
278 indices.append(i);
279 return false;
280 });
281 EXPECT_EQ(indices.as_span(), Span({4}));
282 }
283 {
285 foreach_1_index(vec, [&](const int i) {
286 indices.append(i);
287 return true;
288 });
289 EXPECT_EQ(indices.as_span(), Span({4, 10, 20}));
290 }
291}
292
293TEST(bit_span, FindFirst1Index)
294{
295 {
296 BitVector<> vec(0);
297 EXPECT_EQ(find_first_1_index(vec), std::nullopt);
298 }
299 {
300 BitVector<> vec(10'000, false);
301 EXPECT_EQ(find_first_1_index(vec), std::nullopt);
302 }
303 {
304 BitVector<> vec(10'000, true);
306 }
307 {
308 BitVector<> vec(10, false);
309 vec[6].set();
311 }
312 {
313 BitVector<> vec(10'000, false);
314 vec[2'500].set();
315 EXPECT_EQ(find_first_1_index(vec), 2'500);
316 EXPECT_EQ(find_first_1_index(BitSpan(vec).drop_front(100)), 2'400);
317 }
318 {
319 BitVector<> vec_a(10'000, false);
320 BitVector<> vec_b(10'000, false);
321 vec_a[2'000].set();
322 vec_a[2'400].set();
323 vec_a[2'500].set();
324 vec_b[2'000].set();
325 vec_b[2'400].set();
326 vec_b[2'600].set();
327 /* This finds the first index where the two vectors are different. */
329 [](const BitInt a, const BitInt b) { return a ^ b; }, vec_a, vec_b),
330 2'500);
331 }
332}
333
334TEST(bit_span, FindFirst0Index)
335{
336 {
337 BitVector<> vec(0);
338 EXPECT_EQ(find_first_0_index(vec), std::nullopt);
339 }
340 {
341 BitVector<> vec(10'000, true);
342 EXPECT_EQ(find_first_0_index(vec), std::nullopt);
343 }
344 {
345 BitVector<> vec(10'000, false);
347 }
348 {
349 BitVector<> vec(10'000, true);
350 vec[2'500].reset();
351 EXPECT_EQ(find_first_0_index(vec), 2'500);
352 EXPECT_EQ(find_first_0_index(BitSpan(vec).drop_front(100)), 2'400);
353 }
354}
355
357{
358 {
359 Vector<bool> bools(5, false);
360 bools[2] = true;
361 BitVector<> bits(bools.size());
362 bits[0].set();
364 EXPECT_TRUE(bits[0]);
365 EXPECT_FALSE(bits[1]);
366 EXPECT_TRUE(bits[2]);
367 EXPECT_FALSE(bits[3]);
368 EXPECT_FALSE(bits[4]);
369 }
370 {
371 Vector<bool> bools(100, true);
372 BitVector<> bits(1000, false);
375 EXPECT_FALSE(bits[99]);
376 EXPECT_TRUE(bits[100]);
377 EXPECT_TRUE(bits[101]);
378 EXPECT_TRUE(bits[199]);
379 EXPECT_FALSE(bits[200]);
380 }
381}
382
383TEST(bit_span, to_index_ranges_small)
384{
385 BitVector<> bits(10, false);
386 bits[2].set();
387 bits[3].set();
388 bits[4].set();
389 bits[6].set();
390 bits[7].set();
391
393 IndexRangesBuilder<int> builder(builder_buffer);
394 bits_to_index_ranges(bits, builder);
395
396 EXPECT_EQ(builder.size(), 2);
399}
400
401TEST(bit_span, to_index_ranges_all_ones)
402{
403 BitVector<> bits(10000, true);
404
406 IndexRangesBuilder<int> builder(builder_buffer);
407 bits_to_index_ranges(BitSpan(bits).take_back(8765), builder);
408
409 EXPECT_EQ(builder.size(), 1);
410 EXPECT_EQ(builder[0], IndexRange(8765));
411}
412
413} // namespace blender::bits::tests
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
#define ELEM(...)
BMesh const char void * data
long long int int64_t
unsigned long long int uint64_t
static constexpr IndexRange from_begin_size(const int64_t begin, const int64_t size)
static constexpr IndexRange from_begin_end_inclusive(const int64_t begin, const int64_t last)
int64_t size() const
Span< T > as_span() const
const BitInt * data() const
int64_t size() const
BitSpan slice(const IndexRange range) const
const IndexRange & bit_range() const
MutableBitSpan slice(const IndexRange range) const
const IndexRange & bit_range() const
IndexRange index_range() const
void copy_from(const BitSpan other)
Definition bit_span.cc:66
static ushort indices[]
TEST(bit_group_vector, DefaultConstruct)
uint64_t BitInt
bool or_bools_into_bits(Span< bool > bools, MutableBitSpan r_bits, int64_t allowed_overshoot=0)
std::optional< int64_t > find_first_1_index_expr(ExprFn &&Expr, const FirstBitSpanT &first_arg, const BitSpanT &...args)
static constexpr int64_t BitsPerInt
void bits_to_index_ranges(const BitSpan bits, IndexRangesBuilder< IntT > &builder)
bool is_bounded_span(const BitSpan span)
std::optional< int64_t > find_first_0_index(const BitSpanT &data)
void foreach_1_index(const BitSpanT &data, Fn &&fn)
std::optional< int64_t > find_first_1_index(const BitSpanT &data)
i
Definition text_draw.cc:230