Blender V5.0
BLI_index_mask_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 "testing/testing.h"
6
7#include <fmt/format.h>
8
9#include "BLI_array.hh"
10#include "BLI_bit_span_ops.hh"
11#include "BLI_bit_vector.hh"
12#include "BLI_index_mask.hh"
14#include "BLI_rand.hh"
15#include "BLI_set.hh"
16#include "BLI_timeit.hh"
17
18#include "BLI_strict_flags.h" /* IWYU pragma: keep. Keep last. */
19
21
22TEST(index_mask, IndicesToMask)
23{
24 IndexMaskMemory memory;
26 5, 100, 16383, 16384, 16385, 20000, 20001, 50000, 50001, 50002, 100000, 101000};
28
29 EXPECT_EQ(mask.first(), 5);
30 EXPECT_EQ(mask.last(), 101000);
31 EXPECT_EQ(mask.min_array_size(), 101001);
33}
34
35TEST(index_mask, FromBitsManual)
36{
37 IndexMaskMemory memory;
38 const uint64_t bits =
39 0b0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'1111'0010'0000;
40 const IndexMask mask = IndexMask::from_bits(BitSpan(&bits, IndexRange(2, 40)), memory);
42 mask.to_indices<int>(indices);
43 EXPECT_EQ(indices[0], 3);
44 EXPECT_EQ(indices[1], 6);
45 EXPECT_EQ(indices[2], 7);
46 EXPECT_EQ(indices[3], 8);
47 EXPECT_EQ(indices[4], 9);
48}
49
50TEST(index_mask, FromBitsSimple)
51{
52 IndexMaskMemory memory;
53 BitVector bit_vec(200, true);
54 bit_vec[0].reset();
55 bit_vec[100].reset();
56 const IndexMask mask = IndexMask::from_bits(bit_vec, memory);
57
58 EXPECT_EQ(mask.size(), 198);
59 EXPECT_FALSE(mask.contains(0));
60 EXPECT_FALSE(mask.contains(100));
61}
62
63TEST(index_mask, FromBitsWithUniverse)
64{
65 IndexMaskMemory memory;
66 BitVector bit_vec(200, true);
67 bit_vec[6].reset();
68 bit_vec[100].reset();
69
70 const IndexMask universe = IndexMask::from_indices<int>({4, 6, 7, 8, 9, 100, 101, 102}, memory);
71 const IndexMask mask = IndexMask::from_bits(universe, bit_vec, memory);
72 EXPECT_EQ(mask.size(), 6);
73 EXPECT_EQ(mask[0], 4);
74 EXPECT_EQ(mask[1], 7);
75 EXPECT_EQ(mask[2], 8);
76 EXPECT_EQ(mask[3], 9);
77 EXPECT_EQ(mask[4], 101);
78 EXPECT_EQ(mask[5], 102);
79}
80
81TEST(index_mask, FromBitsSparse)
82{
83 BitVector bit_vec(100'000, false);
84 bit_vec[5].set();
85 bit_vec[100].set();
86 bit_vec[200].set();
87 bit_vec[500].set();
88 bit_vec[800].set();
89 bit_vec[10'000].set();
90 bit_vec[10'002].set();
91 bit_vec[50'000].set();
92 bit_vec[70'000].set();
93 bit_vec[70'002].set();
94 bit_vec[70'004].set();
95 bit_vec[70'005].set();
96
97 IndexMaskMemory memory;
98 const IndexMask mask = IndexMask::from_bits(bit_vec, memory);
99 EXPECT_EQ(mask.size(), 12);
100 EXPECT_EQ(mask[0], 5);
101 EXPECT_EQ(mask[1], 100);
102 EXPECT_EQ(mask[2], 200);
103 EXPECT_EQ(mask[3], 500);
104 EXPECT_EQ(mask[4], 800);
105 EXPECT_EQ(mask[5], 10'000);
106 EXPECT_EQ(mask[6], 10'002);
107 EXPECT_EQ(mask[7], 50'000);
108 EXPECT_EQ(mask[8], 70'000);
109 EXPECT_EQ(mask[9], 70'002);
110 EXPECT_EQ(mask[10], 70'004);
111 EXPECT_EQ(mask[11], 70'005);
112}
113
114TEST(index_mask, FromBoolsSparse)
115{
116 Vector<bool> bools(10'000'000, false);
117 bools[5] = true;
118 bools[100] = true;
119 bools[200] = true;
120 bools[500] = true;
121 bools[800] = true;
122 bools[10'000] = true;
123 bools[10'002] = true;
124 bools[50'000] = true;
125 bools[70'000] = true;
126 bools[70'002] = true;
127 bools[70'004] = true;
128 bools[70'005] = true;
129
130 IndexMaskMemory memory;
131 const IndexMask mask = IndexMask::from_bools(bools, memory);
132 EXPECT_EQ(mask.size(), 12);
133 EXPECT_EQ(mask[0], 5);
134 EXPECT_EQ(mask[1], 100);
135 EXPECT_EQ(mask[2], 200);
136 EXPECT_EQ(mask[3], 500);
137 EXPECT_EQ(mask[4], 800);
138 EXPECT_EQ(mask[5], 10'000);
139 EXPECT_EQ(mask[6], 10'002);
140 EXPECT_EQ(mask[7], 50'000);
141 EXPECT_EQ(mask[8], 70'000);
142 EXPECT_EQ(mask[9], 70'002);
143 EXPECT_EQ(mask[10], 70'004);
144 EXPECT_EQ(mask[11], 70'005);
145}
146
147TEST(index_mask, FromBitsAlternating)
148{
149 int64_t size = 100'000;
150 BitVector<> bits(size, false);
151 for (const int64_t i : IndexRange(size / 2)) {
152 bits[i * 2].set();
153 }
154
155 IndexMaskMemory memory;
156 const IndexMask mask = IndexMask::from_bits(bits, memory);
157 EXPECT_EQ(mask.size(), size / 2);
158 EXPECT_EQ(mask[0], 0);
159 EXPECT_EQ(mask[1], 2);
160 EXPECT_EQ(mask[2], 4);
161 EXPECT_EQ(mask[3], 6);
162}
163
164/* The benchmark is too slow to run during normal test runs. */
165#if 0
166
167static BitVector<> build_bits_with_uniform_distribution(const int bits_num,
168 const int set_bits_num,
169 const uint32_t seed = 0)
170{
171 if (set_bits_num > bits_num / 2) {
172 BitVector bit_vec = build_bits_with_uniform_distribution(bits_num, bits_num - set_bits_num);
173 bits::invert(bit_vec);
174 return bit_vec;
175 }
176 BitVector bit_vec(bits_num, false);
178 int counter = 0;
179 while (counter < set_bits_num) {
180 const int i = rng.get_int32(int(bits_num));
181 MutableBitRef bit = bit_vec[i];
182 if (!bit) {
183 bit.set();
184 counter++;
185 }
186 }
187 return bit_vec;
188}
189
190static void benchmark_uniform_bit_distribution(const int bits_num,
191 const int set_bits_num,
192 const int iterations)
193{
194 const bool machine_readable = true;
195 BitVector bit_vec = build_bits_with_uniform_distribution(bits_num, set_bits_num);
196 std::locale loc("en_US.UTF-8");
197 timeit::Nanoseconds min_duration{INT64_MAX};
198 for ([[maybe_unused]] const int64_t i : IndexRange(iterations)) {
199 IndexMaskMemory memory;
200 timeit::TimePoint start = timeit::Clock::now();
201 const IndexMask mask = IndexMask::from_bits(bit_vec, memory);
202 timeit::TimePoint end = timeit::Clock::now();
203 const timeit::Nanoseconds duration = end - start;
204 // const double ms = double(duration.count()) / 1'000'000.0;
205 // std::cout << fmt::format(loc, "{:15L} / {:L}: {:.4} ms\n", set_bits_num, bits_num, ms);
206 min_duration = std::min(min_duration, duration);
207 EXPECT_EQ(mask.size(), set_bits_num);
208 }
209 const double ms = double(min_duration.count()) / 1'000'000.0;
210 if (machine_readable) {
211 std::cout << fmt::format("{},{:.6}\n", set_bits_num, ms);
212 }
213 else {
214 std::cout << fmt::format(loc, "{:15L} / {:L}: {:.4} ms\n", set_bits_num, bits_num, ms);
215 }
216}
217
218TEST(index_mask, FromBitsBenchmark)
219{
220 const int size = 100'000'000;
221 const int iterations = 5;
222 Vector<int> set_bit_nums;
223 set_bit_nums.append(0);
224 int current = 100;
225 while (current < size / 2) {
226 set_bit_nums.append(current);
227 set_bit_nums.append(size - current);
228 current = int(current * 1.3);
229 }
230 set_bit_nums.append(size);
231 std::sort(set_bit_nums.begin(), set_bit_nums.end());
232
233 for (const int set_bit_num : set_bit_nums) {
234 benchmark_uniform_bit_distribution(size, set_bit_num, iterations);
235 }
236}
237
238/* Benchmark. */
239#endif
240
241TEST(index_mask, FromBitsFuzzy)
242{
244 for ([[maybe_unused]] const int64_t iteration : IndexRange(10)) {
245 const int size = rng.get_int32(100'000) + 1;
246 const int set_bits = rng.get_int32(size);
247
248 /* Remove part of the beginning and end of the bits to test unaligned bit spans. */
249 const int64_t slice_inset = rng.get_int32(size / 10);
250 const IndexRange slice = IndexRange::from_begin_end(slice_inset, size - slice_inset);
251
252 BitVector<> bits(size, false);
253 for ([[maybe_unused]] const int64_t set_bit_i : IndexRange(set_bits)) {
254 int index = rng.get_int32(size);
255 /* This is like linear probing which results in a somewhat random distribution but also leads
256 * to having longer ranges every now and then. */
257 while (true) {
258 if (!bits[index]) {
259 bits[index].set();
260 break;
261 }
262 index = (index + 1) % size;
263 }
264 }
265
266 IndexMaskMemory memory;
267
268 /* The universe is partially a range and partially only even/odd indices.
269 * For example: [1, 2, 3, 4, 6, 8, 10, 12]. */
270 const int64_t slice_half_size = slice.size() / 2;
271 const IndexMask universe = IndexMask::from_union(
272 IndexRange(slice_half_size),
274 IndexRange(1), slice_half_size, 2, slice_half_size, memory),
275 memory)
276 .slice_content(slice.index_range());
277
278 const IndexMask mask = IndexMask::from_bits(universe, BitSpan(bits).slice(slice), memory);
279
280 BitVector<> inverted_bits{bits};
281 bits::invert(inverted_bits);
282 const IndexMask inverted_mask = IndexMask::from_bits(
283 universe, BitSpan(inverted_bits).slice(slice), memory);
284
285 const IndexMask double_inverted_mask = inverted_mask.complement(universe, memory);
286 EXPECT_EQ(mask, double_inverted_mask);
287 }
288}
289
290TEST(index_mask, FromBitsDense)
291{
292 BitVector bit_vec(1'000, true);
293 bit_vec[5].reset();
294 bit_vec[200].reset();
295 bit_vec[201].reset();
296 bit_vec[500].reset();
297 bit_vec[502].reset();
298 bit_vec[504].reset();
299 bit_vec[506].reset();
300
301 IndexMaskMemory memory;
302 const IndexMask mask = IndexMask::from_bits(bit_vec, memory);
303 EXPECT_EQ(mask.size(), 993);
304 EXPECT_FALSE(mask.contains(5));
305 EXPECT_FALSE(mask.contains(200));
306 EXPECT_FALSE(mask.contains(201));
307 EXPECT_FALSE(mask.contains(500));
308 EXPECT_FALSE(mask.contains(502));
309 EXPECT_FALSE(mask.contains(504));
310 EXPECT_FALSE(mask.contains(506));
311}
312
313TEST(index_mask, FromSize)
314{
315 {
316 const IndexMask mask(5);
318 mask.foreach_segment([&](const IndexMaskSegment segment) { segments.append(segment); });
319 EXPECT_EQ(segments.size(), 1);
320 EXPECT_EQ(segments[0].size(), 5);
321 EXPECT_EQ(mask.first(), 0);
322 EXPECT_EQ(mask.last(), 4);
323 EXPECT_EQ(mask.min_array_size(), 5);
324 EXPECT_EQ(mask.bounds(), IndexRange(5));
325 }
326 {
329 mask.foreach_segment([&](const IndexMaskSegment segment) { segments.append(segment); });
330 EXPECT_EQ(segments.size(), 1);
331 EXPECT_EQ(segments[0].size(), max_segment_size);
332 EXPECT_EQ(mask.first(), 0);
333 EXPECT_EQ(mask.last(), max_segment_size - 1);
334 EXPECT_EQ(mask.min_array_size(), max_segment_size);
336 }
337}
338
339TEST(index_mask, FromUnion)
340{
341 {
342 IndexMaskMemory memory;
343 Array<int> data_a = {1, 2};
344 IndexMask mask_a = IndexMask::from_indices<int>(data_a, memory);
345 Array<int> data_b = {2, 20000, 20001};
346 IndexMask mask_b = IndexMask::from_indices<int>(data_b, memory);
347
348 IndexMask mask_union = IndexMask::from_union(mask_a, mask_b, memory);
349
350 EXPECT_EQ(mask_union.size(), 4);
351 EXPECT_EQ(mask_union[0], 1);
352 EXPECT_EQ(mask_union[1], 2);
353 EXPECT_EQ(mask_union[2], 20000);
354 EXPECT_EQ(mask_union[3], 20001);
355 }
356 {
357 IndexMaskMemory memory;
358 Array<int> data_a = {1, 2, 3};
359 IndexMask mask_a = IndexMask::from_indices<int>(data_a, memory);
360 Array<int> data_b = {20000, 20001, 20002};
361 IndexMask mask_b = IndexMask::from_indices<int>(data_b, memory);
362
363 IndexMask mask_union = IndexMask::from_union(mask_a, mask_b, memory);
364
365 EXPECT_EQ(mask_union.size(), 6);
366 EXPECT_EQ(mask_union[0], 1);
367 EXPECT_EQ(mask_union[1], 2);
368 EXPECT_EQ(mask_union[2], 3);
369 EXPECT_EQ(mask_union[3], 20000);
370 EXPECT_EQ(mask_union[4], 20001);
371 EXPECT_EQ(mask_union[5], 20002);
372 }
373 {
374 IndexMaskMemory memory;
375 IndexMask mask_union = IndexMask::from_union({}, memory);
376 EXPECT_TRUE(mask_union.is_empty());
377 }
378 {
379 IndexMaskMemory memory;
381 IndexRange::from_begin_end(20000, 30000),
382 IndexRange::from_begin_end(40000, 50000)},
383 memory);
384 EXPECT_EQ(mask_union.size(), 30000);
385 }
386}
387
388TEST(index_mask, FromDifference)
389{
390 {
391 IndexMaskMemory memory;
392 Array<int> data_a = {1, 2, 3};
393 IndexMask mask_a = IndexMask::from_indices<int>(data_a, memory);
394 Array<int> data_b = {2, 20000, 20001};
395 IndexMask mask_b = IndexMask::from_indices<int>(data_b, memory);
396
397 IndexMask mask_difference = IndexMask::from_difference(mask_a, mask_b, memory);
398
399 EXPECT_EQ(mask_difference.size(), 2);
400 EXPECT_EQ(mask_difference[0], 1);
401 EXPECT_EQ(mask_difference[1], 3);
402 }
403 {
404 IndexMaskMemory memory;
405 Array<int> data_a = {1, 2, 3};
406 IndexMask mask_a = IndexMask::from_indices<int>(data_a, memory);
407 Array<int> data_b = {1, 2, 3};
408 IndexMask mask_b = IndexMask::from_indices<int>(data_b, memory);
409
410 IndexMask mask_difference = IndexMask::from_difference(mask_a, mask_b, memory);
411
412 EXPECT_TRUE(mask_difference.is_empty());
413 }
414}
415
416TEST(index_mask, FromIntersection)
417{
418 {
419 IndexMaskMemory memory;
420 Array<int> data_a = {1, 2, 20000};
421 IndexMask mask_a = IndexMask::from_indices<int>(data_a, memory);
422 Array<int> data_b = {2, 20000, 20001};
423 IndexMask mask_b = IndexMask::from_indices<int>(data_b, memory);
424
425 IndexMask mask_intersection = IndexMask::from_intersection(mask_a, mask_b, memory);
426
427 EXPECT_EQ(mask_intersection.size(), 2);
428 EXPECT_EQ(mask_intersection[0], 2);
429 EXPECT_EQ(mask_intersection[1], 20000);
430 }
431 {
432 IndexMaskMemory memory;
433 Array<int> data_a = {1, 2, 3};
434 IndexMask mask_a = IndexMask::from_indices<int>(data_a, memory);
435 Array<int> data_b = {20000, 20001, 20002};
436 IndexMask mask_b = IndexMask::from_indices<int>(data_b, memory);
437
438 IndexMask mask_intersection = IndexMask::from_intersection(mask_a, mask_b, memory);
439
440 EXPECT_TRUE(mask_intersection.is_empty());
441 }
442}
443
444TEST(index_mask, DefaultConstructor)
445{
447 EXPECT_EQ(mask.size(), 0);
448 EXPECT_EQ(mask.min_array_size(), 0);
449 EXPECT_EQ(mask.bounds(), IndexRange());
450}
451
452TEST(index_mask, ForeachRange)
453{
454 IndexMaskMemory memory;
455 const IndexMask mask = IndexMask::from_indices<int>({2, 3, 4, 10, 40, 41}, memory);
456 Vector<IndexRange> ranges;
457 mask.foreach_range([&](const IndexRange range) { ranges.append(range); });
458
459 EXPECT_EQ(ranges.size(), 3);
460 EXPECT_EQ(ranges[0], IndexRange(2, 3));
461 EXPECT_EQ(ranges[1], IndexRange(10, 1));
462 EXPECT_EQ(ranges[2], IndexRange(40, 2));
463}
464
466{
467 IndexMaskMemory memory;
468 {
469 const IndexMask mask = IndexMask::from_indices<int>({4, 5, 6, 7}, memory);
470 EXPECT_TRUE(mask.to_range().has_value());
471 EXPECT_EQ(*mask.to_range(), IndexRange(4, 4));
472 }
473 {
474 const IndexMask mask = IndexMask::from_indices<int>({}, memory);
475 EXPECT_TRUE(mask.to_range().has_value());
476 EXPECT_EQ(*mask.to_range(), IndexRange());
477 }
478 {
479 const IndexMask mask = IndexMask::from_indices<int>({0, 1, 3, 4}, memory);
480 EXPECT_FALSE(mask.to_range().has_value());
481 }
482 {
483 const IndexRange range{16000, 40000};
484 const IndexMask mask{range};
485 EXPECT_TRUE(mask.to_range().has_value());
486 EXPECT_EQ(*mask.to_range(), range);
487 }
488}
489
491{
492 IndexMaskMemory memory;
493 {
494 const IndexMask mask = IndexMask::from_indices<int>({4, 5, 6, 7}, memory);
495 BitVector<> bits(mask.min_array_size());
496 mask.to_bits(bits);
497 EXPECT_EQ(bits[0].test(), false);
498 EXPECT_EQ(bits[1].test(), false);
499 EXPECT_EQ(bits[2].test(), false);
500 EXPECT_EQ(bits[3].test(), false);
501 EXPECT_EQ(bits[4].test(), true);
502 EXPECT_EQ(bits[5].test(), true);
503 EXPECT_EQ(bits[6].test(), true);
504 EXPECT_EQ(bits[7].test(), true);
505 }
506 {
507 const IndexMask mask = IndexMask::from_indices<int>({4, 5, 6, 7}, memory);
508 BitVector<> bits(mask.min_array_size());
509 bits[0].set();
510 bits[2].set();
511 mask.set_bits(bits);
512 EXPECT_EQ(bits[0].test(), true);
513 EXPECT_EQ(bits[1].test(), false);
514 EXPECT_EQ(bits[2].test(), true);
515 EXPECT_EQ(bits[3].test(), false);
516 EXPECT_EQ(bits[4].test(), true);
517 EXPECT_EQ(bits[5].test(), true);
518 EXPECT_EQ(bits[6].test(), true);
519 EXPECT_EQ(bits[7].test(), true);
520 }
521}
522
523TEST(index_mask, FromRange)
524{
525 const auto test_range = [](const IndexRange range) {
526 const IndexMask mask = range;
527 EXPECT_EQ(mask.to_range(), range);
528 };
529
530 test_range({0, 0});
531 test_range({0, 10});
532 test_range({0, 16384});
533 test_range({16320, 64});
534 test_range({16384, 64});
535 test_range({0, 100000});
536 test_range({100000, 100000});
537 test_range({688064, 64});
538}
539
540TEST(index_mask, FromPredicate)
541{
542 IndexMaskMemory memory;
543 {
544 const IndexRange range{20'000, 50'000};
546 IndexRange(100'000), GrainSize(1024), memory, [&](const int64_t i) {
547 return range.contains(i);
548 });
549 EXPECT_EQ(mask.to_range(), range);
550 }
551 {
552 const Vector<int64_t> indices = {0, 500, 20'000, 50'000};
554 IndexRange(100'000), GrainSize(1024), memory, [&](const int64_t i) {
555 return indices.contains(i);
556 });
557 EXPECT_EQ(mask.size(), indices.size());
558 Vector<int64_t> new_indices(mask.size());
559 mask.to_indices<int64_t>(new_indices);
560 EXPECT_EQ(indices, new_indices);
561 }
562}
563
564TEST(index_mask, IndexIteratorConversionFuzzy)
565{
567
569 indices.append(5);
570 for ([[maybe_unused]] const int64_t i : IndexRange(1000)) {
571 for ([[maybe_unused]] const int64_t j :
572 IndexRange(indices.last() + 1 + rng.get_int32(1000), rng.get_int32(64)))
573 {
574 indices.append(j);
575 }
576 }
577
578 IndexMaskMemory memory;
580 EXPECT_EQ(mask.size(), indices.size());
581
582 for ([[maybe_unused]] const int64_t _ : IndexRange(100)) {
583 const int64_t index = rng.get_int32(int(indices.size()));
584 const RawMaskIterator it = mask.index_to_iterator(index);
585 EXPECT_EQ(mask[it], indices[index]);
586 const int64_t new_index = mask.iterator_to_index(it);
587 EXPECT_EQ(index, new_index);
588 }
589
590 for ([[maybe_unused]] const int64_t _ : IndexRange(100)) {
591 const int64_t start = rng.get_int32(int(indices.size() - 1));
592 const int64_t size = 1 + rng.get_int32(int(indices.size() - start - 1));
593 const IndexMask sub_mask = mask.slice(start, size);
594 const int64_t index = rng.get_int32(int(sub_mask.size()));
595 const RawMaskIterator it = sub_mask.index_to_iterator(index);
596 EXPECT_EQ(sub_mask[it], indices[start + index]);
597 const int64_t new_index = sub_mask.iterator_to_index(it);
598 EXPECT_EQ(index, new_index);
599 }
600
601 for ([[maybe_unused]] const int64_t _ : IndexRange(100)) {
602 const int64_t index = rng.get_int32(int(indices.size() - 1000));
603 for (const int64_t offset : {0, 1, 2, 100, 500}) {
604 const int64_t index_to_search = indices[index] + offset;
605 const bool contained = std::binary_search(indices.begin(), indices.end(), index_to_search);
606 const std::optional<RawMaskIterator> it = mask.find(index_to_search);
607 EXPECT_EQ(contained, it.has_value());
608 if (contained) {
609 EXPECT_EQ(index_to_search, mask[*it]);
610 }
611 }
612 }
613}
614
615TEST(index_mask, FromPredicateFuzzy)
616{
618 Set<int> values;
619
620 for ([[maybe_unused]] const int64_t _ : IndexRange(10000)) {
621 values.add(rng.get_int32(100'000));
622 }
623
624 IndexMaskMemory memory;
626 IndexRange(110'000), GrainSize(1024), memory, [&](const int64_t i) {
627 return values.contains(int(i));
628 });
629 EXPECT_EQ(mask.size(), values.size());
630 for (const int index : values) {
631 EXPECT_TRUE(mask.contains(index));
632 }
633 mask.foreach_index([&](const int64_t index, const int64_t pos) {
634 EXPECT_TRUE(values.contains(int(index)));
635 EXPECT_EQ(index, mask[pos]);
636 });
637}
638
639TEST(index_mask, Complement)
640{
641 IndexMaskMemory memory;
642 {
643 const IndexMask mask(0);
644 const IndexMask complement = mask.complement(IndexRange(100), memory);
645 EXPECT_EQ(100 - mask.size(), complement.size());
646 complement.foreach_index([&](const int64_t i) { EXPECT_FALSE(mask.contains(i)); });
647 mask.foreach_index([&](const int64_t i) { EXPECT_FALSE(complement.contains(i)); });
648 }
649 {
650 const IndexMask mask(10000);
651 const IndexMask complement = mask.complement(IndexRange(10000), memory);
652 EXPECT_EQ(10000 - mask.size(), complement.size());
653 complement.foreach_index([&](const int64_t i) { EXPECT_FALSE(mask.contains(i)); });
654 mask.foreach_index([&](const int64_t i) { EXPECT_FALSE(complement.contains(i)); });
655 }
656 {
657 const IndexMask mask(IndexRange(100, 900));
658 const IndexMask complement = mask.complement(IndexRange(1000), memory);
659 EXPECT_EQ(1000 - mask.size(), complement.size());
660 complement.foreach_index([&](const int64_t i) { EXPECT_FALSE(mask.contains(i)); });
661 mask.foreach_index([&](const int64_t i) { EXPECT_FALSE(complement.contains(i)); });
662 }
663 {
664 const IndexMask mask(IndexRange(0, 900));
665 const IndexMask complement = mask.complement(IndexRange(1000), memory);
666 EXPECT_EQ(1000 - mask.size(), complement.size());
667 complement.foreach_index([&](const int64_t i) { EXPECT_FALSE(mask.contains(i)); });
668 mask.foreach_index([&](const int64_t i) { EXPECT_FALSE(complement.contains(i)); });
669 }
670}
671
672TEST(index_mask, ComplementFuzzy)
673{
675
676 const int64_t mask_size = 100;
677 const int64_t iter_num = 100;
678 const int64_t universe_size = 110;
679
680 for (const int64_t iter : IndexRange(iter_num)) {
681 Set<int> values;
682 for ([[maybe_unused]] const int64_t _ : IndexRange(iter)) {
683 values.add(rng.get_int32(mask_size));
684 }
685 IndexMaskMemory memory;
687 IndexRange(mask_size), GrainSize(1024), memory, [&](const int64_t i) {
688 return values.contains(int(i));
689 });
690
691 const IndexMask complement = mask.complement(IndexRange(universe_size), memory);
692 EXPECT_EQ(universe_size - mask.size(), complement.size());
693 complement.foreach_index([&](const int64_t i) { EXPECT_FALSE(mask.contains(i)); });
694 mask.foreach_index([&](const int64_t i) { EXPECT_FALSE(complement.contains(i)); });
695 }
696}
697
698TEST(index_mask, OffsetIndexRangeFind)
699{
700 IndexMask mask = IndexRange(1, 2);
701 auto result = mask.find(1);
702 EXPECT_TRUE(result.has_value());
703 EXPECT_EQ(mask.iterator_to_index(*result), 0);
704 EXPECT_EQ(mask[0], 1);
705}
706
707TEST(index_mask, FindLargerEqual)
708{
709 IndexMaskMemory memory;
710 {
712 {0, 1, 3, 6, IndexRange(50, 50), IndexRange(100'000, 30)}, memory);
713 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(0)), 0);
714 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(1)), 1);
715 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(2)), 2);
716 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(3)), 2);
717 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(4)), 3);
718 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(5)), 3);
719 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(6)), 3);
720 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(7)), 4);
721 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(10)), 4);
722 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(40)), 4);
723 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(49)), 4);
724 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(50)), 4);
725 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(60)), 14);
726 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(70)), 24);
727 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(99)), 53);
728 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(100)), 54);
729 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(1'000)), 54);
730 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(10'000)), 54);
731 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(50'000)), 54);
732 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(100'000)), 54);
733 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(100'001)), 55);
734 EXPECT_FALSE(mask.find_larger_equal(101'000).has_value());
735 }
736 {
737 const IndexMask mask{IndexRange(10'000, 30'000)};
738 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(0)), 0);
739 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(50)), 0);
740 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(9'999)), 0);
741 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(10'000)), 0);
742 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(10'001)), 1);
743 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(39'998)), 29'998);
744 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(39'999)), 29'999);
745 EXPECT_FALSE(mask.find_larger_equal(40'000).has_value());
746 EXPECT_FALSE(mask.find_larger_equal(40'001).has_value());
747 EXPECT_FALSE(mask.find_larger_equal(100'000).has_value());
748 }
749}
750
751TEST(index_mask, FindSmallerEqual)
752{
753 IndexMaskMemory memory;
754 {
756 {0, 1, 3, 6, IndexRange(50, 50), IndexRange(100'000, 30)}, memory);
757 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(0)), 0);
758 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(1)), 1);
759 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(2)), 1);
760 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(3)), 2);
761 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(4)), 2);
762 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(5)), 2);
763 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(6)), 3);
764 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(7)), 3);
765 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(10)), 3);
766 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(40)), 3);
767 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(49)), 3);
768 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(50)), 4);
769 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(60)), 14);
770 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(70)), 24);
771 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(99)), 53);
772 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(100)), 53);
773 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(1'000)), 53);
774 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(10'000)), 53);
775 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(50'000)), 53);
776 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(100'000)), 54);
777 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(100'001)), 55);
778 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(101'000)), 83);
779 }
780 {
781 const IndexMask mask{IndexRange(10'000, 30'000)};
782 EXPECT_FALSE(mask.find_smaller_equal(0).has_value());
783 EXPECT_FALSE(mask.find_smaller_equal(1).has_value());
784 EXPECT_FALSE(mask.find_smaller_equal(50).has_value());
785 EXPECT_FALSE(mask.find_smaller_equal(9'999).has_value());
786 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(10'000)), 0);
787 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(10'001)), 1);
788 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(39'998)), 29'998);
789 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(39'999)), 29'999);
790 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(40'000)), 29'999);
791 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(40'001)), 29'999);
792 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(100'000)), 29'999);
793 }
794}
795
796TEST(index_mask, SliceContent)
797{
798 IndexMaskMemory memory;
799 {
800 const IndexMask mask;
801 EXPECT_TRUE(mask.slice_content(IndexRange(50, 10)).is_empty());
802 }
803 {
804 const IndexMask mask{IndexRange(10, 90)};
805 const IndexMask a = mask.slice_content(IndexRange(30));
806 EXPECT_EQ(a.size(), 20);
807 const IndexMask b = mask.slice_content(IndexRange(10, 90));
808 EXPECT_EQ(b.size(), 90);
809 const IndexMask c = mask.slice_content(IndexRange(80, 100));
810 EXPECT_EQ(c.size(), 20);
811 const IndexMask d = mask.slice_content(IndexRange(1000, 100));
812 EXPECT_EQ(d.size(), 0);
813 }
814 {
816 {4, 5, 100, 1'000, 10'000, 20'000, 25'000, 100'000}, memory);
817 EXPECT_EQ(mask.slice_content(IndexRange(10)).size(), 2);
818 EXPECT_EQ(mask.slice_content(IndexRange(200)).size(), 3);
819 EXPECT_EQ(mask.slice_content(IndexRange(2'000)).size(), 4);
820 EXPECT_EQ(mask.slice_content(IndexRange(10'000)).size(), 4);
821 EXPECT_EQ(mask.slice_content(IndexRange(10'001)).size(), 5);
822 EXPECT_EQ(mask.slice_content(IndexRange(1'000'000)).size(), 8);
823 EXPECT_EQ(mask.slice_content(IndexRange(10'000, 100'000)).size(), 4);
824 EXPECT_EQ(mask.slice_content(IndexRange(1'001, 100'000)).size(), 4);
825 EXPECT_EQ(mask.slice_content(IndexRange(1'000, 100'000)).size(), 5);
826 EXPECT_EQ(mask.slice_content(IndexRange(1'000, 99'000)).size(), 4);
827 EXPECT_EQ(mask.slice_content(IndexRange(1'000, 10'000)).size(), 2);
828 }
829}
830
831TEST(index_mask, EqualsRangeSelf)
832{
833 IndexMask mask = IndexRange(16384);
835}
836
837TEST(index_mask, EqualsRange)
838{
839 IndexMask mask_a = IndexRange(16384);
840 IndexMask mask_b = IndexRange(16384);
841 EXPECT_EQ(mask_a, mask_b);
842}
843
844TEST(index_mask, EqualsRangeLarge)
845{
846 IndexMask mask_a = IndexRange(96384);
847 IndexMask mask_b = IndexRange(96384);
848 EXPECT_EQ(mask_a, mask_b);
849}
850
851TEST(index_mask, EqualsRangeBegin)
852{
853 IndexMask mask_a = IndexRange(102, 16384 - 102);
854 IndexMask mask_b = IndexRange(102, 16384 - 102);
855 EXPECT_EQ(mask_a, mask_b);
856}
857
858TEST(index_mask, EqualsRangeEnd)
859{
860 IndexMask mask_a = IndexRange(16384 + 1);
861 IndexMask mask_b = IndexRange(16384 + 1);
862 EXPECT_EQ(mask_a, mask_b);
863}
864
865TEST(index_mask, NonEqualsRange)
866{
867 IndexMask mask_a = IndexRange(16384);
868 IndexMask mask_b = IndexRange(1, 16384);
869 EXPECT_NE(mask_a, mask_b);
870}
871
872TEST(index_mask, EqualsSelf)
873{
874 IndexMaskMemory memory;
875 IndexMask mask = IndexMask::from_union(IndexRange(16384), IndexRange(16384 * 3, 533), memory);
877}
878
880{
881 IndexMaskMemory memory;
882 IndexMask mask_a = IndexMask::from_union(IndexRange(16384), IndexRange(16384 * 3, 533), memory);
883 IndexMask mask_b = IndexMask::from_union(IndexRange(16384), IndexRange(16384 * 3, 533), memory);
884 EXPECT_EQ(mask_a, mask_b);
885}
886
887TEST(index_mask, NonEquals)
888{
889 IndexMaskMemory memory;
890 IndexMask mask_a = IndexMask::from_union(IndexRange(16384), IndexRange(16384 * 3, 533), memory);
892 IndexRange(55, 16384), IndexRange(16384 * 5, 533), memory);
893 EXPECT_NE(mask_a, mask_b);
894}
895
896TEST(index_mask, NotEqualsRangeAndIndices)
897{
898 IndexMaskMemory memory;
900 IndexRange(2040), IndexMask::from_indices<int>({2072, 2073, 2075}, memory), memory);
902 IndexRange(2040), IndexMask::from_indices<int>({2072, 2073 + 1, 2075}, memory), memory);
903
904 EXPECT_NE(mask_a, mask_b);
905}
906
908{
909 if (a.size() != b.size()) {
910 return false;
911 }
912 for (const int64_t i : a.index_range()) {
913 if (a[i] != b[i]) {
914 return false;
915 }
916 }
917 return true;
918}
919
920TEST(index_mask, ZippedForeachSelf)
921{
922 IndexMaskMemory memory;
923 IndexMask mask = IndexMask::from_initializers({IndexRange(500), 555, 699, 222, 900, 100},
924 memory);
925 {
926 int calls_num = 0;
928 EXPECT_FALSE(segments.is_empty());
929 calls_num++;
930 return true;
931 });
932 EXPECT_EQ(calls_num, 2);
933 }
934
935 {
936 int calls_num = 0;
938 EXPECT_FALSE(segments.is_empty());
939 EXPECT_TRUE(mask_segments_equals(segments[0], segments[1]));
940 calls_num++;
941 return true;
942 });
943 EXPECT_EQ(calls_num, 2);
944 }
945
946 {
947 int calls_num = 0;
949 EXPECT_FALSE(segments.is_empty());
950 EXPECT_TRUE(mask_segments_equals(segments[0], segments[1]));
951 EXPECT_TRUE(mask_segments_equals(segments[0], segments[2]));
952 calls_num++;
953 return true;
954 });
955 EXPECT_EQ(calls_num, 2);
956 }
957
958 {
959 int calls_num = 0;
961 {mask, mask, mask, mask}, [&](Span<IndexMaskSegment> segments) {
962 EXPECT_FALSE(segments.is_empty());
963 EXPECT_TRUE(mask_segments_equals(segments[0], segments[1]));
964 EXPECT_TRUE(mask_segments_equals(segments[0], segments[2]));
965 EXPECT_TRUE(mask_segments_equals(segments[0], segments[3]));
966 calls_num++;
967 return true;
968 });
969 EXPECT_EQ(calls_num, 2);
970 }
971}
972
973TEST(index_mask, ZippedForeachSameSegments)
974{
975 IndexMaskMemory memory;
976 IndexMask mask_a = IndexMask::from_initializers({0, 1, 2}, memory);
977 IndexMask mask_b = IndexMask::from_initializers({3, 4, 5}, memory);
978 IndexMask mask_c = IndexMask::from_initializers({6, 7, 8}, memory);
979 {
980 int calls_num = 0;
982 EXPECT_FALSE(segments.is_empty());
983 calls_num++;
984 return true;
985 });
986 EXPECT_EQ(calls_num, 1);
987 }
988 {
989 int calls_num = 0;
990 IndexMask::foreach_segment_zipped({mask_a, mask_b}, [&](Span<IndexMaskSegment> segments) {
991 EXPECT_FALSE(segments.is_empty());
992 EXPECT_EQ(segments[0].size(), segments[1].size());
993 EXPECT_FALSE(mask_segments_equals(segments[0], segments[1]));
994 calls_num++;
995 return true;
996 });
997 EXPECT_EQ(calls_num, 1);
998 }
999 {
1000 int calls_num = 0;
1002 {mask_a, mask_b, mask_c}, [&](Span<IndexMaskSegment> segments) {
1003 EXPECT_FALSE(segments.is_empty());
1004 EXPECT_EQ(segments[0].size(), segments[1].size());
1005 EXPECT_EQ(segments[0].size(), segments[2].size());
1006 EXPECT_FALSE(mask_segments_equals(segments[0], segments[1]));
1007 EXPECT_FALSE(mask_segments_equals(segments[0], segments[2]));
1008 EXPECT_FALSE(mask_segments_equals(segments[1], segments[2]));
1009 calls_num++;
1010 return true;
1011 });
1012 EXPECT_EQ(calls_num, 1);
1013 }
1014}
1015
1016TEST(index_mask, ZippedForeachEqual)
1017{
1019
1020 IndexMaskMemory memory;
1022 {{0, indices.take_front(5)}, {5, indices.take_front(5)}}, memory);
1024 {{0, indices.take_front(3)}, {3, indices.take_front(4)}, {7, indices.take_front(3)}},
1025 memory);
1026 IndexMask mask_c = IndexMask::from_segments({{0, indices.take_front(10)}}, memory);
1027
1028 int index = 0;
1029 Array<IndexMaskSegment> reference_segments{{0, indices.take_front(3)},
1030 {3, indices.take_front(2)},
1031 {5, indices.take_front(2)},
1032 {7, indices.take_front(3)}};
1033
1035 {mask_a, mask_b, mask_c}, [&](Span<IndexMaskSegment> segments) {
1036 EXPECT_TRUE(mask_segments_equals(reference_segments[index], segments[0]));
1037 EXPECT_TRUE(mask_segments_equals(reference_segments[index], segments[1]));
1038 EXPECT_TRUE(mask_segments_equals(reference_segments[index], segments[2]));
1039 index++;
1040 return true;
1041 });
1042 EXPECT_EQ(index, 4);
1043}
1044
1045TEST(index_mask, FromRepeatingEmpty)
1046{
1047 IndexMaskMemory memory;
1048 const IndexMask mask = IndexMask::from_repeating(IndexMask(), 100, 0, 10, memory);
1049 EXPECT_TRUE(mask.is_empty());
1050}
1051
1052TEST(index_mask, FromRepeatingSingle)
1053{
1054 IndexMaskMemory memory;
1055 const IndexMask mask = IndexMask::from_repeating(IndexMask(1), 5, 10, 2, memory);
1056 EXPECT_EQ(mask, IndexMask::from_initializers({2, 12, 22, 32, 42}, memory));
1057}
1058
1059TEST(index_mask, FromRepeatingSame)
1060{
1061 IndexMaskMemory memory;
1062 const IndexMask mask = IndexMask::from_indices<int>({4, 6, 7}, memory);
1063 const IndexMask repeated_mask = IndexMask::from_repeating(mask, 1, 100, 0, memory);
1064 EXPECT_EQ(mask, repeated_mask);
1065}
1066
1067TEST(index_mask, FromRepeatingMultiple)
1068{
1069 IndexMaskMemory memory;
1071 IndexMask::from_indices<int>({5, 6, 7, 50}, memory), 3, 100, 1000, memory);
1072 EXPECT_EQ(mask[0], 1005);
1073 EXPECT_EQ(mask[1], 1006);
1074 EXPECT_EQ(mask[2], 1007);
1075 EXPECT_EQ(mask[3], 1050);
1076 EXPECT_EQ(mask[4], 1105);
1077 EXPECT_EQ(mask[5], 1106);
1078 EXPECT_EQ(mask[6], 1107);
1079 EXPECT_EQ(mask[7], 1150);
1080 EXPECT_EQ(mask[8], 1205);
1081 EXPECT_EQ(mask[9], 1206);
1082 EXPECT_EQ(mask[10], 1207);
1083 EXPECT_EQ(mask[11], 1250);
1084}
1085
1086TEST(index_mask, FromRepeatingRangeFromSingle)
1087{
1088 IndexMaskMemory memory;
1089 const IndexMask mask = IndexMask::from_repeating(IndexMask(IndexRange(1)), 50'000, 1, 0, memory);
1090 EXPECT_EQ(*mask.to_range(), IndexRange(50'000));
1091}
1092
1093TEST(index_mask, FromRepeatingRangeFromRange)
1094{
1095 IndexMaskMemory memory;
1097 IndexMask(IndexRange(100)), 50'000, 100, 100, memory);
1098 EXPECT_EQ(*mask.to_range(), IndexRange(100, 5'000'000));
1099}
1100
1101TEST(index_mask, FromRepeatingEverySecond)
1102{
1103 IndexMaskMemory memory;
1104 const IndexMask mask = IndexMask::from_repeating(IndexMask(1), 500'000, 2, 0, memory);
1105 EXPECT_EQ(mask[0], 0);
1106 EXPECT_EQ(mask[1], 2);
1107 EXPECT_EQ(mask[2], 4);
1108 EXPECT_EQ(mask[3], 6);
1109 EXPECT_EQ(mask[20'000], 40'000);
1110}
1111
1112TEST(index_mask, FromRepeatingMultipleRanges)
1113{
1114 IndexMaskMemory memory;
1116 IndexMask::from_initializers({IndexRange(0, 100), IndexRange(10'000, 100)}, memory),
1117 5,
1118 100'000,
1119 0,
1120 memory);
1121 EXPECT_EQ(mask[0], 0);
1122 EXPECT_EQ(mask[1], 1);
1123 EXPECT_EQ(mask[2], 2);
1124 EXPECT_EQ(mask[100], 10'000);
1125 EXPECT_EQ(mask[101], 10'001);
1126 EXPECT_EQ(mask[102], 10'002);
1127 EXPECT_EQ(mask[200], 100'000);
1128 EXPECT_EQ(mask[201], 100'001);
1129 EXPECT_EQ(mask[202], 100'002);
1130 EXPECT_EQ(mask[300], 110'000);
1131 EXPECT_EQ(mask[301], 110'001);
1132 EXPECT_EQ(mask[302], 110'002);
1133}
1134
1135TEST(index_mask, FromRepeatingNoRepetitions)
1136{
1137 IndexMaskMemory memory;
1138 const IndexMask mask = IndexMask::from_repeating(IndexMask(IndexRange(5)), 0, 100, 0, memory);
1139 EXPECT_TRUE(mask.is_empty());
1140}
1141
1142TEST(index_mask, FromEveryNth)
1143{
1144 IndexMaskMemory memory;
1145 {
1146 const IndexMask mask = IndexMask::from_every_nth(2, 5, 0, memory);
1147 EXPECT_EQ(mask, IndexMask::from_initializers({0, 2, 4, 6, 8}, memory));
1148 }
1149 {
1150 const IndexMask mask = IndexMask::from_every_nth(3, 5, 100, memory);
1151 EXPECT_EQ(mask, IndexMask::from_initializers({100, 103, 106, 109, 112}, memory));
1152 }
1153 {
1154 const IndexMask mask = IndexMask::from_every_nth(4, 5, 0, memory);
1155 EXPECT_EQ(mask, IndexMask::from_initializers({0, 4, 8, 12, 16}, memory));
1156 }
1157 {
1158 const IndexMask mask = IndexMask::from_every_nth(10, 5, 100, memory);
1159 EXPECT_EQ(mask, IndexMask::from_initializers({100, 110, 120, 130, 140}, memory));
1160 }
1161 {
1162 const IndexMask mask = IndexMask::from_every_nth(1, 5, 100, memory);
1163 EXPECT_EQ(mask, IndexMask::from_initializers({100, 101, 102, 103, 104}, memory));
1164 }
1165 {
1166 const IndexMask mask = IndexMask::from_every_nth(100'000, 5, 0, memory);
1167 EXPECT_EQ(mask, IndexMask::from_initializers({0, 100'000, 200'000, 300'000, 400'000}, memory));
1168 }
1169}
1170
1172{
1173 IndexMaskMemory memory;
1174 {
1175 const IndexMask mask;
1176 const IndexMask shifted_mask = mask.shift(10, memory);
1177 EXPECT_TRUE(shifted_mask.is_empty());
1178 EXPECT_EQ(mask, shifted_mask);
1179 }
1180 {
1181 const IndexMask mask{IndexRange(100, 10)};
1182 const IndexMask shifted_mask = mask.shift(1000, memory);
1183 EXPECT_EQ(shifted_mask.size(), 10);
1184 EXPECT_EQ(shifted_mask[0], 1100);
1185 EXPECT_EQ(shifted_mask[9], 1109);
1186 }
1187 {
1188 const IndexMask mask = IndexMask::from_initializers({4, 6, 7, IndexRange(100, 100)}, memory);
1189 const IndexMask shifted_mask = mask.shift(1000, memory).shift(-1000, memory);
1190 EXPECT_EQ(mask, shifted_mask);
1191 }
1192 {
1193 const IndexMask mask{IndexRange(100, 10)};
1194 const IndexMask shifted_mask = mask.shift(0, memory);
1195 EXPECT_EQ(mask, shifted_mask);
1196 }
1197}
1198
1199TEST(index_mask, SliceAndShift)
1200{
1201 IndexMaskMemory memory;
1202 {
1203 const IndexMask mask{IndexRange(100, 10)};
1204 const IndexMask new_mask = mask.slice_and_shift(5, 5, 1000, memory);
1205 EXPECT_EQ(new_mask.size(), 5);
1206 EXPECT_EQ(new_mask[0], 1105);
1207 EXPECT_EQ(new_mask[1], 1106);
1208 }
1209 {
1210 const IndexMask mask = IndexMask::from_indices<int>({10, 100, 1'000, 10'000, 100'000}, memory);
1211 const IndexMask new_mask = mask.slice_and_shift(IndexRange(1, 4), -100, memory);
1212 EXPECT_EQ(new_mask.size(), 4);
1213 EXPECT_EQ(new_mask[0], 0);
1214 EXPECT_EQ(new_mask[1], 900);
1215 EXPECT_EQ(new_mask[2], 9'900);
1216 EXPECT_EQ(new_mask[3], 99'900);
1217 }
1218 {
1219 const IndexMask mask = IndexMask::from_indices<int>({10, 100}, memory);
1220 const IndexMask new_mask = mask.slice_and_shift(1, 0, 100, memory);
1221 EXPECT_TRUE(new_mask.is_empty());
1222 }
1223}
1224
1225TEST(index_mask, IndexRangeToMaskSegments)
1226{
1227 auto test_range = [](const IndexRange range) {
1228 Vector<IndexMaskSegment> segments;
1229 index_range_to_mask_segments(range, segments);
1230 IndexMaskMemory memory;
1231 const IndexMask mask = IndexMask::from_segments(segments, memory);
1232 const std::optional<IndexRange> new_range = mask.to_range();
1233 EXPECT_TRUE(new_range.has_value());
1234 EXPECT_EQ(range, *new_range);
1235 };
1236
1237 test_range(IndexRange::from_begin_size(1'000, 0));
1238
1239 test_range(IndexRange::from_begin_end_inclusive(0, 10));
1240 test_range(IndexRange::from_begin_end_inclusive(0, 10'000));
1241 test_range(IndexRange::from_begin_end_inclusive(0, 100'000));
1242 test_range(IndexRange::from_begin_end_inclusive(0, 1'000'000));
1243
1244 test_range(IndexRange::from_begin_end_inclusive(50'000, 1'000'000));
1245 test_range(IndexRange::from_begin_end_inclusive(999'999, 1'000'000));
1246 test_range(IndexRange::from_begin_end_inclusive(1'000'000, 1'000'000));
1247}
1248
1249TEST(index_mask, FromRanges)
1250{
1251 IndexMaskMemory memory;
1252 Array<int> data = {5, 100, 400, 500, 100'000, 200'000};
1253 OffsetIndices<int> offsets(data);
1254
1255 {
1256 const IndexMask mask = IndexMask::from_ranges(offsets, offsets.index_range(), memory);
1257 EXPECT_EQ(mask.size(), 199'995);
1258 EXPECT_EQ(*mask.to_range(), IndexRange::from_begin_end(5, 200'000));
1259 }
1260 {
1261 const IndexMask mask = IndexMask::from_ranges(offsets, IndexRange(0), memory);
1262 EXPECT_TRUE(mask.is_empty());
1263 }
1264 {
1265 const IndexMask mask = IndexMask::from_ranges(offsets, IndexRange(1), memory);
1266 EXPECT_EQ(*mask.to_range(), IndexRange::from_begin_end(5, 100));
1267 }
1268 {
1269 const IndexMask offsets_mask = IndexMask::from_indices(Span<int>({1, 4}), memory);
1270 const IndexMask mask = IndexMask::from_ranges(offsets, offsets_mask, memory);
1273 IndexRange::from_begin_end(100'000, 200'000)},
1274 memory));
1275 }
1276}
1277
1278} // namespace blender::index_mask::tests
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
BMesh const char void * data
long long int int64_t
unsigned long long int uint64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
static unsigned long seed
Definition btSoftBody.h:39
void append(const T &value)
T * end()
T * begin()
constexpr int64_t size() const
static constexpr IndexRange from_begin_end(const int64_t begin, const int64_t end)
static constexpr IndexRange from_begin_size(const int64_t begin, const int64_t size)
constexpr bool contains(int64_t value) const
constexpr IndexRange index_range() const
static constexpr IndexRange from_begin_end_inclusive(const int64_t begin, const int64_t last)
int64_t size() const
IndexRange index_range() const
int64_t size() const
Definition BLI_set.hh:587
bool contains(const Key &key) const
Definition BLI_set.hh:310
bool add(const Key &key)
Definition BLI_set.hh:248
int64_t size() const
void append(const T &value)
static IndexMask from_predicate(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, Fn &&predicate)
static IndexMask from_every_nth(int64_t n, int64_t indices_num, const int64_t initial_offset, IndexMaskMemory &memory)
IndexMask slice_content(IndexRange range) const
static IndexMask from_bits(BitSpan bits, IndexMaskMemory &memory)
static IndexMask from_repeating(const IndexMask &mask_to_repeat, int64_t repetitions, int64_t stride, int64_t initial_offset, IndexMaskMemory &memory)
static IndexMask from_union(const IndexMask &mask_a, const IndexMask &mask_b, IndexMaskMemory &memory)
static IndexMask from_ranges(OffsetIndices< T > offsets, const IndexMask &mask, IndexMaskMemory &memory)
static IndexMask from_intersection(const IndexMask &mask_a, const IndexMask &mask_b, IndexMaskMemory &memory)
static IndexMask from_indices(Span< T > indices, IndexMaskMemory &memory)
int64_t iterator_to_index(const RawMaskIterator &it) const
static IndexMask from_segments(Span< IndexMaskSegment > segments, IndexMaskMemory &memory)
static IndexMask from_initializers(const Span< Initializer > initializers, IndexMaskMemory &memory)
bool contains(int64_t query_index) const
IndexMask complement(const IndexMask &universe, IndexMaskMemory &memory) const
static IndexMask from_bools(Span< bool > bools, IndexMaskMemory &memory)
void foreach_index(Fn &&fn) const
RawMaskIterator index_to_iterator(int64_t index) const
static void foreach_segment_zipped(Span< IndexMask > masks, FunctionRef< bool(Span< IndexMaskSegment > segments)> fn)
static IndexMask from_difference(const IndexMask &mask_a, const IndexMask &mask_b, IndexMaskMemory &memory)
static ushort indices[]
#define INT64_MAX
uint pos
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
void invert(BitSpanT &&data)
static bool mask_segments_equals(const IndexMaskSegment &a, const IndexMaskSegment &b)
void index_range_to_mask_segments(const IndexRange range, Vector< IndexMaskSegment, N > &r_segments)
static constexpr int64_t max_segment_size
const std::array< int16_t, max_segment_size > & get_static_indices_array()
std::chrono::nanoseconds Nanoseconds
Definition BLI_timeit.hh:21
Clock::time_point TimePoint
Definition BLI_timeit.hh:20
i
Definition text_draw.cc:230