Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
ah-dry-mixin_test.cc
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
33
38#include <gtest/gtest.h>
39
40#include <vector>
41#include <string>
42#include <htlist.H>
43#include <ah-dry-mixin.H>
44#include <tpl_array.H>
45#include <tpl_dynArray.H>
46
47using namespace std;
48using namespace Aleph;
49
50// =============================================================================
51// Test Container using CRTP Mixins
52// =============================================================================
53
55template <typename T>
56class MixinVector : public TraverseMixin<MixinVector<T>, T>,
57 public LocateMixin<MixinVector<T>, T>,
58 public FunctionalMixin<MixinVector<T>, T>,
59 public KeysMixin<MixinVector<T>, T>
60{
61 std::vector<T> data;
62
63public:
64 using Item_Type = T;
65
66 MixinVector() = default;
67 MixinVector(std::initializer_list<T> init) : data(init) {}
68
69 void append(const T & item) { data.push_back(item); }
70 void insert(const T & item) { data.insert(data.begin(), item); }
71 size_t size() const noexcept { return data.size(); }
72 bool is_empty() const noexcept { return data.empty(); }
73
74 // Iterator compatible with Aleph requirements
76 {
78 size_t pos;
79
80 public:
82 Iterator(const MixinVector & c) : container(&c), pos(0) {}
83
84 bool has_curr() const noexcept { return pos < container->data.size(); }
85 T & get_curr() const { return const_cast<T&>(container->data[pos]); }
86 void next() { ++pos; }
87 void next_ne() noexcept { ++pos; }
88 };
89
90 Iterator get_it() const { return Iterator(*this); }
91
92 // For testing equality
93 bool operator==(const MixinVector & other) const { return data == other.data; }
94};
95
96
97// =============================================================================
98// TraverseMixin Tests
99// =============================================================================
100
102{
103 MixinVector<int> v = {1, 2, 3, 4, 5};
104
105 int sum = 0;
106 bool completed = v.traverse([&sum](int x) {
107 sum += x;
108 return true;
109 });
110
112 EXPECT_EQ(sum, 15);
113}
114
116{
117 MixinVector<int> v = {1, 2, 3, 4, 5};
118
119 int sum = 0;
120 bool completed = v.traverse([&sum](int x) {
121 if (x > 3) return false;
122 sum += x;
123 return true;
124 });
125
127 EXPECT_EQ(sum, 6); // 1 + 2 + 3
128}
129
131{
133
134 bool completed = v.traverse([](int) { return true; });
136}
137
138
139// =============================================================================
140// FunctionalMixin Tests
141// =============================================================================
142
144{
145 MixinVector<int> v = {1, 2, 3};
146
147 int sum = 0;
148 v.for_each([&sum](int x) { sum += x; });
149
150 EXPECT_EQ(sum, 6);
151}
152
154{
155 MixinVector<int> v = {1, 2, 3};
156
157 v.mutable_for_each([](int& x) { x *= 2; });
158
159 int sum = 0;
160 v.for_each([&sum](int x) { sum += x; });
161 EXPECT_EQ(sum, 12); // 2 + 4 + 6
162}
163
165{
166 MixinVector<int> v = {2, 4, 6, 8};
167
168 EXPECT_TRUE(v.all([](int x) { return x % 2 == 0; }));
169 EXPECT_FALSE(v.all([](int x) { return x > 5; }));
170}
171
173{
175 // Vacuous truth
176 EXPECT_TRUE(v.all([](int) { return false; }));
177}
178
180{
181 MixinVector<int> v = {1, 3, 5, 6, 7};
182
183 EXPECT_TRUE(v.exists([](int x) { return x % 2 == 0; })); // 6
184 EXPECT_FALSE(v.exists([](int x) { return x > 100; }));
185}
186
188{
190 EXPECT_FALSE(v.exists([](int) { return true; }));
191}
192
194{
195 MixinVector<int> v = {1, 2, 3};
196
197 auto squared = v.maps<int>([](int x) { return x * x; });
198
199 EXPECT_EQ(squared.size(), 3);
200
201 int expected[] = {1, 4, 9};
202 int i = 0;
203 squared.for_each([&](int x) { EXPECT_EQ(x, expected[i++]); });
204}
205
207{
208 MixinVector<int> v = {1, 2, 3};
209
210 auto strs = v.maps<string>([](int x) { return to_string(x); });
211
212 EXPECT_EQ(strs.size(), 3);
213
214 string expected[] = {"1", "2", "3"};
215 int i = 0;
216 strs.for_each([&](const string& s) { EXPECT_EQ(s, expected[i++]); });
217}
218
220{
221 MixinVector<int> v = {1, 2, 3, 4, 5, 6};
222
223 auto evens = v.filter([](int x) { return x % 2 == 0; });
224
225 EXPECT_EQ(evens.size(), 3);
226
227 int expected[] = {2, 4, 6};
228 int i = 0;
229 evens.for_each([&](int x) { EXPECT_EQ(x, expected[i++]); });
230}
231
233{
234 MixinVector<int> v = {1, 3, 5, 7};
235
236 auto evens = v.filter([](int x) { return x % 2 == 0; });
237 EXPECT_TRUE(evens.is_empty());
238}
239
241{
242 MixinVector<int> v = {1, 2, 3, 4, 5};
243
244 int sum = v.foldl<int>(0, [](int acc, int x) { return acc + x; });
245 EXPECT_EQ(sum, 15);
246
247 int product = v.foldl<int>(1, [](int acc, int x) { return acc * x; });
248 EXPECT_EQ(product, 120);
249}
250
252{
254
255 int result = v.foldl<int>(42, [](int acc, int x) { return acc + x; });
256 EXPECT_EQ(result, 42);
257}
258
260{
261 MixinVector<int> v = {1, 2, 3, 4, 5, 6};
262
263 auto [evens, odds] = v.partition([](int x) { return x % 2 == 0; });
264
265 EXPECT_EQ(evens.size(), 3);
266 EXPECT_EQ(odds.size(), 3);
267
268 int expected_evens[] = {2, 4, 6};
269 int expected_odds[] = {1, 3, 5};
270
271 int i = 0;
272 evens.for_each([&](int x) { EXPECT_EQ(x, expected_evens[i++]); });
273
274 i = 0;
275 odds.for_each([&](int x) { EXPECT_EQ(x, expected_odds[i++]); });
276}
277
279{
280 MixinVector<int> v = {1, 2, 3, 4, 5};
281 EXPECT_EQ(v.length(), 5);
282
283 MixinVector<int> empty;
284 EXPECT_EQ(empty.length(), 0);
285}
286
288{
289 MixinVector<int> v = {1, 2, 3, 4, 5};
290
291 auto reversed = v.rev();
292
293 EXPECT_EQ(reversed.size(), 5);
294
295 int expected[] = {5, 4, 3, 2, 1};
296 int i = 0;
297 reversed.for_each([&](int x) { EXPECT_EQ(x, expected[i++]); });
298}
299
301{
302 MixinVector<int> v = {1, 2, 3, 4, 5};
303
304 auto first3 = v.take(3);
305 EXPECT_EQ(first3.size(), 3);
306
307 int expected[] = {1, 2, 3};
308 int i = 0;
309 first3.for_each([&](int x) { EXPECT_EQ(x, expected[i++]); });
310
311 auto all = v.take(100);
312 EXPECT_EQ(all.size(), 5);
313}
314
316{
317 MixinVector<int> v = {1, 2, 3, 4, 5};
318
319 auto last3 = v.drop(2);
320 EXPECT_EQ(last3.size(), 3);
321
322 int expected[] = {3, 4, 5};
323 int i = 0;
324 last3.for_each([&](int x) { EXPECT_EQ(x, expected[i++]); });
325
326 auto empty = v.drop(100);
327 EXPECT_TRUE(empty.is_empty());
328}
329
330
331// =============================================================================
332// LocateMixin Tests
333// =============================================================================
334
336{
337 MixinVector<int> v = {10, 20, 30, 40, 50};
338
339 EXPECT_EQ(v.nth(0), 10);
340 EXPECT_EQ(v.nth(2), 30);
341 EXPECT_EQ(v.nth(4), 50);
342
343 EXPECT_THROW(v.nth(5), std::out_of_range);
344 EXPECT_THROW(v.nth(100), std::out_of_range);
345}
346
348{
349 MixinVector<int> v = {10, 20, 30};
350
351 EXPECT_EQ(v.nth_ne(0), 10);
352 EXPECT_EQ(v.nth_ne(1), 20);
353 EXPECT_EQ(v.nth_ne(2), 30);
354}
355
357{
358 MixinVector<int> v = {10, 20, 30};
359
360 v.nth(1) = 25;
361 EXPECT_EQ(v.nth(1), 25);
362}
363
365{
366 MixinVector<int> v = {1, 2, 3, 4, 5};
367
368 int* p = v.find_ptr([](int x) { return x == 3; });
369 ASSERT_NE(p, nullptr);
370 EXPECT_EQ(*p, 3);
371
372 int* not_found = v.find_ptr([](int x) { return x == 100; });
373 EXPECT_EQ(not_found, nullptr);
374}
375
377{
378 MixinVector<int> v = {1, 2, 3, 4, 5};
379
380 int* p = v.find_ptr([](int x) { return x == 3; });
381 ASSERT_NE(p, nullptr);
382 *p = 30;
383
384 EXPECT_EQ(v.nth(2), 30);
385}
386
388{
389 MixinVector<int> v = {1, 2, 3, 4, 5};
390
391 auto [found, item] = v.find_item([](int x) { return x > 3; });
392 EXPECT_TRUE(found);
393 EXPECT_EQ(item, 4);
394
395 auto [not_found, default_val] = v.find_item([](int x) { return x > 100; });
397}
398
399
400// =============================================================================
401// KeysMixin Tests
402// =============================================================================
403
405{
406 MixinVector<int> v = {1, 2, 3};
407
408 auto k = v.keys();
409 EXPECT_EQ(k.size(), 3);
410}
411
413{
414 MixinVector<string> v = {"a", "b", "c"};
415
416 auto items = v.items();
417 EXPECT_EQ(items.size(), 3);
418}
419
420
421// =============================================================================
422// Chained Operations Tests
423// =============================================================================
424
426{
427 MixinVector<int> v = {1, 2, 3, 4, 5, 6};
428
429 // Filter evens, then square them
430 auto evens = v.filter([](int x) { return x % 2 == 0; });
431 auto squared = evens.maps<int>([](int x) { return x * x; });
432
433 EXPECT_EQ(squared.size(), 3);
434
435 int expected[] = {4, 16, 36};
436 int i = 0;
437 squared.for_each([&](int x) { EXPECT_EQ(x, expected[i++]); });
438}
439
441{
442 MixinVector<int> v = {1, 2, 3, 4, 5};
443
444 // Square then sum
445 auto squared = v.maps<int>([](int x) { return x * x; });
446 int sum = squared.foldl<int>(0, [](int acc, int x) { return acc + x; });
447
448 EXPECT_EQ(sum, 1 + 4 + 9 + 16 + 25);
449}
450
451
452// =============================================================================
453// Complex Type Tests
454// =============================================================================
455
456struct Person
457{
458 string name;
459 int age;
460};
461
463{
465 people.append({"Alice", 30});
466 people.append({"Bob", 25});
467 people.append({"Charlie", 35});
468
469 // Find oldest
470 Person* oldest = people.find_ptr([](const Person& p) {
471 return p.age >= 35;
472 });
473 ASSERT_NE(oldest, nullptr);
474 EXPECT_EQ(oldest->name, "Charlie");
475
476 // Get ages
477 auto ages = people.maps<int>([](const Person& p) { return p.age; });
478 int sum = ages.foldl<int>(0, [](int acc, int a) { return acc + a; });
479 EXPECT_EQ(sum, 90);
480
481 // Filter by age
482 auto over27 = people.filter([](const Person& p) { return p.age > 27; });
483 EXPECT_EQ(over27.size(), 2);
484}
485
486
487// =============================================================================
488// Aggregation Tests (sum, product, min, max)
489// =============================================================================
490
492{
493 MixinVector<int> v = {1, 2, 3, 4, 5};
494 EXPECT_EQ(v.sum(), 15);
495 EXPECT_EQ(v.sum(10), 25); // with initial value
496}
497
499{
501 EXPECT_EQ(v.sum(), 0);
502 EXPECT_EQ(v.sum(100), 100);
503}
504
506{
507 MixinVector<string> v = {"Hello", " ", "World"};
508 EXPECT_EQ(v.sum(), "Hello World");
509 EXPECT_EQ(v.sum(string("Prefix: ")), "Prefix: Hello World");
510}
511
513{
514 MixinVector<int> v = {1, 2, 3, 4, 5};
515 EXPECT_EQ(v.product(1), 120);
516 EXPECT_EQ(v.product(2), 240);
517}
518
525
527{
528 MixinVector<int> v = {3, 1, 4, 1, 5, 9, 2, 6};
529
530 const int* min_ptr = v.min();
531 ASSERT_NE(min_ptr, nullptr);
532 EXPECT_EQ(*min_ptr, 1);
533}
534
536{
538 EXPECT_EQ(v.min(), nullptr);
539}
540
542{
543 MixinVector<int> v = {42};
544 ASSERT_NE(v.min(), nullptr);
545 EXPECT_EQ(*v.min(), 42);
546}
547
549{
550 MixinVector<int> v = {3, 1, 4, 1, 5, 9, 2, 6};
551
552 const int* max_ptr = v.max();
553 ASSERT_NE(max_ptr, nullptr);
554 EXPECT_EQ(*max_ptr, 9);
555}
556
558{
560 EXPECT_EQ(v.max(), nullptr);
561}
562
564{
565 MixinVector<int> v = {42};
566 ASSERT_NE(v.max(), nullptr);
567 EXPECT_EQ(*v.max(), 42);
568}
569
571{
572 MixinVector<string> v = {"apple", "pie", "a", "banana"};
573
574 const string* shortest = v.min_by([](const string& a, const string& b) {
575 return a.length() < b.length();
576 });
577
578 ASSERT_NE(shortest, nullptr);
579 EXPECT_EQ(*shortest, "a");
580}
581
583{
584 MixinVector<string> v = {"apple", "pie", "a", "banana"};
585
586 const string* longest = v.max_by([](const string& a, const string& b) {
587 return a.length() < b.length();
588 });
589
590 ASSERT_NE(longest, nullptr);
591 EXPECT_EQ(*longest, "banana");
592}
593
595{
596 MixinVector<int> v = {-5, 3, -10, 7, 0};
597
598 EXPECT_EQ(*v.min(), -10);
599 EXPECT_EQ(*v.max(), 7);
600}
601
602
603// =============================================================================
604// Search and Counting Tests (contains, none, count_if)
605// =============================================================================
606
608{
609 MixinVector<int> v = {1, 2, 3, 4, 5};
610
616 EXPECT_FALSE(v.has_value(100));
617}
618
624
626{
627 MixinVector<string> v = {"apple", "banana", "cherry"};
628
629 EXPECT_TRUE(v.has_value("banana"));
630 EXPECT_FALSE(v.has_value("Banana")); // case sensitive
631 EXPECT_FALSE(v.has_value("grape"));
632}
633
635{
636 MixinVector<int> v = {2, 4, 6, 8, 10};
637
638 EXPECT_TRUE(v.none([](int x) { return x % 2 != 0; })); // no odds
639 EXPECT_FALSE(v.none([](int x) { return x > 5; })); // some > 5
640}
641
643{
645 EXPECT_TRUE(v.none([](int) { return true; })); // vacuously true
646}
647
649{
650 MixinVector<int> v = {2, 4, 6};
651
652 auto is_odd = [](int x) { return x % 2 != 0; };
654}
655
657{
658 MixinVector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
659
660 EXPECT_EQ(v.count_if([](int x) { return x % 2 == 0; }), 5); // evens
661 EXPECT_EQ(v.count_if([](int x) { return x > 5; }), 5); // > 5
662 EXPECT_EQ(v.count_if([](int x) { return x > 100; }), 0); // none
663 EXPECT_EQ(v.count_if([](int) { return true; }), 10); // all
664}
665
667{
669 EXPECT_EQ(v.count_if([](int) { return true; }), 0);
670}
671
672
673// =============================================================================
674// First/Last Element Tests
675// =============================================================================
676
678{
679 MixinVector<int> v = {10, 20, 30};
680
681 const int* ptr = v.first();
682 ASSERT_NE(ptr, nullptr);
683 EXPECT_EQ(*ptr, 10);
684}
685
687{
689 EXPECT_EQ(v.first(), nullptr);
690}
691
693{
694 MixinVector<int> v = {10, 20, 30};
695 EXPECT_EQ(v.first_or(-1), 10);
696
697 MixinVector<int> empty;
698 EXPECT_EQ(empty.first_or(-1), -1);
699}
700
702{
703 MixinVector<int> v = {10, 20, 30};
704
705 const int* ptr = v.last();
706 ASSERT_NE(ptr, nullptr);
707 EXPECT_EQ(*ptr, 30);
708}
709
711{
713 EXPECT_EQ(v.last(), nullptr);
714}
715
717{
718 MixinVector<int> v = {10, 20, 30};
719 EXPECT_EQ(v.last_or(-1), 30);
720
721 MixinVector<int> empty;
722 EXPECT_EQ(empty.last_or(-1), -1);
723}
724
726{
727 MixinVector<int> v = {42};
728
729 EXPECT_EQ(*v.first(), 42);
730 EXPECT_EQ(*v.last(), 42);
731 EXPECT_EQ(v.first_or(-1), 42);
732 EXPECT_EQ(v.last_or(-1), 42);
733}
734
735
736// =============================================================================
737// Enumeration and Indexing Tests
738// =============================================================================
739
741{
742 MixinVector<string> v = {"a", "b", "c"};
743
744 auto enumerated = v.enumerate();
745 EXPECT_EQ(enumerated.size(), 3);
746
747 size_t expected_idx = 0;
748 string expected_vals[] = {"a", "b", "c"};
749 enumerated.for_each([&](const std::pair<size_t, string>& p) {
750 EXPECT_EQ(p.first, expected_idx);
752 ++expected_idx;
753 });
754}
755
762
764{
765 MixinVector<int> v = {10, 20, 30, 40, 50};
766
767 EXPECT_EQ(v.find_index([](int x) { return x == 30; }), 2);
768 EXPECT_EQ(v.find_index([](int x) { return x > 35; }), 3); // first > 35 is 40
769 EXPECT_EQ(v.find_index([](int x) { return x > 100; }), static_cast<size_t>(-1));
770}
771
773{
775 EXPECT_EQ(v.find_index([](int) { return true; }), static_cast<size_t>(-1));
776}
777
779{
780 MixinVector<int> v = {10, 20, 30, 40, 50};
781
782 EXPECT_EQ(v.index_of(10), 0);
783 EXPECT_EQ(v.index_of(30), 2);
784 EXPECT_EQ(v.index_of(50), 4);
785 EXPECT_EQ(v.index_of(99), static_cast<size_t>(-1));
786}
787
789{
790 MixinVector<string> v = {"apple", "banana", "cherry"};
791
792 EXPECT_EQ(v.index_of("banana"), 1);
793 EXPECT_EQ(v.index_of("grape"), static_cast<size_t>(-1));
794}
795
796
797// =============================================================================
798// Combined Operations with New Methods
799// =============================================================================
800
802{
803 MixinVector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
804
805 // Sum of evens using filter + foldl (since filter returns DynList)
806 auto evens = v.filter([](int x) { return x % 2 == 0; });
807 int sum = evens.foldl<int>(0, [](int acc, int x) { return acc + x; });
808 EXPECT_EQ(sum, 2 + 4 + 6 + 8 + 10);
809
810 // Direct sum on MixinVector
811 EXPECT_EQ(v.sum(), 55);
812}
813
815{
816 MixinVector<int> v = {1, 3, 5, 7, 9}; // odds only
817
818 EXPECT_EQ(*v.min(), 1);
819 EXPECT_EQ(*v.max(), 9);
820}
821
823{
824 MixinVector<string> v = {"a", "bb", "ccc", "dd"};
825
826 auto enumerated = v.enumerate();
827 EXPECT_EQ(enumerated.size(), 4);
828
829 // Count even indices using the mixin's count_if
830 // (enumerated is DynList, so we verify via foldl)
831 int even_count = enumerated.foldl<int>(0, [](int acc, const std::pair<size_t, string>& p) {
832 return acc + (p.first % 2 == 0 ? 1 : 0);
833 });
834 EXPECT_EQ(even_count, 2); // indices 0 and 2
835}
836
837
838// =============================================================================
839// Stress Tests
840// =============================================================================
841
843{
844 constexpr size_t N = 10000;
846
847 for (size_t i = 0; i < N; ++i)
848 v.append(i);
849
850 // Sum using foldl
851 size_t sum = v.foldl<size_t>(0, [](size_t acc, size_t x) { return acc + x; });
852 EXPECT_EQ(sum, N * (N - 1) / 2);
853
854 // Sum using sum()
855 EXPECT_EQ(v.sum(), N * (N - 1) / 2);
856
857 // Count evens
858 auto evens = v.filter([](size_t x) { return x % 2 == 0; });
859 EXPECT_EQ(evens.size(), N / 2);
860
861 // count_if
862 EXPECT_EQ(v.count_if([](size_t x) { return x % 2 == 0; }), N / 2);
863
864 // All positive
865 EXPECT_TRUE(v.all([](size_t x) { return x < N; }));
866
867 // Min/Max
868 EXPECT_EQ(*v.min(), 0);
869 EXPECT_EQ(*v.max(), N - 1);
870
871 // has_value
872 EXPECT_TRUE(v.has_value(N / 2));
874
875 // first/last
876 EXPECT_EQ(*v.first(), 0);
877 EXPECT_EQ(*v.last(), N - 1);
878}
879
881{
882 constexpr size_t N = 1000;
884
885 for (size_t i = 0; i < N; ++i)
886 v.append(static_cast<int>(i * 2));
887
888 auto enumerated = v.enumerate();
889 EXPECT_EQ(enumerated.size(), N);
890
891 // Verify all indices are correct
892 size_t idx = 0;
893 enumerated.for_each([&idx](const std::pair<size_t, int>& p) {
894 EXPECT_EQ(p.first, idx);
895 EXPECT_EQ(p.second, static_cast<int>(idx * 2));
896 ++idx;
897 });
898}
899
900
901// =============================================================================
902// Constraint Tests - verify methods are properly constrained
903// =============================================================================
904
905// Type without arithmetic operators
907{
908 int value;
909 // No operator+, operator*, operator<, operator==
910};
911
913{
915 v.append({1});
916 v.append({2});
917 v.append({3});
918
919 // These should compile - they don't require operators
920 EXPECT_EQ(v.length(), 3);
921 EXPECT_NE(v.first(), nullptr);
922 EXPECT_NE(v.last(), nullptr);
923 EXPECT_EQ(v.first()->value, 1);
924 EXPECT_EQ(v.last()->value, 3);
925
926 auto enumerated = v.enumerate();
927 EXPECT_EQ(enumerated.size(), 3);
928
929 // count_if with custom predicate works
930 EXPECT_EQ(v.count_if([](const NoOpType& x) { return x.value > 1; }), 2);
931
932 // find_index with custom predicate works
933 EXPECT_EQ(v.find_index([](const NoOpType& x) { return x.value == 2; }), 1);
934
935 // The following would NOT compile (correctly!) due to requires constraints:
936 // v.sum(); // requires operator+
937 // v.product({0}); // requires operator*
938 // v.min(); // requires operator<
939 // v.max(); // requires operator<
940 // v.has_value({1}); // requires operator==
941 // v.index_of({1}); // requires operator==
942}
943
944// Type with only equality
946{
947 int value;
948 bool operator==(const EqOnlyType& other) const { return value == other.value; }
949};
950
952{
954 v.append({1});
955 v.append({2});
956 v.append({3});
957
958 // has_value and index_of work (require operator==)
959 EXPECT_TRUE(v.has_value({2}));
960 EXPECT_FALSE(v.has_value({99}));
961 EXPECT_EQ(v.index_of({2}), 1);
962
963 // The following would NOT compile:
964 // v.sum(); // requires operator+
965 // v.min(); // requires operator<
966}
967
968// Type with only less-than
970{
971 int value;
972 bool operator<(const LtOnlyType& other) const { return value < other.value; }
973};
974
976{
978 v.append({3});
979 v.append({1});
980 v.append({2});
981
982 // min and max work (require operator<)
983 EXPECT_EQ(v.min()->value, 1);
984 EXPECT_EQ(v.max()->value, 3);
985
986 // The following would NOT compile:
987 // v.sum(); // requires operator+
988 // v.has_value({1}); // requires operator==
989}
990
991
992// =============================================================================
993// Advanced Transformation Tests (unique, intersperse)
994// =============================================================================
995
997{
998 MixinVector<int> v = {1, 1, 2, 2, 2, 3, 1, 1};
999
1000 auto u = v.unique();
1001 EXPECT_EQ(u.size(), 4);
1002
1003 int expected[] = {1, 2, 3, 1};
1004 int i = 0;
1005 u.for_each([&](int x) { EXPECT_EQ(x, expected[i++]); });
1006}
1007
1009{
1011 auto u = v.unique();
1012 EXPECT_TRUE(u.is_empty());
1013}
1014
1016{
1017 MixinVector<int> v = {42};
1018 auto u = v.unique();
1019 EXPECT_EQ(u.size(), 1);
1020
1021 // Verify first element via iteration
1022 int first_val = 0;
1023 u.traverse([&first_val](int x) { first_val = x; return false; });
1024 EXPECT_EQ(first_val, 42);
1025}
1026
1028{
1029 MixinVector<int> v = {1, 2, 3, 4, 5};
1030 auto u = v.unique();
1031 EXPECT_EQ(u.size(), 5);
1032}
1033
1035{
1036 MixinVector<string> v = {"a", "A", "b", "B", "c"};
1037
1038 auto u = v.unique_by([](const string& a, const string& b) {
1039 return tolower(a[0]) == tolower(b[0]);
1040 });
1041
1042 EXPECT_EQ(u.size(), 3); // "a", "b", "c"
1043}
1044
1046{
1047 MixinVector<int> v = {1, 2, 3};
1048
1049 auto i = v.intersperse(0);
1050 EXPECT_EQ(i.size(), 5); // 1, 0, 2, 0, 3
1051
1052 int expected[] = {1, 0, 2, 0, 3};
1053 int idx = 0;
1054 i.for_each([&](int x) { EXPECT_EQ(x, expected[idx++]); });
1055}
1056
1058{
1060 auto i = v.intersperse(0);
1061 EXPECT_TRUE(i.is_empty());
1062}
1063
1065{
1066 MixinVector<int> v = {42};
1067 auto i = v.intersperse(0);
1068 EXPECT_EQ(i.size(), 1);
1069
1070 // Verify first element via iteration
1071 int first_val = 0;
1072 i.traverse([&first_val](int x) { first_val = x; return false; });
1073 EXPECT_EQ(first_val, 42);
1074}
1075
1077{
1078 MixinVector<string> v = {"a", "b", "c"};
1079 auto i = v.intersperse(string("-"));
1080 EXPECT_EQ(i.size(), 5);
1081}
1082
1083
1084// =============================================================================
1085// Chunking and Windowing Tests
1086// =============================================================================
1087
1089{
1090 MixinVector<int> v = {1, 2, 3, 4, 5};
1091
1092 auto chunks = v.chunk(2);
1093 EXPECT_EQ(chunks.size(), 3); // {1,2}, {3,4}, {5}
1094
1095 // Verify first chunk size via iteration
1096 size_t first_chunk_size = 0;
1097 chunks.traverse([&first_chunk_size](const auto& c) {
1098 first_chunk_size = c.size();
1099 return false;
1100 });
1102}
1103
1105{
1106 MixinVector<int> v = {1, 2, 3, 4, 5, 6};
1107
1108 auto chunks = v.chunk(2);
1109 EXPECT_EQ(chunks.size(), 3); // {1,2}, {3,4}, {5,6}
1110}
1111
1113{
1115 auto chunks = v.chunk(2);
1116 EXPECT_TRUE(chunks.is_empty());
1117}
1118
1120{
1121 MixinVector<int> v = {1, 2, 3};
1122 auto chunks = v.chunk(0);
1123 EXPECT_TRUE(chunks.is_empty());
1124}
1125
1127{
1128 MixinVector<int> v = {1, 2};
1129 auto chunks = v.chunk(10);
1130 EXPECT_EQ(chunks.size(), 1); // single chunk with all elements
1131}
1132
1134{
1135 MixinVector<int> v = {1, 2, 3, 4, 5};
1136
1137 auto windows = v.sliding(3);
1138 EXPECT_EQ(windows.size(), 3); // {1,2,3}, {2,3,4}, {3,4,5}
1139
1140 // Verify each window has 3 elements
1141 windows.for_each([](const auto& w) { EXPECT_EQ(w.size(), 3); });
1142}
1143
1145{
1146 MixinVector<int> v = {1, 2, 3, 4, 5, 6};
1147
1148 auto windows = v.sliding(2, 2);
1149 EXPECT_EQ(windows.size(), 3); // {1,2}, {3,4}, {5,6}
1150}
1151
1153{
1155 auto windows = v.sliding(2);
1156 EXPECT_TRUE(windows.is_empty());
1157}
1158
1160{
1161 MixinVector<int> v = {1, 2, 3};
1162 auto windows = v.sliding(0);
1163 EXPECT_TRUE(windows.is_empty());
1164}
1165
1167{
1168 MixinVector<int> v = {1, 2};
1169 auto windows = v.sliding(3);
1170 EXPECT_TRUE(windows.is_empty());
1171}
1172
1173
1174// =============================================================================
1175// Conversion Tests (to_vector, join)
1176// =============================================================================
1177
1179{
1180 MixinVector<int> v = {1, 2, 3, 4, 5};
1181
1182 std::vector<int> vec = v.to_vector();
1183 EXPECT_EQ(vec.size(), 5);
1184 EXPECT_EQ(vec[0], 1);
1185 EXPECT_EQ(vec[4], 5);
1186}
1187
1189{
1191 std::vector<int> vec = v.to_vector();
1192 EXPECT_TRUE(vec.empty());
1193}
1194
1196{
1197 MixinVector<int> v = {1, 2, 3, 4, 5};
1198
1199 DynList<int> list = v.to_dynlist();
1200 EXPECT_EQ(list.size(), 5);
1201
1202 // Verify order is preserved
1203 auto it = list.get_it();
1204 EXPECT_EQ(it.get_curr(), 1);
1205 it.next_ne();
1206 EXPECT_EQ(it.get_curr(), 2);
1207}
1208
1215
1217{
1218 // to_vector -> to_dynlist -> verify same content
1219 MixinVector<int> v = {10, 20, 30};
1220
1221 std::vector<int> vec = v.to_vector();
1222 DynList<int> list = v.to_dynlist();
1223
1224 // Both should have same size and content
1225 EXPECT_EQ(vec.size(), list.size());
1226
1227 size_t i = 0;
1228 list.for_each([&vec, &i](int x) {
1229 EXPECT_EQ(x, vec[i++]);
1230 });
1231}
1232
1234{
1235 MixinVector<int> v = {1, 2, 3};
1236
1237 string s = v.join(string(", "));
1238 EXPECT_EQ(s, "1, 2, 3");
1239}
1240
1242{
1243 MixinVector<int> v = {42};
1244 string s = v.join(string("-"));
1245 EXPECT_EQ(s, "42");
1246}
1247
1249{
1251 string s = v.join(string(", "));
1252 EXPECT_EQ(s, "");
1253}
1254
1256{
1257 MixinVector<string> v = {"a", "b", "c"};
1258
1259 string s = v.join_str("-");
1260 EXPECT_EQ(s, "a-b-c");
1261}
1262
1264{
1266 string s = v.join_str("-");
1267 EXPECT_EQ(s, "");
1268}
1269
1270
1271// =============================================================================
1272// Zip Tests
1273// =============================================================================
1274
1276{
1277 MixinVector<int> a = {1, 2, 3};
1279 b.append("a");
1280 b.append("b");
1281 b.append("c");
1282
1283 auto zipped = a.zip_with(b);
1284 EXPECT_EQ(zipped.size(), 3);
1285
1286 // Verify pairs
1287 auto it = zipped.get_it();
1288 EXPECT_EQ(it.get_curr().first, 1);
1289 EXPECT_EQ(it.get_curr().second, "a");
1290}
1291
1293{
1294 MixinVector<int> a = {1, 2, 3, 4, 5};
1295 MixinVector<int> b = {10, 20};
1296
1297 auto zipped = a.zip_with(b);
1298 EXPECT_EQ(zipped.size(), 2); // stops at shorter
1299}
1300
1302{
1303 MixinVector<int> a = {1, 2, 3};
1305
1306 auto zipped = a.zip_with(b);
1307 EXPECT_TRUE(zipped.is_empty());
1308}
1309
1311{
1314
1315 auto zipped = a.zip_with(b);
1316 EXPECT_TRUE(zipped.is_empty());
1317}
1318
1319
1320// =============================================================================
1321// Combined Advanced Operations
1322// =============================================================================
1323
1325{
1326 MixinVector<int> v = {1, 1, 2, 2, 3};
1327
1328 auto unique_result = v.unique();
1329 EXPECT_EQ(unique_result.size(), 3); // 1, 2, 3
1330
1331 // Verify values via iteration
1332 int expected[] = {1, 2, 3};
1333 int idx = 0;
1334 unique_result.for_each([&](int x) { EXPECT_EQ(x, expected[idx++]); });
1335}
1336
1338{
1339 MixinVector<int> v = {1, 2, 3, 4, 5, 6};
1340
1341 auto chunks = v.chunk(2);
1342 // Each chunk: {1,2}, {3,4}, {5,6} -> sums: 3, 7, 11
1343
1344 int total = 0;
1345 chunks.for_each([&total](const Aleph::DynList<int>& chunk) {
1346 total += chunk.foldl<int>(0, [](int acc, int x) { return acc + x; });
1347 });
1348 EXPECT_EQ(total, 21);
1349}
1350
1351
1352// =============================================================================
1353// Tests with DynList (Real Aleph Container) - uses existing methods
1354// =============================================================================
1355
1357{
1358 // DynList uses legacy ahDry.H macros, so only test existing methods
1360 for (int i = 1; i <= 5; ++i)
1361 list.append(i);
1362
1363 // foldl exists in DynList
1364 int sum = list.foldl<int>(0, [](int acc, int x) { return acc + x; });
1365 EXPECT_EQ(sum, 15);
1366
1367 // filter exists
1368 auto evens = list.filter([](int x) { return x % 2 == 0; });
1369 EXPECT_EQ(evens.size(), 2);
1370
1371 // all exists
1372 EXPECT_TRUE(list.all([](int x) { return x <= 5; }));
1373
1374 // exists works
1375 EXPECT_TRUE(list.exists([](int x) { return x == 3; }));
1376}
1377
1378
1379// =============================================================================
1380// EqualSequenceMethod Tests
1381// Exercises equal_to(), operator==, and operator!= on Array<T> and DynArray<T>,
1382// both of which inherit EqualSequenceMethod via CRTP.
1383// =============================================================================
1384
1385// Helper: build an Array<int> from an initializer list.
1386static Array<int> make_array(std::initializer_list<int> vals)
1387{
1388 Array<int> a;
1389 for (int v : vals)
1390 a.append(v);
1391 return a;
1392}
1393
1394// Helper: build a DynArray<int> from an initializer list.
1395static DynArray<int> make_dynarray(std::initializer_list<int> vals)
1396{
1397 DynArray<int> a;
1398 for (int v : vals)
1399 a.append(v);
1400 return a;
1401}
1402
1404{
1405 // Containers with different sizes must compare unequal regardless of content.
1406 const Array<int> a3 = make_array({1, 2, 3});
1407 const Array<int> a2 = make_array({1, 2});
1408
1409 EXPECT_FALSE(a3.equal_to(a2));
1410 EXPECT_FALSE(a2.equal_to(a3));
1411 EXPECT_FALSE(a3 == a2);
1412 EXPECT_TRUE(a3 != a2);
1413
1414 const DynArray<int> d3 = make_dynarray({1, 2, 3});
1415 const DynArray<int> d2 = make_dynarray({1, 2});
1416
1417 EXPECT_FALSE(d3.equal_to(d2));
1418 EXPECT_FALSE(d2.equal_to(d3));
1419 EXPECT_FALSE(d3 == d2);
1420 EXPECT_TRUE(d3 != d2);
1421}
1422
1424{
1425 // equal_to(self) must return true via the identity fast-path.
1426 const Array<int> a = make_array({10, 20, 30});
1427 EXPECT_TRUE(a.equal_to(a));
1428 EXPECT_TRUE(a == a);
1429 EXPECT_FALSE(a != a);
1430
1431 const DynArray<int> d = make_dynarray({10, 20, 30});
1432 EXPECT_TRUE(d.equal_to(d));
1433 EXPECT_TRUE(d == d);
1434 EXPECT_FALSE(d != d);
1435}
1436
1438{
1439 // Same multiset, different traversal order → unequal (order-sensitive).
1440 const Array<int> a1 = make_array({1, 2, 3});
1441 const Array<int> a2 = make_array({3, 2, 1});
1442
1443 EXPECT_FALSE(a1.equal_to(a2));
1444 EXPECT_FALSE(a1 == a2);
1445 EXPECT_TRUE(a1 != a2);
1446
1447 const DynArray<int> d1 = make_dynarray({1, 2, 3});
1448 const DynArray<int> d2 = make_dynarray({3, 2, 1});
1449
1450 EXPECT_FALSE(d1.equal_to(d2));
1451 EXPECT_FALSE(d1 == d2);
1452 EXPECT_TRUE(d1 != d2);
1453}
1454
1456{
1457 // Same elements but different duplicate counts → unequal.
1458 const Array<int> a1 = make_array({1, 1, 2}); // two 1s
1459 const Array<int> a2 = make_array({1, 2, 2}); // two 2s
1460
1461 EXPECT_FALSE(a1.equal_to(a2));
1462 EXPECT_FALSE(a1 == a2);
1463 EXPECT_TRUE(a1 != a2);
1464
1465 const DynArray<int> d1 = make_dynarray({5, 5, 7});
1466 const DynArray<int> d2 = make_dynarray({5, 7, 7});
1467
1468 EXPECT_FALSE(d1.equal_to(d2));
1469 EXPECT_FALSE(d1 == d2);
1470 EXPECT_TRUE(d1 != d2);
1471}
1472
1474{
1475 // Sanity-check the positive case: identical content → equal.
1476 const Array<int> a1 = make_array({4, 5, 6});
1477 const Array<int> a2 = make_array({4, 5, 6});
1478
1479 EXPECT_TRUE(a1.equal_to(a2));
1480 EXPECT_TRUE(a1 == a2);
1481 EXPECT_FALSE(a1 != a2);
1482
1483 const DynArray<int> d1 = make_dynarray({4, 5, 6});
1484 const DynArray<int> d2 = make_dynarray({4, 5, 6});
1485
1486 EXPECT_TRUE(d1.equal_to(d2));
1487 EXPECT_TRUE(d1 == d2);
1488 EXPECT_FALSE(d1 != d2);
1489}
1490
1492{
1493 const Array<int> a1, a2;
1494 EXPECT_TRUE(a1.equal_to(a2));
1495 EXPECT_TRUE(a1 == a2);
1496 EXPECT_FALSE(a1 != a2);
1497
1498 const DynArray<int> d1, d2;
1499 EXPECT_TRUE(d1.equal_to(d2));
1500 EXPECT_TRUE(d1 == d2);
1501 EXPECT_FALSE(d1 != d2);
1502}
1503
1505{
1506 // Array
1507 Array<int> a1 = {10};
1508 Array<int> a2 = {10};
1509 Array<int> a3 = {20};
1510
1511 EXPECT_TRUE(a1.equal_to(a1)); // Self
1512 EXPECT_TRUE(a1.equal_to(a2)); // Equal
1513 EXPECT_FALSE(a1.equal_to(a3)); // Not equal value
1514 EXPECT_TRUE(a1 != a3);
1515
1516 // DynArray
1517 DynArray<int> d1 = {10};
1518 DynArray<int> d2 = {10};
1519 DynArray<int> d3 = {20};
1520
1521 EXPECT_TRUE(d1 == d2);
1522 EXPECT_FALSE(d1 == d3);
1523}
1524
1526{
1527 constexpr size_t N = 10000;
1528 Array<int> a1, a2;
1529 DynArray<int> d1, d2;
1530
1531 for (size_t i = 0; i < N; ++i)
1532 {
1533 a1.append(i);
1534 a2.append(i);
1535 d1.append(i);
1536 d2.append(i);
1537 }
1538
1539 EXPECT_TRUE(a1 == a2);
1540 EXPECT_TRUE(d1 == d2);
1541 EXPECT_TRUE(a1.equal_to(a2));
1542 EXPECT_TRUE(d1.equal_to(d2));
1543 EXPECT_FALSE(a1 != a2);
1544 EXPECT_FALSE(d1 != d2);
1545
1546 // Differ at one position
1547 a2(N/2) = -1;
1548 d2(N/2) = -1;
1549
1550 EXPECT_FALSE(a1 == a2);
1551 EXPECT_FALSE(d1 == d2);
1552 EXPECT_FALSE(a1.equal_to(a2));
1553 EXPECT_FALSE(d1.equal_to(d2));
1554 EXPECT_TRUE(a1 != a2);
1555 EXPECT_TRUE(d1 != d2);
1556}
1557
CRTP Mixins for container functionality (DRY principle).
static DynArray< int > make_dynarray(std::initializer_list< int > vals)
static Array< int > make_array(std::initializer_list< int > vals)
long double w
Definition btreepic.C:153
Simple dynamic array with automatic resizing and functional operations.
Definition tpl_array.H:139
T & append(const T &data)
Append a copy of data
Definition tpl_array.H:245
T & append()
Allocate a new entry to the end of array.
Dynamic singly linked list with functional programming support.
Definition htlist.H:1155
T & append(const T &item)
Definition htlist.H:1271
CRTP Mixin providing functional programming operations.
size_t find_index(Predicate pred) const
Find the index of the first element satisfying a predicate.
bool all(Operation &operation) const
Test if all elements satisfy a predicate.
const Type * min_by(Compare cmp) const
Find the minimum element using a custom comparator.
auto mutable_for_each(Operation &operation) -> decltype(self())
Apply an operation to each element (mutable).
Container< Type > drop(const size_t n) const
Skip the first n elements.
Container< std::pair< size_t, Type > > enumerate() const
Enumerate elements with their indices.
Container< Container< Type > > chunk(size_t n) const
Split into chunks of fixed size.
size_t count_if(Predicate pred) const
Count elements satisfying a predicate.
DynListType to_dynlist() const
Convert container to DynList.
DynList< Type > filter(Operation &operation) const
Filter elements by a predicate.
const Type * max() const
Find the maximum element.
Container< Type > rev() const
Create a reversed copy.
Container< __Type > maps(Operation &operation) const
Transform elements using a mapping function.
Container< Container< Type > > sliding(size_t size, size_t step=1) const
Create sliding windows of fixed size.
Container< Type > take(const size_t n) const
Take the first n elements.
std::string join_str(const std::string &sep=", ") const
Join string elements with separator.
Container< Type > unique() const
Remove consecutive duplicate elements.
const Type * first() const
Get the first element.
Container< std::pair< Type, typename Other::Item_Type > > zip_with(const Other &other) const
Zip with another container.
bool none(Predicate &pred) const
Check if no element satisfies a predicate.
Type last_or(const Type &default_val) const
Get the last element or a default value.
bool has_value(const Type &val) const
Check if container has a value.
StringType join(const StringType &sep=StringType{", "}) const
Join elements into a string with separator.
bool exists(Operation &operation) const
Test if any element satisfies a predicate.
size_t index_of(const Type &val) const
Find the index of a specific value.
__Type foldl(const __Type &init, std::function< __Type(const __Type &, const Type &)> operation) const
Left fold (reduce) with initial value.
auto for_each(Operation &operation) const -> decltype(self())
Apply an operation to each element (read-only).
Type product(const Type &init) const
Compute the product of all elements.
size_t length() const noexcept
Count the number of elements.
Container< Type > unique_by(EqPred eq) const
Remove consecutive duplicates using a custom equality predicate.
Type sum(const Type &init=Type{}) const
Compute the sum of all elements.
const Type * max_by(Compare cmp) const
Find the maximum element using a custom comparator.
std::pair< DynList< Type >, DynList< Type > > partition(Operation &op) const
Partition elements by a predicate.
std::vector< Type > to_vector() const
Convert to std::vector.
Container< Type > intersperse(const Type &sep) const
Intersperse a separator between elements.
Type first_or(const Type &default_val) const
Get the first element or a default value.
const Type * last() const
Get the last element.
const Type * min() const
Find the minimum element.
constexpr bool is_empty() const noexcept
Definition htlist.H:419
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1065
CRTP Mixin for extracting keys from set-like containers.
Container< Type > items() const
Alias for keys().
Container< Type > keys() const
Extract all keys as a list.
CRTP Mixin providing element location operations.
std::tuple< bool, Type > find_item(Operation &operation)
Find element with success flag.
Type * find_ptr(Operation &operation)
Find the first element satisfying a predicate.
Type & nth_ne(const size_t n) const noexcept
Access the n-th element (unchecked).
Type & nth(const size_t n) const
Access the n-th element (bounds-checked).
CRTP Mixin providing traversal operations.
bool traverse(Operation &operation) const
Traverse all elements, applying an operation to each.
Mixin providing equality comparison for sequence containers.
Definition ah-dry.H:1756
bool equal_to(const Container &r) const
Equality test between this and r.
Definition ah-dry.H:1775
__T foldl(const __T &init, Op &op) const
Fold the elements of the container to a specific result.
Definition ah-dry.H:1200
Aleph::DynList< T > filter(Operation &operation) const
Filter the elements of a container according to a matching criterion.
Definition ah-dry.H:1319
bool exists(Operation &op) const
Test for existence in the container of an element satisfying a criterion.
Definition ah-dry.H:993
bool all(Operation &operation) const
Check if all the elements of the container satisfy a condition.
Definition ah-dry.H:957
void for_each(Operation &operation)
Traverse all the container and performs an operation on each element.
Definition ah-dry.H:779
Aleph::DynList< __T > maps(Operation &op) const
Map the elements of the container.
Definition ah-dry.H:1057
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
Definition ah-dry.H:222
Iterator(const MixinVector &c)
const MixinVector * container
bool has_curr() const noexcept
Simple test container using std::vector internally but with Aleph mixins.
void insert(const T &item)
Iterator get_it() const
bool operator==(const MixinVector &other) const
void append(const T &item)
std::vector< T > data
MixinVector()=default
MixinVector(std::initializer_list< T > init)
size_t size() const noexcept
bool is_empty() const noexcept
#define TEST(name)
#define N
Definition fib.C:294
Singly linked list implementations with head-tail access.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
std::string tolower(const char *str)
Convert a C std::string to lower-case.
const Container::Item_Type * min_ptr(const Container &container, Cmp cmp=Cmp())
Find the minimum element in a container.
bool all(Container &container, Operation &operation)
Return true if all elements satisfy a predicate.
bool completed() const noexcept
Return true if all underlying iterators are finished.
Definition ah-zip.H:136
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:105
T product(const Container &container, const T &init=T{1})
Compute product of all elements.
const Container::Item_Type * max_ptr(const Container &container, Cmp cmp=Cmp())
Find the maximum element in a container.
std::string to_string(const time_t t, const std::string &format)
Format a time_t value into a string using format.
Definition ah-date.H:140
static std::atomic< bool > init
Definition hash-fct.C:53
T sum(const Container &container, const T &init=T{})
Compute sum of all elements.
STL namespace.
#define is_odd(x)
Definition ran_array.c:30
Represents a missing value.
bool operator==(const EqOnlyType &other) const
bool operator<(const LtOnlyType &other) const
static int * k
Dynamic array container with automatic resizing.
Lazy and scalable dynamic array implementation.