Blender V4.3
BLI_map_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 <memory>
6#include <unordered_map>
7
8#include "testing/testing.h"
9
11#include "BLI_map.hh"
12#include "BLI_rand.h"
13#include "BLI_set.hh"
14#include "BLI_timeit.hh"
15#include "BLI_vector.hh"
16
17#include "BLI_strict_flags.h" /* Keep last. */
18
19namespace blender::tests {
20
21TEST(map, DefaultConstructor)
22{
24 EXPECT_EQ(map.size(), 0);
25 EXPECT_TRUE(map.is_empty());
26}
27
28TEST(map, AddIncreasesSize)
29{
31 EXPECT_EQ(map.size(), 0);
32 EXPECT_TRUE(map.is_empty());
33 map.add(2, 5.0f);
34 EXPECT_EQ(map.size(), 1);
35 EXPECT_FALSE(map.is_empty());
36 map.add(6, 2.0f);
37 EXPECT_EQ(map.size(), 2);
38 EXPECT_FALSE(map.is_empty());
39}
40
41TEST(map, Contains)
42{
44 EXPECT_FALSE(map.contains(4));
45 map.add(5, 6.0f);
46 EXPECT_FALSE(map.contains(4));
47 map.add(4, 2.0f);
48 EXPECT_TRUE(map.contains(4));
49}
50
51TEST(map, LookupExisting)
52{
54 map.add(2, 6.0f);
55 map.add(4, 1.0f);
56 EXPECT_EQ(map.lookup(2), 6.0f);
57 EXPECT_EQ(map.lookup(4), 1.0f);
58}
59
60TEST(map, LookupNotExisting)
61{
63 map.add(2, 4.0f);
64 map.add(1, 1.0f);
65 EXPECT_EQ(map.lookup_ptr(0), nullptr);
66 EXPECT_EQ(map.lookup_ptr(5), nullptr);
67}
68
69TEST(map, AddMany)
70{
71 Map<int, int> map;
72 for (int i = 0; i < 100; i++) {
73 map.add(i * 30, i);
74 map.add(i * 31, i);
75 }
76}
77
78TEST(map, PopItem)
79{
81 map.add(2, 3.0f);
82 map.add(1, 9.0f);
83 EXPECT_TRUE(map.contains(2));
84 EXPECT_TRUE(map.contains(1));
85
86 EXPECT_EQ(map.pop(1), 9.0f);
87 EXPECT_TRUE(map.contains(2));
88 EXPECT_FALSE(map.contains(1));
89
90 EXPECT_EQ(map.pop(2), 3.0f);
91 EXPECT_FALSE(map.contains(2));
92 EXPECT_FALSE(map.contains(1));
93}
94
95TEST(map, PopTry)
96{
97 Map<int, int> map;
98 map.add(1, 5);
99 map.add(2, 7);
100 EXPECT_EQ(map.size(), 2);
101 std::optional<int> value = map.pop_try(4);
102 EXPECT_EQ(map.size(), 2);
103 EXPECT_FALSE(value.has_value());
104 value = map.pop_try(2);
105 EXPECT_EQ(map.size(), 1);
106 EXPECT_TRUE(value.has_value());
107 EXPECT_EQ(*value, 7);
108 EXPECT_EQ(*map.pop_try(1), 5);
109 EXPECT_EQ(map.size(), 0);
110}
111
112TEST(map, PopDefault)
113{
114 Map<int, int> map;
115 map.add(1, 4);
116 map.add(2, 7);
117 map.add(3, 8);
118 EXPECT_EQ(map.size(), 3);
119 EXPECT_EQ(map.pop_default(4, 10), 10);
120 EXPECT_EQ(map.size(), 3);
121 EXPECT_EQ(map.pop_default(1, 10), 4);
122 EXPECT_EQ(map.size(), 2);
123 EXPECT_EQ(map.pop_default(2, 20), 7);
124 EXPECT_EQ(map.size(), 1);
125 EXPECT_EQ(map.pop_default(2, 20), 20);
126 EXPECT_EQ(map.size(), 1);
127 EXPECT_EQ(map.pop_default(3, 0), 8);
128 EXPECT_EQ(map.size(), 0);
129}
130
131TEST(map, PopItemMany)
132{
133 Map<int, int> map;
134 for (int i = 0; i < 100; i++) {
135 map.add_new(i, i);
136 }
137 for (int i = 25; i < 80; i++) {
138 EXPECT_EQ(map.pop(i), i);
139 }
140 for (int i = 0; i < 100; i++) {
141 EXPECT_EQ(map.contains(i), i < 25 || i >= 80);
142 }
143}
144
145TEST(map, ValueIterator)
146{
147 Map<int, float> map;
148 map.add(3, 5.0f);
149 map.add(1, 2.0f);
150 map.add(7, -2.0f);
151
152 blender::Set<float> values;
153
154 int iterations = 0;
155 for (float value : map.values()) {
156 values.add(value);
157 iterations++;
158 }
159
160 EXPECT_EQ(iterations, 3);
161 EXPECT_TRUE(values.contains(5.0f));
162 EXPECT_TRUE(values.contains(-2.0f));
163 EXPECT_TRUE(values.contains(2.0f));
164}
165
166TEST(map, KeyIterator)
167{
168 Map<int, float> map;
169 map.add(6, 3.0f);
170 map.add(2, 4.0f);
171 map.add(1, 3.0f);
172
174
175 int iterations = 0;
176 for (int key : map.keys()) {
177 keys.add(key);
178 iterations++;
179 }
180
181 EXPECT_EQ(iterations, 3);
182 EXPECT_TRUE(keys.contains(1));
183 EXPECT_TRUE(keys.contains(2));
184 EXPECT_TRUE(keys.contains(6));
185}
186
188{
189 Map<int, float> map;
190 map.add(5, 3.0f);
191 map.add(2, 9.0f);
192 map.add(1, 0.0f);
193
195 blender::Set<float> values;
196
197 int iterations = 0;
198 const Map<int, float> &const_map = map;
199 for (auto item : const_map.items()) {
200 keys.add(item.key);
201 values.add(item.value);
202 iterations++;
203 }
204
205 EXPECT_EQ(iterations, 3);
206 EXPECT_TRUE(keys.contains(5));
207 EXPECT_TRUE(keys.contains(2));
208 EXPECT_TRUE(keys.contains(1));
209 EXPECT_TRUE(values.contains(3.0f));
210 EXPECT_TRUE(values.contains(9.0f));
211 EXPECT_TRUE(values.contains(0.0f));
212}
213
214TEST(map, MutableValueIterator)
215{
216 Map<int, int> map;
217 map.add(3, 6);
218 map.add(2, 1);
219
220 for (int &value : map.values()) {
221 value += 10;
222 }
223
224 EXPECT_EQ(map.lookup(3), 16);
225 EXPECT_EQ(map.lookup(2), 11);
226}
227
228TEST(map, MutableItemIterator)
229{
230 Map<int, int> map;
231 map.add(3, 6);
232 map.add(2, 1);
233
234 for (auto item : map.items()) {
235 item.value += item.key;
236 }
237
238 EXPECT_EQ(map.lookup(3), 9.0f);
239 EXPECT_EQ(map.lookup(2), 3.0f);
240}
241
242TEST(map, MutableItemToItemConversion)
243{
244 Map<int, int> map;
245 map.add(3, 6);
246 map.add(2, 1);
247
248 Vector<int> keys, values;
249 for (MapItem<int, int> item : map.items()) {
250 keys.append(item.key);
251 values.append(item.value);
252 }
253
254 EXPECT_EQ(keys.size(), 2);
255 EXPECT_EQ(values.size(), 2);
256 EXPECT_TRUE(keys.contains(3));
257 EXPECT_TRUE(keys.contains(2));
258 EXPECT_TRUE(values.contains(6));
259 EXPECT_TRUE(values.contains(1));
260}
261
262static float return_42()
263{
264 return 42.0f;
265}
266
267TEST(map, LookupOrAddCB_SeparateFunction)
268{
269 Map<int, float> map;
270 EXPECT_EQ(map.lookup_or_add_cb(0, return_42), 42.0f);
271 EXPECT_EQ(map.lookup(0), 42);
272
273 map.keys();
274}
275
276TEST(map, LookupOrAddCB_Lambdas)
277{
278 Map<int, float> map;
279 auto lambda1 = []() { return 11.0f; };
280 EXPECT_EQ(map.lookup_or_add_cb(0, lambda1), 11.0f);
281 auto lambda2 = []() { return 20.0f; };
282 EXPECT_EQ(map.lookup_or_add_cb(1, lambda2), 20.0f);
283
284 EXPECT_EQ(map.lookup_or_add_cb(0, lambda2), 11.0f);
285 EXPECT_EQ(map.lookup_or_add_cb(1, lambda1), 20.0f);
286}
287
288TEST(map, AddOrModify)
289{
290 Map<int, float> map;
291 auto create_func = [](float *value) {
292 *value = 10.0f;
293 return true;
294 };
295 auto modify_func = [](float *value) {
296 *value += 5;
297 return false;
298 };
299 EXPECT_TRUE(map.add_or_modify(1, create_func, modify_func));
300 EXPECT_EQ(map.lookup(1), 10.0f);
301 EXPECT_FALSE(map.add_or_modify(1, create_func, modify_func));
302 EXPECT_EQ(map.lookup(1), 15.0f);
303}
304
305TEST(map, AddOrModifyReference)
306{
308 auto create_func = [](std::unique_ptr<int> *value) -> int & {
309 new (value) std::unique_ptr<int>(new int{10});
310 return **value;
311 };
312 auto modify_func = [](std::unique_ptr<int> *value) -> int & {
313 **value += 5;
314 return **value;
315 };
316 EXPECT_EQ(map.add_or_modify(1, create_func, modify_func), 10);
317 int &a = map.add_or_modify(1, create_func, modify_func);
318 EXPECT_EQ(a, 15);
319 a = 100;
320 EXPECT_EQ(*map.lookup(1), 100);
321}
322
323TEST(map, AddOverwrite)
324{
325 Map<int, float> map;
326 EXPECT_FALSE(map.contains(3));
327 EXPECT_TRUE(map.add_overwrite(3, 6.0f));
328 EXPECT_EQ(map.lookup(3), 6.0f);
329 EXPECT_FALSE(map.add_overwrite(3, 7.0f));
330 EXPECT_EQ(map.lookup(3), 7.0f);
331 EXPECT_FALSE(map.add(3, 8.0f));
332 EXPECT_EQ(map.lookup(3), 7.0f);
333}
334
335TEST(map, LookupOrAddDefault)
336{
337 Map<int, float> map;
338 map.lookup_or_add_default(3) = 6;
339 EXPECT_EQ(map.lookup(3), 6);
340 map.lookup_or_add_default(5) = 2;
341 EXPECT_EQ(map.lookup(5), 2);
342 map.lookup_or_add_default(3) += 4;
343 EXPECT_EQ(map.lookup(3), 10);
344}
345
346TEST(map, LookupOrAdd)
347{
348 Map<int, int> map;
349 EXPECT_EQ(map.lookup_or_add(6, 4), 4);
350 EXPECT_EQ(map.lookup_or_add(6, 5), 4);
351 map.lookup_or_add(6, 4) += 10;
352 EXPECT_EQ(map.lookup(6), 14);
353}
354
355TEST(map, MoveConstructorSmall)
356{
357 Map<int, float> map1;
358 map1.add(1, 2.0f);
359 map1.add(4, 1.0f);
360 Map<int, float> map2(std::move(map1));
361 EXPECT_EQ(map2.size(), 2);
362 EXPECT_EQ(map2.lookup(1), 2.0f);
363 EXPECT_EQ(map2.lookup(4), 1.0f);
364 EXPECT_EQ(map1.size(), 0); /* NOLINT: bugprone-use-after-move */
365 EXPECT_EQ(map1.lookup_ptr(4), nullptr);
366}
367
368TEST(map, MoveConstructorLarge)
369{
370 Map<int, int> map1;
371 for (int i = 0; i < 100; i++) {
372 map1.add_new(i, i);
373 }
374 Map<int, int> map2(std::move(map1));
375 EXPECT_EQ(map2.size(), 100);
376 EXPECT_EQ(map2.lookup(1), 1);
377 EXPECT_EQ(map2.lookup(4), 4);
378 EXPECT_EQ(map1.size(), 0); /* NOLINT: bugprone-use-after-move */
379 EXPECT_EQ(map1.lookup_ptr(4), nullptr);
380}
381
382TEST(map, MoveAssignment)
383{
384 Map<int, float> map1;
385 map1.add(1, 2.0f);
386 map1.add(4, 1.0f);
387 Map<int, float> map2;
388 map2 = std::move(map1);
389 EXPECT_EQ(map2.size(), 2);
390 EXPECT_EQ(map2.lookup(1), 2.0f);
391 EXPECT_EQ(map2.lookup(4), 1.0f);
392 EXPECT_EQ(map1.size(), 0); /* NOLINT: bugprone-use-after-move */
393 EXPECT_EQ(map1.lookup_ptr(4), nullptr);
394}
395
396TEST(map, CopyAssignment)
397{
398 Map<int, float> map1;
399 map1.add(1, 2.0f);
400 map1.add(4, 1.0f);
401 Map<int, float> map2;
402 map2 = map1;
403 EXPECT_EQ(map2.size(), 2);
404 EXPECT_EQ(map2.lookup(1), 2.0f);
405 EXPECT_EQ(map2.lookup(4), 1.0f);
406 EXPECT_EQ(map1.size(), 2);
407 EXPECT_EQ(*map1.lookup_ptr(4), 1.0f);
408}
409
410TEST(map, Clear)
411{
412 Map<int, float> map;
413 map.add(1, 1.0f);
414 map.add(2, 5.0f);
415
416 EXPECT_EQ(map.size(), 2);
417 EXPECT_TRUE(map.contains(1));
418 EXPECT_TRUE(map.contains(2));
419
420 map.clear();
421
422 EXPECT_EQ(map.size(), 0);
423 EXPECT_FALSE(map.contains(1));
424 EXPECT_FALSE(map.contains(2));
425}
426
427TEST(map, UniquePtrValue)
428{
429 auto value1 = std::make_unique<int>();
430 auto value2 = std::make_unique<int>();
431 auto value3 = std::make_unique<int>();
432
433 int *value1_ptr = value1.get();
434
436 map.add_new(1, std::move(value1));
437 map.add(2, std::move(value2));
438 map.add_overwrite(3, std::move(value3));
439 map.lookup_or_add_cb(4, []() { return std::make_unique<int>(); });
440 map.add_new(5, std::make_unique<int>());
441 map.add(6, std::make_unique<int>());
442 map.add_overwrite(7, std::make_unique<int>());
443 map.lookup_or_add(8, std::make_unique<int>());
444 map.pop_default(9, std::make_unique<int>());
445
446 EXPECT_EQ(map.lookup(1).get(), value1_ptr);
447 EXPECT_EQ(map.lookup_ptr(100), nullptr);
448}
449
450TEST(map, Remove)
451{
452 Map<int, int> map;
453 map.add(2, 4);
454 EXPECT_EQ(map.size(), 1);
455 EXPECT_FALSE(map.remove(3));
456 EXPECT_EQ(map.size(), 1);
457 EXPECT_TRUE(map.remove(2));
458 EXPECT_EQ(map.size(), 0);
459}
460
461TEST(map, PointerKeys)
462{
463 char a, b, c, d;
464
466 EXPECT_TRUE(map.add(&a, 5));
467 EXPECT_FALSE(map.add(&a, 4));
468 map.add_new(&b, 1);
469 map.add_new(&c, 1);
470 EXPECT_EQ(map.size(), 3);
471 EXPECT_TRUE(map.remove(&b));
472 EXPECT_TRUE(map.add(&b, 8));
473 EXPECT_FALSE(map.remove(&d));
474 EXPECT_TRUE(map.remove(&a));
475 EXPECT_TRUE(map.remove(&b));
476 EXPECT_TRUE(map.remove(&c));
477 EXPECT_TRUE(map.is_empty());
478}
479
480TEST(map, ConstKeysAndValues)
481{
483 map.reserve(10);
484 map.add("45", "643");
485 EXPECT_TRUE(map.contains("45"));
486 EXPECT_FALSE(map.contains("54"));
487}
488
489TEST(map, ForeachItem)
490{
491 Map<int, int> map;
492 map.add(3, 4);
493 map.add(1, 8);
494
495 Vector<int> keys;
496 Vector<int> values;
497 map.foreach_item([&](int key, int value) {
498 keys.append(key);
499 values.append(value);
500 });
501
502 EXPECT_EQ(keys.size(), 2);
503 EXPECT_EQ(values.size(), 2);
504 EXPECT_EQ(keys.first_index_of(3), values.first_index_of(4));
505 EXPECT_EQ(keys.first_index_of(1), values.first_index_of(8));
506}
507
508TEST(map, CopyConstructorExceptions)
509{
511 MapType map;
512 map.add(2, 2);
513 map.add(4, 4);
514 map.lookup(2).throw_during_copy = true;
515 EXPECT_ANY_THROW({ MapType map_copy(map); });
516}
517
518TEST(map, MoveConstructorExceptions)
519{
521 MapType map;
522 map.add(1, 1);
523 map.add(2, 2);
524 map.lookup(1).throw_during_move = true;
525 EXPECT_ANY_THROW({ MapType map_moved(std::move(map)); });
526 map.add(5, 5); /* NOLINT: bugprone-use-after-move */
527}
528
529TEST(map, AddNewExceptions)
530{
532 ExceptionThrower key1 = 1;
533 key1.throw_during_copy = true;
534 ExceptionThrower value1;
535 EXPECT_ANY_THROW({ map.add_new(key1, value1); });
536 EXPECT_EQ(map.size(), 0);
537 ExceptionThrower key2 = 2;
538 ExceptionThrower value2;
539 value2.throw_during_copy = true;
540 EXPECT_ANY_THROW({ map.add_new(key2, value2); });
541}
542
543TEST(map, ReserveExceptions)
544{
546 map.add(3, 3);
547 map.add(5, 5);
548 map.add(2, 2);
549 map.lookup(2).throw_during_move = true;
550 EXPECT_ANY_THROW({ map.reserve(100); });
551 map.add(1, 1);
552 map.add(5, 5);
553}
554
555TEST(map, PopExceptions)
556{
558 map.add(3, 3);
559 map.lookup(3).throw_during_move = true;
560 EXPECT_ANY_THROW({ map.pop(3); }); /* NOLINT: bugprone-throw-keyword-missing */
561 EXPECT_EQ(map.size(), 1);
562 map.add(1, 1);
563 EXPECT_EQ(map.size(), 2);
564}
565
566TEST(map, AddOrModifyExceptions)
567{
569 auto create_fn = [](ExceptionThrower * /*v*/) { throw std::runtime_error(""); };
570 auto modify_fn = [](ExceptionThrower * /*v*/) {};
571 EXPECT_ANY_THROW({ map.add_or_modify(3, create_fn, modify_fn); });
572}
573
574namespace {
575enum class TestEnum {
576 A = 0,
577 B = 1,
578 C = 2,
579 D = 1,
580};
581}
582
583TEST(map, EnumKey)
584{
586 map.add(TestEnum::A, 4);
587 map.add(TestEnum::B, 6);
588 EXPECT_EQ(map.lookup(TestEnum::A), 4);
589 EXPECT_EQ(map.lookup(TestEnum::B), 6);
590 EXPECT_EQ(map.lookup(TestEnum::D), 6);
591 EXPECT_FALSE(map.contains(TestEnum::C));
592 map.lookup(TestEnum::D) = 10;
593 EXPECT_EQ(map.lookup(TestEnum::B), 10);
594}
595
596TEST(map, GenericAlgorithms)
597{
598 Map<int, int> map;
599 map.add(5, 2);
600 map.add(1, 4);
601 map.add(2, 2);
602 map.add(7, 1);
603 map.add(8, 6);
604 EXPECT_TRUE(std::any_of(map.keys().begin(), map.keys().end(), [](int v) { return v == 1; }));
605 EXPECT_TRUE(std::any_of(map.values().begin(), map.values().end(), [](int v) { return v == 1; }));
606 EXPECT_TRUE(std::any_of(
607 map.items().begin(), map.items().end(), [](auto item) { return item.value == 1; }));
608 EXPECT_EQ(std::count(map.values().begin(), map.values().end(), 2), 2);
609 EXPECT_EQ(std::count(map.values().begin(), map.values().end(), 4), 1);
610 EXPECT_EQ(std::count(map.keys().begin(), map.keys().end(), 7), 1);
611}
612
613TEST(map, AddAsVariadic)
614{
616 map.add_as(3, "hello", 2);
617 map.add_as(2, "test", 1);
618 EXPECT_EQ(map.lookup(3), "he");
619 EXPECT_EQ(map.lookup(2), "t");
620}
621
622TEST(map, RemoveDuringIteration)
623{
624 Map<int, int> map;
625 map.add(2, 1);
626 map.add(5, 2);
627 map.add(1, 2);
628 map.add(6, 0);
629 map.add(3, 3);
630
631 EXPECT_EQ(map.size(), 5);
632
634 Iter begin = map.items().begin();
635 Iter end = map.items().end();
636 for (Iter iter = begin; iter != end; ++iter) {
637 MutableMapItem<int, int> item = *iter;
638 if (item.value == 2) {
639 map.remove(iter);
640 }
641 }
642
643 EXPECT_EQ(map.size(), 3);
644 EXPECT_EQ(map.lookup(2), 1);
645 EXPECT_EQ(map.lookup(6), 0);
646 EXPECT_EQ(map.lookup(3), 3);
647}
648
649TEST(map, RemoveIf)
650{
652 for (const int64_t i : IndexRange(100)) {
653 map.add(i * i, i);
654 }
655 const int64_t removed = map.remove_if([](auto item) { return item.key > 100; });
656 EXPECT_EQ(map.size() + removed, 100);
657 for (const int64_t i : IndexRange(100)) {
658 if (i <= 10) {
659 EXPECT_EQ(map.lookup(i * i), i);
660 }
661 else {
662 EXPECT_FALSE(map.contains(i * i));
663 }
664 }
665}
666
667TEST(map, LookupKey)
668{
670 map.add("a", 0);
671 map.add("b", 1);
672 map.add("c", 2);
673 EXPECT_EQ(map.lookup_key("a"), "a");
674 EXPECT_EQ(map.lookup_key_as("c"), "c");
675 EXPECT_EQ(map.lookup_key_ptr_as("d"), nullptr);
676 EXPECT_EQ(map.lookup_key_ptr_as("b")->size(), 1);
677 EXPECT_EQ(map.lookup_key_ptr("a"), map.lookup_key_ptr_as("a"));
678}
679
680TEST(map, VectorKey)
681{
682 Map<Vector<int>, int> map;
683 map.add({1, 2, 3}, 100);
684 map.add({3, 2, 1}, 200);
685
686 EXPECT_EQ(map.size(), 2);
687 EXPECT_EQ(map.lookup({1, 2, 3}), 100);
688 EXPECT_EQ(map.lookup({3, 2, 1}), 200);
689 EXPECT_FALSE(map.contains({1, 2}));
690
691 std::array<int, 3> array = {1, 2, 3};
692 EXPECT_EQ(map.lookup_as(array), 100);
693
694 map.remove_as(Vector<int>({1, 2, 3}).as_mutable_span());
695 EXPECT_EQ(map.size(), 1);
696}
697
698TEST(map, Equality)
699{
702
703 EXPECT_EQ(a, b);
704 a.add(3, 4);
705 EXPECT_NE(a, b);
706 b.add(3, 4);
707 EXPECT_EQ(a, b);
708
709 a.add(4, 10);
710 b.add(4, 11);
711 EXPECT_NE(a, b);
712}
713
717#if 0
718template<typename MapT>
719BLI_NOINLINE void benchmark_random_ints(StringRef name, int amount, int factor)
720{
721 RNG *rng = BLI_rng_new(0);
722 Vector<int> values;
723 for (int i = 0; i < amount; i++) {
724 values.append(BLI_rng_get_int(rng) * factor);
725 }
726 BLI_rng_free(rng);
727
728 MapT map;
729 {
730 SCOPED_TIMER(name + " Add");
731 for (int value : values) {
732 map.add(value, value);
733 }
734 }
735 int count = 0;
736 {
737 SCOPED_TIMER(name + " Contains");
738 for (int value : values) {
739 count += map.contains(value);
740 }
741 }
742 {
743 SCOPED_TIMER(name + " Remove");
744 for (int value : values) {
745 count += map.remove(value);
746 }
747 }
748
749 /* Print the value for simple error checking and to avoid some compiler optimizations. */
750 std::cout << "Count: " << count << "\n";
751}
752
757template<typename Key, typename Value> class StdUnorderedMapWrapper {
758 private:
759 using MapType = std::unordered_map<Key, Value, blender::DefaultHash<Key>>;
760 MapType map_;
761
762 public:
763 int64_t size() const
764 {
765 return int64_t(map_.size());
766 }
767
768 bool is_empty() const
769 {
770 return map_.empty();
771 }
772
773 void reserve(int64_t n)
774 {
775 map_.reserve(n);
776 }
777
778 template<typename ForwardKey, typename... ForwardValue>
779 void add_new(ForwardKey &&key, ForwardValue &&...value)
780 {
781 map_.insert({std::forward<ForwardKey>(key), Value(std::forward<ForwardValue>(value)...)});
782 }
783
784 template<typename ForwardKey, typename... ForwardValue>
785 bool add(ForwardKey &&key, ForwardValue &&...value)
786 {
787 return map_
788 .insert({std::forward<ForwardKey>(key), Value(std::forward<ForwardValue>(value)...)})
789 .second;
790 }
791
792 bool contains(const Key &key) const
793 {
794 return map_.find(key) != map_.end();
795 }
796
797 bool remove(const Key &key)
798 {
799 return bool(map_.erase(key));
800 }
801
802 Value &lookup(const Key &key)
803 {
804 return map_.find(key)->second;
805 }
806
807 const Value &lookup(const Key &key) const
808 {
809 return map_.find(key)->second;
810 }
811
812 void clear()
813 {
814 map_.clear();
815 }
816
817 void print_stats(StringRef /*name*/ = "") const {}
818};
819
820TEST(map, Benchmark)
821{
822 for (int i = 0; i < 3; i++) {
823 benchmark_random_ints<blender::Map<int, int>>("blender::Map ", 1000000, 1);
824 benchmark_random_ints<blender::StdUnorderedMapWrapper<int, int>>(
825 "std::unordered_map", 1000000, 1);
826 }
827 std::cout << "\n";
828 for (int i = 0; i < 3; i++) {
829 uint32_t factor = (3 << 10);
830 benchmark_random_ints<blender::Map<int, int>>("blender::Map ", 1000000, factor);
831 benchmark_random_ints<blender::StdUnorderedMapWrapper<int, int>>(
832 "std::unordered_map", 1000000, factor);
833 }
834}
835
888#endif /* Benchmark */
889
890} // namespace blender::tests
#define BLI_NOINLINE
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
Random number functions.
void int BLI_rng_get_int(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition rand.cc:78
struct RNG * BLI_rng_new(unsigned int seed)
Definition rand.cc:39
void BLI_rng_free(struct RNG *rng) ATTR_NONNULL(1)
Definition rand.cc:58
#define SCOPED_TIMER(name)
Definition BLI_timeit.hh:61
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a producing a negative Combine Generate a color from its and blue Hue Saturation Value
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
SubIterator begin() const
Definition BLI_map.hh:730
SubIterator end() const
Definition BLI_map.hh:740
const Value * lookup_ptr(const Key &key) const
Definition BLI_map.hh:484
Value & lookup_or_add_default(const Key &key)
Definition BLI_map.hh:601
bool add(const Key &key, const Value &value)
Definition BLI_map.hh:271
const Value & lookup(const Key &key) const
Definition BLI_map.hh:506
bool add_as(ForwardKey &&key, ForwardValue &&...value)
Definition BLI_map.hh:288
void add_new(const Key &key, const Value &value)
Definition BLI_map.hh:241
int64_t size() const
Definition BLI_map.hh:927
ItemIterator items() const
Definition BLI_map.hh:864
void reserve(int64_t n)
Definition BLI_map.hh:979
bool contains(const Key &key) const
Definition BLI_set.hh:291
bool add(const Key &key)
Definition BLI_set.hh:248
int64_t size() const
bool contains(const T &value) const
void append(const T &value)
int64_t first_index_of(const T &value) const
local_group_size(16, 16) .push_constant(Type b
blender::Vector< blender::nodes::ItemDeclarationPtr >::const_iterator ItemIterator
int count
#define B
static void clear(Message &msg)
Definition msgfmt.cc:218
static void add(blender::Map< std::string, std::string > &messages, Message &msg)
Definition msgfmt.cc:227
GAttributeReader lookup(const void *owner, const StringRef attribute_id)
static float return_42()
TEST(any, DefaultConstructor)
static PyObject * create_func(PyObject *, PyObject *args)
Definition python.cpp:161
unsigned int uint32_t
Definition stdint.h:80
__int64 int64_t
Definition stdint.h:89
Definition rand.cc:33