Blender V4.3
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" /* Keep last. */
19
21
22TEST(index_mask, IndicesToMask)
23{
24 IndexMaskMemory memory;
25 Array<int> data = {
26 5, 100, 16383, 16384, 16385, 20000, 20001, 50000, 50001, 50002, 100000, 101000};
27 IndexMask mask = IndexMask::from_indices<int>(data, memory);
28
29 EXPECT_EQ(mask.first(), 5);
30 EXPECT_EQ(mask.last(), 101000);
31 EXPECT_EQ(mask.min_array_size(), 101001);
32 EXPECT_EQ(mask.bounds(), IndexRange::from_begin_end_inclusive(5, 101000));
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);
335 EXPECT_EQ(mask.bounds(), IndexRange(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
375TEST(index_mask, FromDifference)
376{
377 {
378 IndexMaskMemory memory;
379 Array<int> data_a = {1, 2, 3};
380 IndexMask mask_a = IndexMask::from_indices<int>(data_a, memory);
381 Array<int> data_b = {2, 20000, 20001};
382 IndexMask mask_b = IndexMask::from_indices<int>(data_b, memory);
383
384 IndexMask mask_difference = IndexMask::from_difference(mask_a, mask_b, memory);
385
386 EXPECT_EQ(mask_difference.size(), 2);
387 EXPECT_EQ(mask_difference[0], 1);
388 EXPECT_EQ(mask_difference[1], 3);
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 = {1, 2, 3};
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_TRUE(mask_difference.is_empty());
400 }
401}
402
403TEST(index_mask, FromIntersection)
404{
405 {
406 IndexMaskMemory memory;
407 Array<int> data_a = {1, 2, 20000};
408 IndexMask mask_a = IndexMask::from_indices<int>(data_a, memory);
409 Array<int> data_b = {2, 20000, 20001};
410 IndexMask mask_b = IndexMask::from_indices<int>(data_b, memory);
411
412 IndexMask mask_intersection = IndexMask::from_intersection(mask_a, mask_b, memory);
413
414 EXPECT_EQ(mask_intersection.size(), 2);
415 EXPECT_EQ(mask_intersection[0], 2);
416 EXPECT_EQ(mask_intersection[1], 20000);
417 }
418 {
419 IndexMaskMemory memory;
420 Array<int> data_a = {1, 2, 3};
421 IndexMask mask_a = IndexMask::from_indices<int>(data_a, memory);
422 Array<int> data_b = {20000, 20001, 20002};
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_TRUE(mask_intersection.is_empty());
428 }
429}
430
431TEST(index_mask, DefaultConstructor)
432{
434 EXPECT_EQ(mask.size(), 0);
435 EXPECT_EQ(mask.min_array_size(), 0);
436 EXPECT_EQ(mask.bounds(), IndexRange());
437}
438
439TEST(index_mask, ForeachRange)
440{
441 IndexMaskMemory memory;
442 const IndexMask mask = IndexMask::from_indices<int>({2, 3, 4, 10, 40, 41}, memory);
443 Vector<IndexRange> ranges;
444 mask.foreach_range([&](const IndexRange range) { ranges.append(range); });
445
446 EXPECT_EQ(ranges.size(), 3);
447 EXPECT_EQ(ranges[0], IndexRange(2, 3));
448 EXPECT_EQ(ranges[1], IndexRange(10, 1));
449 EXPECT_EQ(ranges[2], IndexRange(40, 2));
450}
451
452TEST(index_mask, ToRange)
453{
454 IndexMaskMemory memory;
455 {
456 const IndexMask mask = IndexMask::from_indices<int>({4, 5, 6, 7}, memory);
457 EXPECT_TRUE(mask.to_range().has_value());
458 EXPECT_EQ(*mask.to_range(), IndexRange(4, 4));
459 }
460 {
461 const IndexMask mask = IndexMask::from_indices<int>({}, memory);
462 EXPECT_TRUE(mask.to_range().has_value());
463 EXPECT_EQ(*mask.to_range(), IndexRange());
464 }
465 {
466 const IndexMask mask = IndexMask::from_indices<int>({0, 1, 3, 4}, memory);
467 EXPECT_FALSE(mask.to_range().has_value());
468 }
469 {
470 const IndexRange range{16000, 40000};
471 const IndexMask mask{range};
472 EXPECT_TRUE(mask.to_range().has_value());
473 EXPECT_EQ(*mask.to_range(), range);
474 }
475}
476
477TEST(index_mask, ToBits)
478{
479 IndexMaskMemory memory;
480 {
481 const IndexMask mask = IndexMask::from_indices<int>({4, 5, 6, 7}, memory);
482 BitVector<> bits(mask.min_array_size());
483 mask.to_bits(bits);
484 EXPECT_EQ(bits[0].test(), false);
485 EXPECT_EQ(bits[1].test(), false);
486 EXPECT_EQ(bits[2].test(), false);
487 EXPECT_EQ(bits[3].test(), false);
488 EXPECT_EQ(bits[4].test(), true);
489 EXPECT_EQ(bits[5].test(), true);
490 EXPECT_EQ(bits[6].test(), true);
491 EXPECT_EQ(bits[7].test(), true);
492 }
493 {
494 const IndexMask mask = IndexMask::from_indices<int>({4, 5, 6, 7}, memory);
495 BitVector<> bits(mask.min_array_size());
496 bits[0].set();
497 bits[2].set();
498 mask.set_bits(bits);
499 EXPECT_EQ(bits[0].test(), true);
500 EXPECT_EQ(bits[1].test(), false);
501 EXPECT_EQ(bits[2].test(), true);
502 EXPECT_EQ(bits[3].test(), false);
503 EXPECT_EQ(bits[4].test(), true);
504 EXPECT_EQ(bits[5].test(), true);
505 EXPECT_EQ(bits[6].test(), true);
506 EXPECT_EQ(bits[7].test(), true);
507 }
508}
509
510TEST(index_mask, FromRange)
511{
512 const auto test_range = [](const IndexRange range) {
513 const IndexMask mask = range;
514 EXPECT_EQ(mask.to_range(), range);
515 };
516
517 test_range({0, 0});
518 test_range({0, 10});
519 test_range({0, 16384});
520 test_range({16320, 64});
521 test_range({16384, 64});
522 test_range({0, 100000});
523 test_range({100000, 100000});
524 test_range({688064, 64});
525}
526
527TEST(index_mask, FromPredicate)
528{
529 IndexMaskMemory memory;
530 {
531 const IndexRange range{20'000, 50'000};
533 IndexRange(100'000), GrainSize(1024), memory, [&](const int64_t i) {
534 return range.contains(i);
535 });
536 EXPECT_EQ(mask.to_range(), range);
537 }
538 {
539 const Vector<int64_t> indices = {0, 500, 20'000, 50'000};
541 IndexRange(100'000), GrainSize(1024), memory, [&](const int64_t i) {
542 return indices.contains(i);
543 });
544 EXPECT_EQ(mask.size(), indices.size());
545 Vector<int64_t> new_indices(mask.size());
546 mask.to_indices<int64_t>(new_indices);
547 EXPECT_EQ(indices, new_indices);
548 }
549}
550
551TEST(index_mask, IndexIteratorConversionFuzzy)
552{
554
556 indices.append(5);
557 for ([[maybe_unused]] const int64_t i : IndexRange(1000)) {
558 for ([[maybe_unused]] const int64_t j :
559 IndexRange(indices.last() + 1 + rng.get_int32(1000), rng.get_int32(64)))
560 {
561 indices.append(j);
562 }
563 }
564
565 IndexMaskMemory memory;
566 const IndexMask mask = IndexMask::from_indices<int64_t>(indices, memory);
567 EXPECT_EQ(mask.size(), indices.size());
568
569 for ([[maybe_unused]] const int64_t _ : IndexRange(100)) {
570 const int64_t index = rng.get_int32(int(indices.size()));
571 const RawMaskIterator it = mask.index_to_iterator(index);
572 EXPECT_EQ(mask[it], indices[index]);
573 const int64_t new_index = mask.iterator_to_index(it);
574 EXPECT_EQ(index, new_index);
575 }
576
577 for ([[maybe_unused]] const int64_t _ : IndexRange(100)) {
578 const int64_t start = rng.get_int32(int(indices.size() - 1));
579 const int64_t size = 1 + rng.get_int32(int(indices.size() - start - 1));
580 const IndexMask sub_mask = mask.slice(start, size);
581 const int64_t index = rng.get_int32(int(sub_mask.size()));
582 const RawMaskIterator it = sub_mask.index_to_iterator(index);
583 EXPECT_EQ(sub_mask[it], indices[start + index]);
584 const int64_t new_index = sub_mask.iterator_to_index(it);
585 EXPECT_EQ(index, new_index);
586 }
587
588 for ([[maybe_unused]] const int64_t _ : IndexRange(100)) {
589 const int64_t index = rng.get_int32(int(indices.size() - 1000));
590 for (const int64_t offset : {0, 1, 2, 100, 500}) {
591 const int64_t index_to_search = indices[index] + offset;
592 const bool contained = std::binary_search(indices.begin(), indices.end(), index_to_search);
593 const std::optional<RawMaskIterator> it = mask.find(index_to_search);
594 EXPECT_EQ(contained, it.has_value());
595 if (contained) {
596 EXPECT_EQ(index_to_search, mask[*it]);
597 }
598 }
599 }
600}
601
602TEST(index_mask, FromPredicateFuzzy)
603{
605 Set<int> values;
606
607 for ([[maybe_unused]] const int64_t _ : IndexRange(10000)) {
608 values.add(rng.get_int32(100'000));
609 }
610
611 IndexMaskMemory memory;
613 IndexRange(110'000), GrainSize(1024), memory, [&](const int64_t i) {
614 return values.contains(int(i));
615 });
616 EXPECT_EQ(mask.size(), values.size());
617 for (const int index : values) {
618 EXPECT_TRUE(mask.contains(index));
619 }
620 mask.foreach_index([&](const int64_t index, const int64_t pos) {
621 EXPECT_TRUE(values.contains(int(index)));
622 EXPECT_EQ(index, mask[pos]);
623 });
624}
625
626TEST(index_mask, Complement)
627{
628 IndexMaskMemory memory;
629 {
630 const IndexMask mask(0);
631 const IndexMask complement = mask.complement(IndexRange(100), memory);
632 EXPECT_EQ(100 - mask.size(), complement.size());
633 complement.foreach_index([&](const int64_t i) { EXPECT_FALSE(mask.contains(i)); });
634 mask.foreach_index([&](const int64_t i) { EXPECT_FALSE(complement.contains(i)); });
635 }
636 {
637 const IndexMask mask(10000);
638 const IndexMask complement = mask.complement(IndexRange(10000), memory);
639 EXPECT_EQ(10000 - mask.size(), complement.size());
640 complement.foreach_index([&](const int64_t i) { EXPECT_FALSE(mask.contains(i)); });
641 mask.foreach_index([&](const int64_t i) { EXPECT_FALSE(complement.contains(i)); });
642 }
643 {
644 const IndexMask mask(IndexRange(100, 900));
645 const IndexMask complement = mask.complement(IndexRange(1000), memory);
646 EXPECT_EQ(1000 - mask.size(), complement.size());
647 complement.foreach_index([&](const int64_t i) { EXPECT_FALSE(mask.contains(i)); });
648 mask.foreach_index([&](const int64_t i) { EXPECT_FALSE(complement.contains(i)); });
649 }
650 {
651 const IndexMask mask(IndexRange(0, 900));
652 const IndexMask complement = mask.complement(IndexRange(1000), memory);
653 EXPECT_EQ(1000 - mask.size(), complement.size());
654 complement.foreach_index([&](const int64_t i) { EXPECT_FALSE(mask.contains(i)); });
655 mask.foreach_index([&](const int64_t i) { EXPECT_FALSE(complement.contains(i)); });
656 }
657}
658
659TEST(index_mask, ComplementFuzzy)
660{
662
663 const int64_t mask_size = 100;
664 const int64_t iter_num = 100;
665 const int64_t universe_size = 110;
666
667 for (const int64_t iter : IndexRange(iter_num)) {
668 Set<int> values;
669 for ([[maybe_unused]] const int64_t _ : IndexRange(iter)) {
670 values.add(rng.get_int32(mask_size));
671 }
672 IndexMaskMemory memory;
674 IndexRange(mask_size), GrainSize(1024), memory, [&](const int64_t i) {
675 return values.contains(int(i));
676 });
677
678 const IndexMask complement = mask.complement(IndexRange(universe_size), memory);
679 EXPECT_EQ(universe_size - mask.size(), complement.size());
680 complement.foreach_index([&](const int64_t i) { EXPECT_FALSE(mask.contains(i)); });
681 mask.foreach_index([&](const int64_t i) { EXPECT_FALSE(complement.contains(i)); });
682 }
683}
684
685TEST(index_mask, OffsetIndexRangeFind)
686{
687 IndexMask mask = IndexRange(1, 2);
688 auto result = mask.find(1);
689 EXPECT_TRUE(result.has_value());
690 EXPECT_EQ(mask.iterator_to_index(*result), 0);
691 EXPECT_EQ(mask[0], 1);
692}
693
694TEST(index_mask, FindLargerEqual)
695{
696 IndexMaskMemory memory;
697 {
699 {0, 1, 3, 6, IndexRange(50, 50), IndexRange(100'000, 30)}, memory);
700 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(0)), 0);
701 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(1)), 1);
702 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(2)), 2);
703 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(3)), 2);
704 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(4)), 3);
705 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(5)), 3);
706 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(6)), 3);
707 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(7)), 4);
708 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(10)), 4);
709 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(40)), 4);
710 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(49)), 4);
711 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(50)), 4);
712 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(60)), 14);
713 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(70)), 24);
714 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(99)), 53);
715 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(100)), 54);
716 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(1'000)), 54);
717 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(10'000)), 54);
718 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(50'000)), 54);
719 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(100'000)), 54);
720 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(100'001)), 55);
721 EXPECT_FALSE(mask.find_larger_equal(101'000).has_value());
722 }
723 {
724 const IndexMask mask{IndexRange(10'000, 30'000)};
725 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(0)), 0);
726 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(50)), 0);
727 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(9'999)), 0);
728 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(10'000)), 0);
729 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(10'001)), 1);
730 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(39'998)), 29'998);
731 EXPECT_EQ(mask.iterator_to_index(*mask.find_larger_equal(39'999)), 29'999);
732 EXPECT_FALSE(mask.find_larger_equal(40'000).has_value());
733 EXPECT_FALSE(mask.find_larger_equal(40'001).has_value());
734 EXPECT_FALSE(mask.find_larger_equal(100'000).has_value());
735 }
736}
737
738TEST(index_mask, FindSmallerEqual)
739{
740 IndexMaskMemory memory;
741 {
743 {0, 1, 3, 6, IndexRange(50, 50), IndexRange(100'000, 30)}, memory);
744 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(0)), 0);
745 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(1)), 1);
746 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(2)), 1);
747 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(3)), 2);
748 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(4)), 2);
749 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(5)), 2);
750 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(6)), 3);
751 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(7)), 3);
752 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(10)), 3);
753 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(40)), 3);
754 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(49)), 3);
755 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(50)), 4);
756 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(60)), 14);
757 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(70)), 24);
758 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(99)), 53);
759 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(100)), 53);
760 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(1'000)), 53);
761 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(10'000)), 53);
762 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(50'000)), 53);
763 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(100'000)), 54);
764 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(100'001)), 55);
765 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(101'000)), 83);
766 }
767 {
768 const IndexMask mask{IndexRange(10'000, 30'000)};
769 EXPECT_FALSE(mask.find_smaller_equal(0).has_value());
770 EXPECT_FALSE(mask.find_smaller_equal(1).has_value());
771 EXPECT_FALSE(mask.find_smaller_equal(50).has_value());
772 EXPECT_FALSE(mask.find_smaller_equal(9'999).has_value());
773 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(10'000)), 0);
774 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(10'001)), 1);
775 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(39'998)), 29'998);
776 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(39'999)), 29'999);
777 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(40'000)), 29'999);
778 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(40'001)), 29'999);
779 EXPECT_EQ(mask.iterator_to_index(*mask.find_smaller_equal(100'000)), 29'999);
780 }
781}
782
783TEST(index_mask, SliceContent)
784{
785 IndexMaskMemory memory;
786 {
787 const IndexMask mask;
788 EXPECT_TRUE(mask.slice_content(IndexRange(50, 10)).is_empty());
789 }
790 {
791 const IndexMask mask{IndexRange(10, 90)};
792 const IndexMask a = mask.slice_content(IndexRange(30));
793 EXPECT_EQ(a.size(), 20);
794 const IndexMask b = mask.slice_content(IndexRange(10, 90));
795 EXPECT_EQ(b.size(), 90);
796 const IndexMask c = mask.slice_content(IndexRange(80, 100));
797 EXPECT_EQ(c.size(), 20);
798 const IndexMask d = mask.slice_content(IndexRange(1000, 100));
799 EXPECT_EQ(d.size(), 0);
800 }
801 {
803 {4, 5, 100, 1'000, 10'000, 20'000, 25'000, 100'000}, memory);
804 EXPECT_EQ(mask.slice_content(IndexRange(10)).size(), 2);
805 EXPECT_EQ(mask.slice_content(IndexRange(200)).size(), 3);
806 EXPECT_EQ(mask.slice_content(IndexRange(2'000)).size(), 4);
807 EXPECT_EQ(mask.slice_content(IndexRange(10'000)).size(), 4);
808 EXPECT_EQ(mask.slice_content(IndexRange(10'001)).size(), 5);
809 EXPECT_EQ(mask.slice_content(IndexRange(1'000'000)).size(), 8);
810 EXPECT_EQ(mask.slice_content(IndexRange(10'000, 100'000)).size(), 4);
811 EXPECT_EQ(mask.slice_content(IndexRange(1'001, 100'000)).size(), 4);
812 EXPECT_EQ(mask.slice_content(IndexRange(1'000, 100'000)).size(), 5);
813 EXPECT_EQ(mask.slice_content(IndexRange(1'000, 99'000)).size(), 4);
814 EXPECT_EQ(mask.slice_content(IndexRange(1'000, 10'000)).size(), 2);
815 }
816}
817
818TEST(index_mask, EqualsRangeSelf)
819{
820 IndexMask mask = IndexRange(16384);
821 EXPECT_EQ(mask, mask);
822}
823
824TEST(index_mask, EqualsRange)
825{
826 IndexMask mask_a = IndexRange(16384);
827 IndexMask mask_b = IndexRange(16384);
828 EXPECT_EQ(mask_a, mask_b);
829}
830
831TEST(index_mask, EqualsRangeLarge)
832{
833 IndexMask mask_a = IndexRange(96384);
834 IndexMask mask_b = IndexRange(96384);
835 EXPECT_EQ(mask_a, mask_b);
836}
837
838TEST(index_mask, EqualsRangeBegin)
839{
840 IndexMask mask_a = IndexRange(102, 16384 - 102);
841 IndexMask mask_b = IndexRange(102, 16384 - 102);
842 EXPECT_EQ(mask_a, mask_b);
843}
844
845TEST(index_mask, EqualsRangeEnd)
846{
847 IndexMask mask_a = IndexRange(16384 + 1);
848 IndexMask mask_b = IndexRange(16384 + 1);
849 EXPECT_EQ(mask_a, mask_b);
850}
851
852TEST(index_mask, NonEqualsRange)
853{
854 IndexMask mask_a = IndexRange(16384);
855 IndexMask mask_b = IndexRange(1, 16384);
856 EXPECT_NE(mask_a, mask_b);
857}
858
859TEST(index_mask, EqualsSelf)
860{
861 IndexMaskMemory memory;
862 IndexMask mask = IndexMask::from_union(IndexRange(16384), IndexRange(16384 * 3, 533), memory);
863 EXPECT_EQ(mask, mask);
864}
865
866TEST(index_mask, Equals)
867{
868 IndexMaskMemory memory;
869 IndexMask mask_a = IndexMask::from_union(IndexRange(16384), IndexRange(16384 * 3, 533), memory);
870 IndexMask mask_b = IndexMask::from_union(IndexRange(16384), IndexRange(16384 * 3, 533), memory);
871 EXPECT_EQ(mask_a, mask_b);
872}
873
874TEST(index_mask, NonEquals)
875{
876 IndexMaskMemory memory;
877 IndexMask mask_a = IndexMask::from_union(IndexRange(16384), IndexRange(16384 * 3, 533), memory);
879 IndexRange(55, 16384), IndexRange(16384 * 5, 533), memory);
880 EXPECT_NE(mask_a, mask_b);
881}
882
883TEST(index_mask, NotEqualsRangeAndIndices)
884{
885 IndexMaskMemory memory;
887 IndexRange(2040), IndexMask::from_indices<int>({2072, 2073, 2075}, memory), memory);
889 IndexRange(2040), IndexMask::from_indices<int>({2072, 2073 + 1, 2075}, memory), memory);
890
891 EXPECT_NE(mask_a, mask_b);
892}
893
895{
896 if (a.size() != b.size()) {
897 return false;
898 }
899 for (const int64_t i : a.index_range()) {
900 if (a[i] != b[i]) {
901 return false;
902 }
903 }
904 return true;
905}
906
907TEST(index_mask, ZippedForeachSelf)
908{
909 IndexMaskMemory memory;
910 IndexMask mask = IndexMask::from_initializers({IndexRange(500), 555, 699, 222, 900, 100},
911 memory);
912 {
913 int calls_num = 0;
915 EXPECT_FALSE(segments.is_empty());
916 calls_num++;
917 return true;
918 });
919 EXPECT_EQ(calls_num, 2);
920 }
921
922 {
923 int calls_num = 0;
925 EXPECT_FALSE(segments.is_empty());
926 EXPECT_TRUE(mask_segments_equals(segments[0], segments[1]));
927 calls_num++;
928 return true;
929 });
930 EXPECT_EQ(calls_num, 2);
931 }
932
933 {
934 int calls_num = 0;
936 EXPECT_FALSE(segments.is_empty());
937 EXPECT_TRUE(mask_segments_equals(segments[0], segments[1]));
938 EXPECT_TRUE(mask_segments_equals(segments[0], segments[2]));
939 calls_num++;
940 return true;
941 });
942 EXPECT_EQ(calls_num, 2);
943 }
944
945 {
946 int calls_num = 0;
948 {mask, mask, mask, mask}, [&](Span<IndexMaskSegment> segments) {
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 EXPECT_TRUE(mask_segments_equals(segments[0], segments[3]));
953 calls_num++;
954 return true;
955 });
956 EXPECT_EQ(calls_num, 2);
957 }
958}
959
960TEST(index_mask, ZippedForeachSameSegments)
961{
962 IndexMaskMemory memory;
963 IndexMask mask_a = IndexMask::from_initializers({0, 1, 2}, memory);
964 IndexMask mask_b = IndexMask::from_initializers({3, 4, 5}, memory);
965 IndexMask mask_c = IndexMask::from_initializers({6, 7, 8}, memory);
966 {
967 int calls_num = 0;
969 EXPECT_FALSE(segments.is_empty());
970 calls_num++;
971 return true;
972 });
973 EXPECT_EQ(calls_num, 1);
974 }
975 {
976 int calls_num = 0;
977 IndexMask::foreach_segment_zipped({mask_a, mask_b}, [&](Span<IndexMaskSegment> segments) {
978 EXPECT_FALSE(segments.is_empty());
979 EXPECT_EQ(segments[0].size(), segments[1].size());
980 EXPECT_FALSE(mask_segments_equals(segments[0], segments[1]));
981 calls_num++;
982 return true;
983 });
984 EXPECT_EQ(calls_num, 1);
985 }
986 {
987 int calls_num = 0;
989 {mask_a, mask_b, mask_c}, [&](Span<IndexMaskSegment> segments) {
990 EXPECT_FALSE(segments.is_empty());
991 EXPECT_EQ(segments[0].size(), segments[1].size());
992 EXPECT_EQ(segments[0].size(), segments[2].size());
993 EXPECT_FALSE(mask_segments_equals(segments[0], segments[1]));
994 EXPECT_FALSE(mask_segments_equals(segments[0], segments[2]));
995 EXPECT_FALSE(mask_segments_equals(segments[1], segments[2]));
996 calls_num++;
997 return true;
998 });
999 EXPECT_EQ(calls_num, 1);
1000 }
1001}
1002
1003TEST(index_mask, ZippedForeachEqual)
1004{
1006
1007 IndexMaskMemory memory;
1009 {{0, indices.take_front(5)}, {5, indices.take_front(5)}}, memory);
1011 {{0, indices.take_front(3)}, {3, indices.take_front(4)}, {7, indices.take_front(3)}},
1012 memory);
1013 IndexMask mask_c = IndexMask::from_segments({{0, indices.take_front(10)}}, memory);
1014
1015 int index = 0;
1016 Array<IndexMaskSegment> reference_segments{{0, indices.take_front(3)},
1017 {3, indices.take_front(2)},
1018 {5, indices.take_front(2)},
1019 {7, indices.take_front(3)}};
1020
1022 {mask_a, mask_b, mask_c}, [&](Span<IndexMaskSegment> segments) {
1023 EXPECT_TRUE(mask_segments_equals(reference_segments[index], segments[0]));
1024 EXPECT_TRUE(mask_segments_equals(reference_segments[index], segments[1]));
1025 EXPECT_TRUE(mask_segments_equals(reference_segments[index], segments[2]));
1026 index++;
1027 return true;
1028 });
1029 EXPECT_EQ(index, 4);
1030}
1031
1032TEST(index_mask, FromRepeatingEmpty)
1033{
1034 IndexMaskMemory memory;
1035 const IndexMask mask = IndexMask::from_repeating(IndexMask(), 100, 0, 10, memory);
1036 EXPECT_TRUE(mask.is_empty());
1037}
1038
1039TEST(index_mask, FromRepeatingSingle)
1040{
1041 IndexMaskMemory memory;
1042 const IndexMask mask = IndexMask::from_repeating(IndexMask(1), 5, 10, 2, memory);
1043 EXPECT_EQ(mask, IndexMask::from_initializers({2, 12, 22, 32, 42}, memory));
1044}
1045
1046TEST(index_mask, FromRepeatingSame)
1047{
1048 IndexMaskMemory memory;
1049 const IndexMask mask = IndexMask::from_indices<int>({4, 6, 7}, memory);
1050 const IndexMask repeated_mask = IndexMask::from_repeating(mask, 1, 100, 0, memory);
1051 EXPECT_EQ(mask, repeated_mask);
1052}
1053
1054TEST(index_mask, FromRepeatingMultiple)
1055{
1056 IndexMaskMemory memory;
1058 IndexMask::from_indices<int>({5, 6, 7, 50}, memory), 3, 100, 1000, memory);
1059 EXPECT_EQ(mask[0], 1005);
1060 EXPECT_EQ(mask[1], 1006);
1061 EXPECT_EQ(mask[2], 1007);
1062 EXPECT_EQ(mask[3], 1050);
1063 EXPECT_EQ(mask[4], 1105);
1064 EXPECT_EQ(mask[5], 1106);
1065 EXPECT_EQ(mask[6], 1107);
1066 EXPECT_EQ(mask[7], 1150);
1067 EXPECT_EQ(mask[8], 1205);
1068 EXPECT_EQ(mask[9], 1206);
1069 EXPECT_EQ(mask[10], 1207);
1070 EXPECT_EQ(mask[11], 1250);
1071}
1072
1073TEST(index_mask, FromRepeatingRangeFromSingle)
1074{
1075 IndexMaskMemory memory;
1076 const IndexMask mask = IndexMask::from_repeating(IndexMask(IndexRange(1)), 50'000, 1, 0, memory);
1077 EXPECT_EQ(*mask.to_range(), IndexRange(50'000));
1078}
1079
1080TEST(index_mask, FromRepeatingRangeFromRange)
1081{
1082 IndexMaskMemory memory;
1084 IndexMask(IndexRange(100)), 50'000, 100, 100, memory);
1085 EXPECT_EQ(*mask.to_range(), IndexRange(100, 5'000'000));
1086}
1087
1088TEST(index_mask, FromRepeatingEverySecond)
1089{
1090 IndexMaskMemory memory;
1091 const IndexMask mask = IndexMask::from_repeating(IndexMask(1), 500'000, 2, 0, memory);
1092 EXPECT_EQ(mask[0], 0);
1093 EXPECT_EQ(mask[1], 2);
1094 EXPECT_EQ(mask[2], 4);
1095 EXPECT_EQ(mask[3], 6);
1096 EXPECT_EQ(mask[20'000], 40'000);
1097}
1098
1099TEST(index_mask, FromRepeatingMultipleRanges)
1100{
1101 IndexMaskMemory memory;
1103 IndexMask::from_initializers({IndexRange(0, 100), IndexRange(10'000, 100)}, memory),
1104 5,
1105 100'000,
1106 0,
1107 memory);
1108 EXPECT_EQ(mask[0], 0);
1109 EXPECT_EQ(mask[1], 1);
1110 EXPECT_EQ(mask[2], 2);
1111 EXPECT_EQ(mask[100], 10'000);
1112 EXPECT_EQ(mask[101], 10'001);
1113 EXPECT_EQ(mask[102], 10'002);
1114 EXPECT_EQ(mask[200], 100'000);
1115 EXPECT_EQ(mask[201], 100'001);
1116 EXPECT_EQ(mask[202], 100'002);
1117 EXPECT_EQ(mask[300], 110'000);
1118 EXPECT_EQ(mask[301], 110'001);
1119 EXPECT_EQ(mask[302], 110'002);
1120}
1121
1122TEST(index_mask, FromRepeatingNoRepetitions)
1123{
1124 IndexMaskMemory memory;
1125 const IndexMask mask = IndexMask::from_repeating(IndexMask(IndexRange(5)), 0, 100, 0, memory);
1126 EXPECT_TRUE(mask.is_empty());
1127}
1128
1129TEST(index_mask, FromEveryNth)
1130{
1131 IndexMaskMemory memory;
1132 {
1133 const IndexMask mask = IndexMask::from_every_nth(2, 5, 0, memory);
1134 EXPECT_EQ(mask, IndexMask::from_initializers({0, 2, 4, 6, 8}, memory));
1135 }
1136 {
1137 const IndexMask mask = IndexMask::from_every_nth(3, 5, 100, memory);
1138 EXPECT_EQ(mask, IndexMask::from_initializers({100, 103, 106, 109, 112}, memory));
1139 }
1140 {
1141 const IndexMask mask = IndexMask::from_every_nth(4, 5, 0, memory);
1142 EXPECT_EQ(mask, IndexMask::from_initializers({0, 4, 8, 12, 16}, memory));
1143 }
1144 {
1145 const IndexMask mask = IndexMask::from_every_nth(10, 5, 100, memory);
1146 EXPECT_EQ(mask, IndexMask::from_initializers({100, 110, 120, 130, 140}, memory));
1147 }
1148 {
1149 const IndexMask mask = IndexMask::from_every_nth(1, 5, 100, memory);
1150 EXPECT_EQ(mask, IndexMask::from_initializers({100, 101, 102, 103, 104}, memory));
1151 }
1152 {
1153 const IndexMask mask = IndexMask::from_every_nth(100'000, 5, 0, memory);
1154 EXPECT_EQ(mask, IndexMask::from_initializers({0, 100'000, 200'000, 300'000, 400'000}, memory));
1155 }
1156}
1157
1158TEST(index_mask, Shift)
1159{
1160 IndexMaskMemory memory;
1161 {
1162 const IndexMask mask;
1163 const IndexMask shifted_mask = mask.shift(10, memory);
1164 EXPECT_TRUE(shifted_mask.is_empty());
1165 EXPECT_EQ(mask, shifted_mask);
1166 }
1167 {
1168 const IndexMask mask{IndexRange(100, 10)};
1169 const IndexMask shifted_mask = mask.shift(1000, memory);
1170 EXPECT_EQ(shifted_mask.size(), 10);
1171 EXPECT_EQ(shifted_mask[0], 1100);
1172 EXPECT_EQ(shifted_mask[9], 1109);
1173 }
1174 {
1175 const IndexMask mask = IndexMask::from_initializers({4, 6, 7, IndexRange(100, 100)}, memory);
1176 const IndexMask shifted_mask = mask.shift(1000, memory).shift(-1000, memory);
1177 EXPECT_EQ(mask, shifted_mask);
1178 }
1179 {
1180 const IndexMask mask{IndexRange(100, 10)};
1181 const IndexMask shifted_mask = mask.shift(0, memory);
1182 EXPECT_EQ(mask, shifted_mask);
1183 }
1184}
1185
1186TEST(index_mask, SliceAndShift)
1187{
1188 IndexMaskMemory memory;
1189 {
1190 const IndexMask mask{IndexRange(100, 10)};
1191 const IndexMask new_mask = mask.slice_and_shift(5, 5, 1000, memory);
1192 EXPECT_EQ(new_mask.size(), 5);
1193 EXPECT_EQ(new_mask[0], 1105);
1194 EXPECT_EQ(new_mask[1], 1106);
1195 }
1196 {
1197 const IndexMask mask = IndexMask::from_indices<int>({10, 100, 1'000, 10'000, 100'000}, memory);
1198 const IndexMask new_mask = mask.slice_and_shift(IndexRange(1, 4), -100, memory);
1199 EXPECT_EQ(new_mask.size(), 4);
1200 EXPECT_EQ(new_mask[0], 0);
1201 EXPECT_EQ(new_mask[1], 900);
1202 EXPECT_EQ(new_mask[2], 9'900);
1203 EXPECT_EQ(new_mask[3], 99'900);
1204 }
1205 {
1206 const IndexMask mask = IndexMask::from_indices<int>({10, 100}, memory);
1207 const IndexMask new_mask = mask.slice_and_shift(1, 0, 100, memory);
1208 EXPECT_TRUE(new_mask.is_empty());
1209 }
1210}
1211
1212} // namespace blender::index_mask::tests
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
typedef double(DMatrix)[4][4]
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
static unsigned long seed
Definition btSoftBody.h:39
constexpr int64_t size() const
static constexpr IndexRange from_begin_end(const int64_t begin, const int64_t end)
constexpr IndexRange index_range() const
static constexpr IndexRange from_begin_end_inclusive(const int64_t begin, const int64_t last)
bool add(const Key &key)
Definition BLI_set.hh:248
int64_t size() const
void append(const T &value)
IndexMask slice_and_shift(IndexRange range, int64_t offset, IndexMaskMemory &memory) const
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)
IndexMask shift(const int64_t offset, IndexMaskMemory &memory) const
IndexMask slice(IndexRange range) const
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)
local_group_size(16, 16) .push_constant(Type b
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
static ushort indices[]
IndexRange range
ccl_device_inline float4 mask(const int4 mask, const float4 a)
void invert(BitSpanT &&data)
static bool mask_segments_equals(const IndexMaskSegment &a, const IndexMaskSegment &b)
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:16
Clock::time_point TimePoint
Definition BLI_timeit.hh:15
unsigned int uint32_t
Definition stdint.h:80
__int64 int64_t
Definition stdint.h:89
#define INT64_MAX
Definition stdint.h:139
unsigned __int64 uint64_t
Definition stdint.h:90