Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
ah-stl-functional_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
44#include <gtest/gtest.h>
45#include <numeric>
46#include <ah-stl-functional.H>
47
48#include <vector>
49#include <list>
50#include <deque>
51#include <string>
52
53using namespace Aleph;
54
55//==============================================================================
56// Range Generation Tests
57//==============================================================================
58
60{
61 auto r = stl_range(1, 5);
62 EXPECT_EQ(r.size(), 5);
63 EXPECT_EQ(r[0], 1);
64 EXPECT_EQ(r[4], 5);
65}
66
68{
69 auto r = stl_range(0, 10, 2);
70 EXPECT_EQ(r.size(), 6);
71 EXPECT_EQ(r[0], 0);
72 EXPECT_EQ(r[5], 10);
73}
74
76{
77 auto r = stl_range(5);
78 EXPECT_EQ(r.size(), 5);
79 EXPECT_EQ(r[0], 0);
80 EXPECT_EQ(r[4], 4);
81}
82
84{
85 auto r = stl_linspace(0.0, 1.0, 5);
86 EXPECT_EQ(r.size(), 5);
87 EXPECT_DOUBLE_EQ(r[0], 0.0);
88 EXPECT_DOUBLE_EQ(r[4], 1.0);
89}
90
92{
93 auto r = stl_rep(5, 42);
94 EXPECT_EQ(r.size(), 5);
95 for (int x : r)
96 EXPECT_EQ(x, 42);
97}
98
100{
101 auto r = stl_generate(5, [](size_t i) { return i * i; });
102 EXPECT_EQ(r.size(), 5);
103 EXPECT_EQ(r[0], 0);
104 EXPECT_EQ(r[2], 4);
105 EXPECT_EQ(r[4], 16);
106}
107
108//==============================================================================
109// Core Functional Operations Tests
110//==============================================================================
111
113{
114 std::vector<int> v = {1, 2, 3, 4, 5};
115 int sum = 0;
116 stl_for_each([&sum](int x) { sum += x; }, v);
117 EXPECT_EQ(sum, 15);
118}
119
121{
122 std::vector<std::string> v = {"a", "b", "c"};
123 std::vector<std::string> results;
124 stl_for_each_indexed([&results](size_t i, const std::string& s) {
125 results.push_back(std::to_string(i) + ":" + s);
126 }, v);
127
128 EXPECT_EQ(results[0], "0:a");
129 EXPECT_EQ(results[2], "2:c");
130}
131
133{
134 std::vector<int> v = {1, 2, 3, 4, 5};
135 auto squares = stl_map([](int x) { return x * x; }, v);
136
137 EXPECT_EQ(squares.size(), 5);
138 EXPECT_EQ(squares[0], 1);
139 EXPECT_EQ(squares[2], 9);
140 EXPECT_EQ(squares[4], 25);
141}
142
144{
145 std::vector<int> v = {1, 2, 3};
146 auto strings = stl_map([](int x) { return std::to_string(x); }, v);
147
148 EXPECT_EQ(strings[0], "1");
149 EXPECT_EQ(strings[2], "3");
150}
151
153{
154 std::vector<std::string> v = {"a", "b", "c"};
155 auto results = stl_mapi([](size_t i, const std::string& s) {
156 return std::to_string(i) + s;
157 }, v);
158
159 EXPECT_EQ(results[0], "0a");
160 EXPECT_EQ(results[2], "2c");
161}
162
164{
165 std::vector<int> v = {1, 2, 3, 4, 5, 6};
166 auto evens = stl_filter([](int x) { return x % 2 == 0; }, v);
167
168 EXPECT_EQ(evens.size(), 3);
169 EXPECT_EQ(evens[0], 2);
170 EXPECT_EQ(evens[2], 6);
171}
172
174{
175 std::vector<int> v = {10, 20, 30, 40, 50};
176 auto evens = stl_filteri([](size_t i, int) { return i % 2 == 0; }, v);
177
178 EXPECT_EQ(evens.size(), 3);
179 EXPECT_EQ(evens[0], 10);
180 EXPECT_EQ(evens[1], 30);
181 EXPECT_EQ(evens[2], 50);
182}
183
184//==============================================================================
185// Fold Tests
186//==============================================================================
187
189{
190 std::vector<int> v = {1, 2, 3, 4, 5};
191 int sum = stl_foldl(0, [](int acc, int x) { return acc + x; }, v);
192 EXPECT_EQ(sum, 15);
193}
194
196{
197 std::vector<int> v = {1, 2, 3, 4};
198 int product = stl_foldl(1, [](int acc, int x) { return acc * x; }, v);
199 EXPECT_EQ(product, 24);
200}
201
203{
204 // Right fold: 1 - (2 - (3 - 0)) = 1 - (2 - 3) = 1 - (-1) = 2
205 std::vector<int> v = {1, 2, 3};
206 int result = stl_foldr(0, [](int x, int acc) { return x - acc; }, v);
207 EXPECT_EQ(result, 2);
208}
209
211{
212 // Right fold to construct string: "1" + ("2" + ("3" + ""))
213 std::vector<int> v = {1, 2, 3};
214 std::string result = stl_foldr(std::string(""), [](int x, std::string acc) {
215 return std::to_string(x) + acc;
216 }, v);
217 EXPECT_EQ(result, "123");
218}
219
221{
222 std::vector<int> v = {1, 2, 3, 4};
223 auto sums = stl_scan_left(0, [](int acc, int x) { return acc + x; }, v);
224
225 EXPECT_EQ(sums.size(), 5);
226 EXPECT_EQ(sums[0], 0); // init
227 EXPECT_EQ(sums[1], 1); // 0 + 1
228 EXPECT_EQ(sums[2], 3); // 1 + 2
229 EXPECT_EQ(sums[3], 6); // 3 + 3
230 EXPECT_EQ(sums[4], 10); // 6 + 4
231}
232
234{
235 std::vector<int> v = {1, 2, 3};
236 auto results = stl_scan_right(0, [](int x, int acc) { return x + acc; }, v);
237
238 // scan_right [1,2,3] with + and 0: [6, 5, 3, 0]
239 EXPECT_EQ(results.size(), 4);
240 EXPECT_EQ(results[0], 6); // 1+2+3+0
241 EXPECT_EQ(results[1], 5); // 2+3+0
242 EXPECT_EQ(results[2], 3); // 3+0
243 EXPECT_EQ(results[3], 0); // init
244}
245
246//==============================================================================
247// Predicate Tests
248//==============================================================================
249
251{
252 std::vector<int> v = {2, 4, 6, 8};
253 EXPECT_TRUE(stl_all([](int x) { return x % 2 == 0; }, v));
254}
255
257{
258 std::vector<int> v = {2, 3, 6, 8};
259 EXPECT_FALSE(stl_all([](int x) { return x % 2 == 0; }, v));
260}
261
263{
264 std::vector<int> v = {1, 2, 3, 4, 5};
265 EXPECT_TRUE(stl_exists([](int x) { return x == 3; }, v));
266}
267
269{
270 std::vector<int> v = {1, 2, 3, 4, 5};
271 EXPECT_FALSE(stl_exists([](int x) { return x == 10; }, v));
272}
273
275{
276 std::vector<int> v = {1, 3, 5, 7};
277 EXPECT_TRUE(stl_none([](int x) { return x % 2 == 0; }, v));
278}
279
280//==============================================================================
281// Finding Tests
282//==============================================================================
283
285{
286 std::vector<int> v = {1, 2, 3, 4, 5};
287 auto result = stl_find([](int x) { return x > 3; }, v);
288
289 ASSERT_TRUE(result.has_value());
290 EXPECT_EQ(*result, 4);
291}
292
294{
295 std::vector<int> v = {1, 2, 3};
296 auto result = stl_find([](int x) { return x > 10; }, v);
297
298 EXPECT_FALSE(result.has_value());
299}
300
302{
303 std::vector<int> v = {1, 2, 3, 4, 5};
304 auto result = stl_find_last([](int x) { return x % 2 == 0; }, v);
305
306 ASSERT_TRUE(result.has_value());
307 EXPECT_EQ(*result, 4);
308}
309
311{
312 std::vector<std::string> v = {"a", "b", "c", "d"};
313 auto result = stl_find_index([](const std::string& s) { return s == "c"; }, v);
314
315 ASSERT_TRUE(result.has_value());
316 EXPECT_EQ(*result, 2);
317}
318
320{
321 std::vector<int> v = {1, 2, 3, 4, 5};
322 auto result = stl_find_mapi([](size_t i, int x) -> std::optional<std::string> {
323 if (x == 3)
324 return "found at " + std::to_string(i);
325 return std::nullopt;
326 }, v);
327
328 ASSERT_TRUE(result.has_value());
329 EXPECT_EQ(*result, "found at 2");
330}
331
333{
334 std::vector<int> v = {1, 2, 3, 4, 5};
335 EXPECT_TRUE(stl_mem(3, v));
336 EXPECT_FALSE(stl_mem(10, v));
337}
338
339//==============================================================================
340// Counting Tests
341//==============================================================================
342
344{
345 std::vector<int> v = {1, 2, 3, 4, 5, 6};
346 size_t count = stl_count([](int x) { return x % 2 == 0; }, v);
347 EXPECT_EQ(count, 3);
348}
349
351{
352 std::vector<int> v = {1, 2, 2, 3, 2, 4};
353 EXPECT_EQ(stl_count_value(2, v), 3);
354}
355
356//==============================================================================
357// Take and Drop Tests
358//==============================================================================
359
361{
362 std::vector<int> v = {1, 2, 3, 4, 5};
363 auto result = stl_take(3, v);
364
365 EXPECT_EQ(result.size(), 3);
366 EXPECT_EQ(result[0], 1);
367 EXPECT_EQ(result[2], 3);
368}
369
371{
372 std::vector<int> v = {1, 2, 3, 4, 5};
373 auto result = stl_drop(2, v);
374
375 EXPECT_EQ(result.size(), 3);
376 EXPECT_EQ(result[0], 3);
377 EXPECT_EQ(result[2], 5);
378}
379
381{
382 std::vector<int> v = {1, 2, 3, 4, 5};
383 auto result = stl_take_last(3, v);
384
385 EXPECT_EQ(result.size(), 3);
386 EXPECT_EQ(result[0], 3);
387 EXPECT_EQ(result[2], 5);
388}
389
391{
392 std::vector<int> v = {1, 2, 3, 10, 4, 5};
393 auto result = stl_take_while([](int x) { return x < 10; }, v);
394
395 EXPECT_EQ(result.size(), 3);
396 EXPECT_EQ(result[2], 3);
397}
398
400{
401 std::vector<int> v = {1, 2, 3, 10, 4, 5};
402 auto result = stl_drop_while([](int x) { return x < 10; }, v);
403
404 EXPECT_EQ(result.size(), 3);
405 EXPECT_EQ(result[0], 10);
406}
407
408//==============================================================================
409// Accessing Tests
410//==============================================================================
411
413{
414 std::vector<int> v = {10, 20, 30};
415 auto result = stl_first(v);
416
417 ASSERT_TRUE(result.has_value());
418 EXPECT_EQ(*result, 10);
419}
420
422{
423 std::vector<int> v;
424 auto result = stl_first(v);
425
426 EXPECT_FALSE(result.has_value());
427}
428
430{
431 std::vector<int> v = {10, 20, 30};
432 auto result = stl_last(v);
433
434 ASSERT_TRUE(result.has_value());
435 EXPECT_EQ(*result, 30);
436}
437
439{
440 std::vector<int> v = {10, 20, 30, 40, 50};
441 auto result = stl_nth(2, v);
442
443 ASSERT_TRUE(result.has_value());
444 EXPECT_EQ(*result, 30);
445}
446
447//==============================================================================
448// Min/Max Tests
449//==============================================================================
450
452{
453 std::vector<int> v = {3, 1, 4, 1, 5, 9};
454 auto result = stl_min(v);
455
456 ASSERT_TRUE(result.has_value());
457 EXPECT_EQ(*result, 1);
458}
459
461{
462 std::vector<int> v = {3, 1, 4, 1, 5, 9};
463 auto result = stl_max(v);
464
465 ASSERT_TRUE(result.has_value());
466 EXPECT_EQ(*result, 9);
467}
468
470{
471 std::vector<int> v = {3, 1, 4, 1, 5, 9};
472 auto result = stl_min_max(v);
473
474 ASSERT_TRUE(result.has_value());
475 EXPECT_EQ(result->first, 1);
476 EXPECT_EQ(result->second, 9);
477}
478
480{
481 std::vector<std::string> v = {"hello", "a", "world"};
482 auto result = stl_min_by([](const std::string& s) { return s.length(); }, v);
483
484 ASSERT_TRUE(result.has_value());
485 EXPECT_EQ(*result, "a");
486}
487
489{
490 std::vector<std::string> v = {"hello", "a", "world"};
491 auto result = stl_max_by([](const std::string& s) { return s.length(); }, v);
492
493 ASSERT_TRUE(result.has_value());
494 EXPECT_EQ(*result, "hello");
495}
496
497//==============================================================================
498// Sum and Product Tests
499//==============================================================================
500
502{
503 std::vector<int> v = {1, 2, 3, 4, 5};
504 EXPECT_EQ(stl_sum(v), 15);
505}
506
508{
509 std::vector<int> v = {1, 2, 3, 4};
510 EXPECT_EQ(stl_product(v), 24);
511}
512
513//==============================================================================
514// Partition Tests
515//==============================================================================
516
518{
519 std::vector<int> v = {1, 2, 3, 4, 5, 6};
520 auto [evens, odds] = stl_partition([](int x) { return x % 2 == 0; }, v);
521
522 EXPECT_EQ(evens.size(), 3);
523 EXPECT_EQ(odds.size(), 3);
524}
525
526//==============================================================================
527// Zip and Enumerate Tests
528//==============================================================================
529
531{
532 std::vector<int> v1 = {1, 2, 3};
533 std::vector<std::string> v2 = {"a", "b", "c"};
534
535 auto result = stl_zip_to_pairs(v1, v2);
536
537 EXPECT_EQ(result.size(), 3);
538 EXPECT_EQ(result[0].first, 1);
539 EXPECT_EQ(result[0].second, "a");
540}
541
543{
544 std::vector<std::pair<int, std::string>> v = {{1, "a"}, {2, "b"}, {3, "c"}};
545
546 auto [nums, strs] = stl_unzip_pairs(v);
547
548 EXPECT_EQ(nums.size(), 3);
549 EXPECT_EQ(strs.size(), 3);
550 EXPECT_EQ(nums[1], 2);
551 EXPECT_EQ(strs[1], "b");
552}
553
555{
556 std::vector<std::string> v = {"a", "b", "c"};
557
558 auto result = stl_enumerate_to_pairs(v);
559
560 EXPECT_EQ(result.size(), 3);
561 EXPECT_EQ(result[0].first, 0);
562 EXPECT_EQ(result[0].second, "a");
563 EXPECT_EQ(result[2].first, 2);
564}
565
566//==============================================================================
567// Comparison Tests
568//==============================================================================
569
571{
572 std::vector<int> v1 = {1, 2, 3};
573 std::vector<int> v2 = {1, 2, 3};
574
575 EXPECT_TRUE(stl_equal(v1, v2));
576}
577
579{
580 std::vector<int> v1 = {1, 2, 3};
581 std::vector<int> v2 = {1, 2, 4};
582
583 EXPECT_FALSE(stl_equal(v1, v2));
584}
585
587{
588 std::vector<int> v1 = {1, 2, 3};
589 std::vector<int> v2 = {1, 2, 3};
590
591 EXPECT_EQ(stl_compare(v1, v2), 0);
592}
593
595{
596 std::vector<int> v1 = {1, 2, 3};
597 std::vector<int> v2 = {1, 2, 4};
598
599 EXPECT_EQ(stl_compare(v1, v2), -1);
600}
601
603{
604 std::vector<int> v1 = {1, 2, 4};
605 std::vector<int> v2 = {1, 2, 3};
606
607 EXPECT_EQ(stl_compare(v1, v2), 1);
608}
609
610//==============================================================================
611// Reverse and Sort Tests
612//==============================================================================
613
615{
616 std::vector<int> v = {1, 2, 3, 4, 5};
617 auto result = stl_reverse(v);
618
619 EXPECT_EQ(result[0], 5);
620 EXPECT_EQ(result[4], 1);
621}
622
624{
625 std::vector<int> v = {3, 1, 4, 1, 5, 9};
626 auto result = stl_sort(v);
627
628 EXPECT_EQ(result[0], 1);
629 EXPECT_EQ(result[5], 9);
630}
631
633{
634 std::vector<std::string> v = {"hello", "a", "world"};
635 auto result = stl_sort_by([](const std::string& a, const std::string& b) {
636 return a.length() < b.length();
637 }, v);
638
639 EXPECT_EQ(result[0], "a");
640 EXPECT_EQ(result[2], "world");
641}
642
643//==============================================================================
644// Uniqueness Tests
645//==============================================================================
646
648{
649 std::vector<int> v = {1, 1, 2, 2, 2, 3, 3};
650 auto result = stl_unique(v);
651
652 EXPECT_EQ(result.size(), 3);
653 EXPECT_EQ(result[0], 1);
654 EXPECT_EQ(result[1], 2);
655 EXPECT_EQ(result[2], 3);
656}
657
659{
660 std::vector<int> v = {1, 2, 1, 3, 2, 4};
661 auto result = stl_distinct(v);
662
663 EXPECT_EQ(result.size(), 4);
664}
665
666//==============================================================================
667// Concat and Flatten Tests
668//==============================================================================
669
671{
672 std::vector<int> v1 = {1, 2, 3};
673 std::vector<int> v2 = {4, 5, 6};
674
675 auto result = stl_concat(v1, v2);
676
677 EXPECT_EQ(result.size(), 6);
678 EXPECT_EQ(result[0], 1);
679 EXPECT_EQ(result[5], 6);
680}
681
683{
684 std::vector<std::vector<int>> v = {{1, 2}, {3, 4}, {5}};
685
686 auto result = stl_flatten(v);
687
688 EXPECT_EQ(result.size(), 5);
689 EXPECT_EQ(result[0], 1);
690 EXPECT_EQ(result[4], 5);
691}
692
694{
695 std::vector<int> v = {1, 2, 3};
696 auto result = stl_flat_map([](int x) {
697 return std::vector<int>{x, x * 10};
698 }, v);
699
700 EXPECT_EQ(result.size(), 6);
701 EXPECT_EQ(result[0], 1);
702 EXPECT_EQ(result[1], 10);
703 EXPECT_EQ(result[4], 3);
704 EXPECT_EQ(result[5], 30);
705}
706
707//==============================================================================
708// Grouping Tests
709//==============================================================================
710
712{
713 std::vector<int> v = {1, 1, 2, 2, 2, 3};
714
715 auto result = stl_group(v);
716
717 EXPECT_EQ(result.size(), 3);
718 EXPECT_EQ(result[0].size(), 2); // {1, 1}
719 EXPECT_EQ(result[1].size(), 3); // {2, 2, 2}
720 EXPECT_EQ(result[2].size(), 1); // {3}
721}
722
724{
725 std::vector<std::string> v = {"a", "bb", "c", "dd", "eee"};
726
727 auto result = stl_group_by([](const std::string& s) { return s.length(); }, v);
728
729 EXPECT_EQ(result.size(), 3); // lengths 1, 2, 3
730}
731
732//==============================================================================
733// Works with Different Container Types
734//==============================================================================
735
737{
738 std::list<int> l = {1, 2, 3, 4, 5};
739
740 auto squares = stl_map([](int x) { return x * x; }, l);
741 EXPECT_EQ(squares.size(), 5);
742 EXPECT_EQ(squares[4], 25);
743
744 int sum = stl_foldl(0, [](int acc, int x) { return acc + x; }, l);
745 EXPECT_EQ(sum, 15);
746
747 // foldr works with list (has rbegin/rend)
748 int result = stl_foldr(0, [](int x, int acc) { return x - acc; }, l);
749 EXPECT_EQ(result, 3); // 1-(2-(3-(4-(5-0)))) = 1-(2-(3-(4-5))) = ...
750}
751
753{
754 std::deque<int> d = {1, 2, 3, 4, 5};
755
756 auto evens = stl_filter([](int x) { return x % 2 == 0; }, d);
757 EXPECT_EQ(evens.size(), 2);
758}
759
760//==============================================================================
761// Combinatorics Tests
762//==============================================================================
763
765{
766 std::vector<int> v = {1, 2, 3};
767 auto perms = stl_permutations(v);
768
769 EXPECT_EQ(perms.size(), 6); // 3! = 6
770}
771
773{
774 std::vector<int> v = {1, 2, 3};
775 int count = 0;
776
777 bool completed = stl_traverse_permutations([&count](const auto&) {
778 ++count;
779 return count < 3; // stop after 3
780 }, v);
781
783 EXPECT_EQ(count, 3);
784}
785
787{
788 std::vector<int> v = {1, 2, 3, 4};
789 auto combos = stl_combinations(2, v);
790
791 // C(4,2) = 6
792 EXPECT_EQ(combos.size(), 6);
793
794 // Verify one combination
795 EXPECT_EQ(combos[0][0], 1);
796 EXPECT_EQ(combos[0][1], 2);
797}
798
800{
801 std::vector<int> v = {1, 2, 3, 4, 5};
802 auto combos = stl_combinations(3, v);
803
804 // C(5,3) = 10
805 EXPECT_EQ(combos.size(), 10);
806}
807
809{
810 std::vector<int> v = {1, 2, 3};
811 auto arrs = stl_arrangements(2, v);
812
813 // P(3,2) = 3!/(3-2)! = 6
814 EXPECT_EQ(arrs.size(), 6);
815}
816
818{
819 std::vector<std::vector<int>> sets = {{1, 2}, {3, 4}};
821
822 // 2 * 2 = 4
823 EXPECT_EQ(product.size(), 4);
824}
825
827{
828 std::vector<int> v = {1, 2, 3};
829 auto ps = stl_power_set(v);
830
831 // 2^3 = 8
832 EXPECT_EQ(ps.size(), 8);
833}
834
835//==============================================================================
836// Ruby/ML Operations Tests
837//==============================================================================
838
840{
841 std::vector<int> v = {1, 2, 3, 4, 5};
842 auto windows = stl_sliding_window(3, v);
843
844 EXPECT_EQ(windows.size(), 3);
845 EXPECT_EQ(windows[0], (std::vector<int>{1, 2, 3}));
846 EXPECT_EQ(windows[1], (std::vector<int>{2, 3, 4}));
847 EXPECT_EQ(windows[2], (std::vector<int>{3, 4, 5}));
848}
849
851{
852 std::vector<int> v = {1, 2, 3, 4, 5};
853 auto chunks = stl_chunks(2, v);
854
855 EXPECT_EQ(chunks.size(), 3);
856 EXPECT_EQ(chunks[0], (std::vector<int>{1, 2}));
857 EXPECT_EQ(chunks[1], (std::vector<int>{3, 4}));
858 EXPECT_EQ(chunks[2], (std::vector<int>{5}));
859}
860
862{
863 std::vector<int> v = {1, 2, 3};
864 auto result = stl_intersperse(0, v);
865
866 EXPECT_EQ(result, (std::vector<int>{1, 0, 2, 0, 3}));
867}
868
870{
871 std::vector<int> v = {1, 2, 3, 4, 5};
872 auto [first, second] = stl_split_at(2, v);
873
874 EXPECT_EQ(first, (std::vector<int>{1, 2}));
875 EXPECT_EQ(second, (std::vector<int>{3, 4, 5}));
876}
877
879{
880 std::vector<int> v = {1, 2, 3, 10, 4, 5};
881 auto [first, second] = stl_span([](int x) { return x < 10; }, v);
882
883 EXPECT_EQ(first, (std::vector<int>{1, 2, 3}));
884 EXPECT_EQ(second, (std::vector<int>{10, 4, 5}));
885}
886
888{
889 std::vector<int> v = {1, 2, 3, 4, 5};
890 auto result = stl_init(v);
891
892 EXPECT_EQ(result, (std::vector<int>{1, 2, 3, 4}));
893}
894
896{
897 std::vector<int> v = {1, 2, 3, 4, 5};
898 auto result = stl_tail(v);
899
900 EXPECT_EQ(result, (std::vector<int>{2, 3, 4, 5}));
901}
902
904{
905 std::vector<int> v = {1, 2, 2, 3, 3, 3};
906 auto result = stl_tally(v);
907
908 EXPECT_EQ(result.size(), 3);
909 EXPECT_EQ(result[0].first, 1);
910 EXPECT_EQ(result[0].second, 1);
911 EXPECT_EQ(result[1].first, 2);
912 EXPECT_EQ(result[1].second, 2);
913 EXPECT_EQ(result[2].first, 3);
914 EXPECT_EQ(result[2].second, 3);
915}
916
918{
919 std::vector<int> v = {1, 2, 3, 4, 5, 6};
920 auto result = stl_reject([](int x) { return x % 2 == 0; }, v);
921
922 EXPECT_EQ(result, (std::vector<int>{1, 3, 5}));
923}
924
925//==============================================================================
926// Performance Tests - Large Containers (Hash Path)
927//==============================================================================
928
930{
931 // Create container with 1000 elements, 100 distinct values
932 std::vector<int> large;
933 large.reserve(1000);
934 for (int i = 0; i < 1000; ++i)
935 large.push_back(i % 100);
936
937 auto result = stl_distinct(large);
938
939 EXPECT_EQ(result.size(), 100);
940 // Verify order preserved (first occurrence)
941 EXPECT_EQ(result[0], 0);
942 EXPECT_EQ(result[1], 1);
943 EXPECT_EQ(result[99], 99);
944}
945
947{
948 // 10000 elements, 500 distinct
949 std::vector<int> very_large;
950 very_large.reserve(10000);
951 for (int i = 0; i < 10000; ++i)
952 very_large.push_back(i % 500);
953
954 auto result = stl_distinct(very_large);
955
956 EXPECT_EQ(result.size(), 500);
957}
958
960{
961 std::vector<int> large;
962 large.reserve(1000);
963 for (int i = 0; i < 1000; ++i)
964 large.push_back(i % 100);
965
966 auto result = stl_tally(large);
967
968 EXPECT_EQ(result.size(), 100);
969 // Each value appears 10 times
970 for (const auto & [val, count] : result)
971 EXPECT_EQ(count, 10);
972}
973
975{
976 std::vector<int> large;
977 large.reserve(1000);
978 for (int i = 0; i < 1000; ++i)
979 large.push_back(i);
980
981 // Group by last digit
982 auto result = stl_group_by([](int x) { return x % 10; }, large);
983
984 EXPECT_EQ(result.size(), 10);
985 for (const auto & [key, group] : result)
986 EXPECT_EQ(group.size(), 100);
987}
988
989//==============================================================================
990// Edge Cases
991//==============================================================================
992
994{
995 std::vector<int> empty;
996 auto result = stl_distinct(empty);
997 EXPECT_TRUE(result.empty());
998}
999
1001{
1002 std::vector<int> single = {42};
1003 auto result = stl_distinct(single);
1004 EXPECT_EQ(result.size(), 1);
1005 EXPECT_EQ(result[0], 42);
1006}
1007
1009{
1010 std::vector<int> all_same(100, 42);
1011 auto result = stl_distinct(all_same);
1012 EXPECT_EQ(result.size(), 1);
1013 EXPECT_EQ(result[0], 42);
1014}
1015
1017{
1018 auto input = stl_range(0, 99);
1019 auto result = stl_distinct(input);
1020 EXPECT_EQ(result.size(), 100);
1021}
1022
1024{
1025 std::vector<int> empty;
1026 auto result = stl_tally(empty);
1027 EXPECT_TRUE(result.empty());
1028}
1029
1031{
1032 std::vector<int> single = {42};
1033 auto result = stl_tally(single);
1034 EXPECT_EQ(result.size(), 1);
1035 EXPECT_EQ(result[0].first, 42);
1036 EXPECT_EQ(result[0].second, 1);
1037}
1038
1040{
1041 std::vector<int> empty;
1042 auto result = stl_group_by([](int x) { return x; }, empty);
1043 EXPECT_TRUE(result.empty());
1044}
1045
1047{
1048 std::vector<int> single = {42};
1049 auto result = stl_group_by([](int x) { return x % 10; }, single);
1050 EXPECT_EQ(result.size(), 1);
1051 EXPECT_EQ(result[0].first, 2);
1052 EXPECT_EQ(result[0].second.size(), 1);
1053}
1054
1056{
1057 std::vector<int> v = {10, 20, 30, 40, 50};
1058 auto result = stl_group_by([](int x) { return x % 10; }, v);
1059 EXPECT_EQ(result.size(), 1);
1060 EXPECT_EQ(result[0].first, 0);
1061 EXPECT_EQ(result[0].second.size(), 5);
1062}
1063
1064//==============================================================================
1065// Small Container Tests (Linear Path - threshold <= 64)
1066//==============================================================================
1067
1069{
1070 // Exactly at threshold
1071 std::vector<int> at_threshold;
1072 for (int i = 0; i < 64; ++i)
1073 at_threshold.push_back(i % 32);
1074
1075 auto result = stl_distinct(at_threshold);
1076 EXPECT_EQ(result.size(), 32);
1077}
1078
1080{
1081 std::vector<int> small = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
1082 auto result = stl_tally(small);
1083
1084 EXPECT_EQ(result.size(), 4);
1085 EXPECT_EQ(result[0].second, 1); // 1 appears once
1086 EXPECT_EQ(result[1].second, 2); // 2 appears twice
1087 EXPECT_EQ(result[2].second, 3); // 3 appears three times
1088 EXPECT_EQ(result[3].second, 4); // 4 appears four times
1089}
1090
1091//==============================================================================
1092// Custom Types Tests
1093//==============================================================================
1094
1095namespace {
1096
1097struct Point
1098{
1099 int x, y;
1100
1101 bool operator==(const Point & other) const
1102 {
1103 return x == other.x && y == other.y;
1104 }
1105};
1106
1107struct PointHash
1108{
1109 size_t operator()(const Point & p) const
1110 {
1111 return std::hash<int>{}(p.x) ^ (std::hash<int>{}(p.y) << 1);
1112 }
1113};
1114
1115// Make Point hashable for std::unordered_set/map
1116} // anonymous namespace
1117
1118namespace std {
1119template<>
1120struct hash<Point>
1121{
1122 size_t operator()(const Point & p) const
1123 {
1124 return hash<int>{}(p.x) ^ (hash<int>{}(p.y) << 1);
1125 }
1126};
1127} // namespace std
1128
1130{
1131 std::vector<Point> points = {{1, 2}, {3, 4}, {1, 2}, {5, 6}, {3, 4}};
1132 auto result = stl_distinct(points);
1133
1134 EXPECT_EQ(result.size(), 3);
1135 EXPECT_EQ(result[0].x, 1);
1136 EXPECT_EQ(result[0].y, 2);
1137}
1138
1140{
1141 std::vector<Point> points;
1142 points.reserve(200);
1143 for (int i = 0; i < 200; ++i)
1144 points.push_back({i % 50, i % 25});
1145
1146 auto result = stl_distinct(points);
1147 // 50 * 25 = 1250 possible, but we only have 200 elements with some repeats
1148 EXPECT_LE(result.size(), 200);
1149 EXPECT_GT(result.size(), 0);
1150}
1151
1153{
1154 std::vector<Point> points = {{1, 2}, {3, 4}, {1, 2}, {5, 6}, {1, 2}};
1155 auto result = stl_tally(points);
1156
1157 EXPECT_EQ(result.size(), 3);
1158 // Find the count for {1,2}
1159 auto it = std::find_if(result.begin(), result.end(),
1160 [](const auto & p) { return p.first.x == 1 && p.first.y == 2; });
1161 ASSERT_NE(it, result.end());
1162 EXPECT_EQ(it->second, 3);
1163}
1164
1166{
1167 std::vector<Point> points = {
1168 {1, 1}, {-1, 1}, {-1, -1}, {1, -1},
1169 {2, 3}, {-2, 3}, {-2, -3}, {2, -3}
1170 };
1171
1172 auto quadrant = [](const Point & p) {
1173 if (p.x >= 0 && p.y >= 0) return 1;
1174 if (p.x < 0 && p.y >= 0) return 2;
1175 if (p.x < 0 && p.y < 0) return 3;
1176 return 4;
1177 };
1178
1179 auto result = stl_group_by(quadrant, points);
1180
1181 EXPECT_EQ(result.size(), 4);
1182 for (const auto & [quad, pts] : result)
1183 EXPECT_EQ(pts.size(), 2);
1184}
1185
1186//==============================================================================
1187// Move Semantics and Forwarding Tests
1188//==============================================================================
1189
1190namespace {
1191
1192struct MoveTracker
1193{
1194 int value;
1195 static int move_count;
1196 static int copy_count;
1197
1198 MoveTracker(int v = 0) : value(v) {}
1199
1200 MoveTracker(const MoveTracker & other) : value(other.value)
1201 {
1202 ++copy_count;
1203 }
1204
1205 MoveTracker(MoveTracker && other) noexcept : value(other.value)
1206 {
1207 other.value = -1;
1208 ++move_count;
1209 }
1210
1211 MoveTracker & operator=(const MoveTracker & other)
1212 {
1213 value = other.value;
1214 ++copy_count;
1215 return *this;
1216 }
1217
1218 MoveTracker & operator=(MoveTracker && other) noexcept
1219 {
1220 value = other.value;
1221 other.value = -1;
1222 ++move_count;
1223 return *this;
1224 }
1225
1226 bool operator==(const MoveTracker & other) const
1227 {
1228 return value == other.value;
1229 }
1230
1231 static void reset()
1232 {
1233 move_count = 0;
1234 copy_count = 0;
1235 }
1236};
1237
1238int MoveTracker::move_count = 0;
1239int MoveTracker::copy_count = 0;
1240
1241} // anonymous namespace
1242
1243namespace std {
1244template<>
1245struct hash<MoveTracker>
1246{
1247 size_t operator()(const MoveTracker & m) const
1248 {
1249 return hash<int>{}(m.value);
1250 }
1251};
1252} // namespace std
1253
1255{
1256 std::vector<int> v = {1, 2, 3};
1257 std::string prefix = "num_";
1258
1259 auto result = stl_map([&prefix](int x) {
1260 return prefix + std::to_string(x);
1261 }, v);
1262
1263 EXPECT_EQ(result[0], "num_1");
1264 EXPECT_EQ(result[1], "num_2");
1265 EXPECT_EQ(result[2], "num_3");
1266}
1267
1269{
1270 std::vector<int> v = {1, 2, 3, 4, 5};
1271 int threshold = 3;
1272
1273 // Mutable lambda that modifies captured state
1274 int call_count = 0;
1275 auto result = stl_filter([&call_count, threshold](int x) mutable {
1276 ++call_count;
1277 return x > threshold;
1278 }, v);
1279
1280 EXPECT_EQ(result.size(), 2);
1281 EXPECT_EQ(call_count, 5);
1282}
1283
1285{
1286 std::vector<std::string> words = {"hello", " ", "world"};
1287
1288 auto result = stl_foldl(std::string{}, [](std::string acc, const std::string & w) {
1289 return acc + w;
1290 }, words);
1291
1292 EXPECT_EQ(result, "hello world");
1293}
1294
1295//==============================================================================
1296// Different Container Types
1297//==============================================================================
1298
1300{
1301 std::list<int> l = {1, 2, 1, 3, 2, 4};
1302 auto result = stl_distinct(l);
1303 EXPECT_EQ(result.size(), 4);
1304}
1305
1307{
1308 std::deque<int> d = {1, 2, 1, 3, 2, 4};
1309 auto result = stl_distinct(d);
1310 EXPECT_EQ(result.size(), 4);
1311}
1312
1314{
1315 std::list<int> l = {1, 2, 2, 3, 3, 3};
1316 auto result = stl_tally(l);
1317 EXPECT_EQ(result.size(), 3);
1318}
1319
1321{
1322 std::list<std::string> l = {"a", "bb", "ccc", "dd", "e"};
1323 auto result = stl_group_by([](const std::string & s) { return s.length(); }, l);
1324 EXPECT_EQ(result.size(), 3);
1325}
1326
1327//==============================================================================
1328// Order Preservation Tests
1329//==============================================================================
1330
1332{
1333 std::vector<int> v = {5, 3, 5, 1, 3, 7, 1, 5};
1334 auto result = stl_distinct(v);
1335
1336 ASSERT_EQ(result.size(), 4);
1337 EXPECT_EQ(result[0], 5); // First occurrence
1338 EXPECT_EQ(result[1], 3);
1339 EXPECT_EQ(result[2], 1);
1340 EXPECT_EQ(result[3], 7);
1341}
1342
1344{
1345 // Test with hash path
1346 std::vector<int> v;
1347 v.reserve(200);
1348 for (int i = 199; i >= 0; --i)
1349 v.push_back(i % 100);
1350
1351 auto result = stl_distinct(v);
1352
1353 ASSERT_EQ(result.size(), 100);
1354 // First occurrence of 99 is at index 0 (199 % 100 = 99)
1355 EXPECT_EQ(result[0], 99);
1356 // First occurrence of 98 is at index 1 (198 % 100 = 98)
1357 EXPECT_EQ(result[1], 98);
1358}
1359
1361{
1362 std::vector<int> v = {5, 3, 5, 1, 3, 7, 1, 5};
1363 auto result = stl_tally(v);
1364
1365 ASSERT_EQ(result.size(), 4);
1366 EXPECT_EQ(result[0].first, 5);
1367 EXPECT_EQ(result[0].second, 3);
1368 EXPECT_EQ(result[1].first, 3);
1369 EXPECT_EQ(result[1].second, 2);
1370 EXPECT_EQ(result[2].first, 1);
1371 EXPECT_EQ(result[2].second, 2);
1372 EXPECT_EQ(result[3].first, 7);
1373 EXPECT_EQ(result[3].second, 1);
1374}
1375
1377{
1378 std::vector<int> v = {15, 23, 31, 42, 54};
1379 auto result = stl_group_by([](int x) { return x % 10; }, v);
1380
1381 ASSERT_EQ(result.size(), 5);
1382 // First key seen is 5 (from 15)
1383 EXPECT_EQ(result[0].first, 5);
1384 // Second key seen is 3 (from 23)
1385 EXPECT_EQ(result[1].first, 3);
1386}
1387
1388//==============================================================================
1389// String Tests
1390//==============================================================================
1391
1393{
1394 std::vector<std::string> v = {"apple", "banana", "apple", "cherry", "banana"};
1395 auto result = stl_distinct(v);
1396
1397 ASSERT_EQ(result.size(), 3);
1398 EXPECT_EQ(result[0], "apple");
1399 EXPECT_EQ(result[1], "banana");
1400 EXPECT_EQ(result[2], "cherry");
1401}
1402
1404{
1405 std::vector<std::string> v;
1406 v.reserve(200);
1407 for (int i = 0; i < 200; ++i)
1408 v.push_back("str_" + std::to_string(i % 50));
1409
1410 auto result = stl_distinct(v);
1411 EXPECT_EQ(result.size(), 50);
1412}
1413
1415{
1416 std::vector<std::string> v = {"a", "bb", "ccc", "dd", "eee", "f"};
1417 auto result = stl_group_by([](const std::string & s) { return s.length(); }, v);
1418
1419 EXPECT_EQ(result.size(), 3);
1420}
1421
1423{
1424 std::vector<std::string> v = {"apple", "apricot", "banana", "blueberry", "cherry"};
1425 auto result = stl_group_by([](const std::string & s) { return s[0]; }, v);
1426
1427 EXPECT_EQ(result.size(), 3); // a, b, c
1428}
1429
1430//==============================================================================
1431// Boundary Tests (around threshold = 64)
1432//==============================================================================
1433
1435{
1436 std::vector<int> v;
1437 for (int i = 0; i < 63; ++i)
1438 v.push_back(i % 30);
1439
1440 auto result = stl_distinct(v);
1441 EXPECT_EQ(result.size(), 30);
1442}
1443
1445{
1446 std::vector<int> v;
1447 for (int i = 0; i < 64; ++i)
1448 v.push_back(i % 30);
1449
1450 auto result = stl_distinct(v);
1451 EXPECT_EQ(result.size(), 30);
1452}
1453
1455{
1456 std::vector<int> v;
1457 for (int i = 0; i < 65; ++i)
1458 v.push_back(i % 30);
1459
1460 auto result = stl_distinct(v);
1461 EXPECT_EQ(result.size(), 30);
1462}
1463
1464//==============================================================================
1465// Composition Tests
1466//==============================================================================
1467
1469{
1470 std::vector<int> v = {1, 2, 1, 3, 2, 4};
1471 auto distinct = stl_distinct(v);
1472 auto squared = stl_map([](int x) { return x * x; }, distinct);
1473
1474 EXPECT_EQ(squared, (std::vector<int>{1, 4, 9, 16}));
1475}
1476
1478{
1479 std::vector<int> v = {1, 2, 3, 4, 5, 6, 1, 2, 3};
1480 auto evens = stl_filter([](int x) { return x % 2 == 0; }, v);
1482
1483 EXPECT_EQ(unique_evens, (std::vector<int>{2, 4, 6}));
1484}
1485
1487{
1488 std::vector<int> v = {1, 2, 3, 4, 5, 6};
1489 auto groups = stl_group_by([](int x) { return x % 2; }, v);
1490 auto sums = stl_map([](const auto & p) {
1491 return std::make_pair(p.first, stl_foldl(0, std::plus<int>{}, p.second));
1492 }, groups);
1493
1494 EXPECT_EQ(sums.size(), 2);
1495}
1496
1497//==============================================================================
1498// forward_list Compatibility Tests (containers without size())
1499//==============================================================================
1500
1501#include <forward_list>
1502
1504{
1505 std::forward_list<int> fl = {1, 2, 3, 4, 5};
1506 auto result = stl_map([](int x) { return x * 2; }, fl);
1507
1508 EXPECT_EQ(result.size(), 5);
1509 EXPECT_EQ(result[0], 2);
1510 EXPECT_EQ(result[4], 10);
1511}
1512
1514{
1515 std::forward_list<int> fl = {1, 2, 3, 4, 5, 6};
1516 auto result = stl_filter([](int x) { return x % 2 == 0; }, fl);
1517
1518 EXPECT_EQ(result.size(), 3);
1519 EXPECT_EQ(result[0], 2);
1520}
1521
1523{
1524 std::forward_list<int> fl = {1, 2, 3, 4, 5};
1525 int sum = stl_foldl(0, [](int acc, int x) { return acc + x; }, fl);
1526
1527 EXPECT_EQ(sum, 15);
1528}
1529
1531{
1532 std::forward_list<int> fl = {1, 2, 1, 3, 2, 4};
1533 auto result = stl_distinct(fl);
1534
1535 EXPECT_EQ(result.size(), 4);
1536}
1537
1539{
1540 std::forward_list<int> fl = {1, 2, 2, 3, 3, 3};
1541 auto result = stl_tally(fl);
1542
1543 EXPECT_EQ(result.size(), 3);
1544}
1545
1547{
1548 std::forward_list<int> fl = {1, 2, 3, 4, 5, 6};
1549 auto result = stl_group_by([](int x) { return x % 2; }, fl);
1550
1551 EXPECT_EQ(result.size(), 2);
1552}
1553
1555{
1556 std::forward_list<int> fl = {1, 2, 3, 4, 5};
1557 auto result = stl_last(fl);
1558
1559 ASSERT_TRUE(result.has_value());
1560 EXPECT_EQ(*result, 5);
1561}
1562
1564{
1565 std::forward_list<int> fl = {1, 2, 3, 4, 5};
1566 auto result = stl_take_last(3, fl);
1567
1568 EXPECT_EQ(result.size(), 3);
1569 EXPECT_EQ(result[0], 3);
1570 EXPECT_EQ(result[2], 5);
1571}
1572
1574{
1575 std::forward_list<int> fl = {1, 2, 3, 4, 5};
1576 auto result = stl_drop(2, fl);
1577
1578 EXPECT_EQ(result.size(), 3);
1579 EXPECT_EQ(result[0], 3);
1580}
1581
1582//==============================================================================
1583// Non-Hashable Type Tests (uses linear path only)
1584//==============================================================================
1585
1586namespace {
1587
1588// A type that is NOT hashable (no std::hash specialization)
1589struct NonHashable
1590{
1591 int x, y;
1592
1593 bool operator==(const NonHashable & other) const
1594 {
1595 return x == other.x && y == other.y;
1596 }
1597};
1598
1599} // anonymous namespace
1600
1602{
1603 std::vector<NonHashable> v = {{1, 2}, {3, 4}, {1, 2}, {5, 6}};
1604 auto result = stl_distinct(v);
1605
1606 EXPECT_EQ(result.size(), 3);
1607}
1608
1610{
1611 // Even with large container, non-hashable types use linear path
1612 std::vector<NonHashable> v;
1613 v.reserve(200);
1614 for (int i = 0; i < 200; ++i)
1615 v.push_back({i % 50, i % 25});
1616
1617 auto result = stl_distinct(v);
1618
1619 EXPECT_GT(result.size(), 0);
1620 EXPECT_LE(result.size(), 200);
1621}
1622
1624{
1625 std::vector<NonHashable> v = {{1, 2}, {3, 4}, {1, 2}, {1, 2}};
1626 auto result = stl_tally(v);
1627
1628 EXPECT_EQ(result.size(), 2);
1629 // Find the count for {1,2}
1630 auto it = std::find_if(result.begin(), result.end(),
1631 [](const auto & p) { return p.first.x == 1 && p.first.y == 2; });
1632 ASSERT_NE(it, result.end());
1633 EXPECT_EQ(it->second, 3);
1634}
1635
1637{
1638 // Group by a non-hashable key type
1639 std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8};
1640
1641 // Key function returns NonHashable
1642 auto result = stl_group_by([](int x) {
1643 return NonHashable{x % 2, x % 3};
1644 }, v);
1645
1646 // With modulo (2,3), we can have up to 6 different keys
1647 EXPECT_GT(result.size(), 0);
1648 EXPECT_LE(result.size(), 6);
1649}
1650
1651//==============================================================================
1652// Stateful Callable Tests (verifies fix for std::forward in loops)
1653//==============================================================================
1654
1655namespace {
1656
1657struct StatefulCallable
1658{
1659 int call_count = 0;
1660 int threshold;
1661
1662 explicit StatefulCallable(int t) : threshold(t) {}
1663
1664 bool operator()(int x)
1665 {
1666 ++call_count;
1667 return x > threshold;
1668 }
1669};
1670
1671struct StatefulMapper
1672{
1673 int multiplier;
1674 int call_count = 0;
1675
1676 explicit StatefulMapper(int m) : multiplier(m) {}
1677
1678 int operator()(int x)
1679 {
1680 ++call_count;
1681 return x * multiplier;
1682 }
1683};
1684
1685} // anonymous namespace
1686
1688{
1689 std::vector<int> v = {1, 2, 3, 4, 5};
1690
1691 // Use a stateful callable
1692 StatefulCallable pred(3);
1693 auto result = stl_filter(pred, v);
1694
1695 EXPECT_EQ(result.size(), 2);
1696 EXPECT_EQ(result[0], 4);
1697 EXPECT_EQ(result[1], 5);
1698}
1699
1701{
1702 std::vector<int> v = {1, 2, 3};
1703
1704 StatefulMapper mapper(10);
1705 auto result = stl_map(mapper, v);
1706
1707 EXPECT_EQ(result.size(), 3);
1708 EXPECT_EQ(result[0], 10);
1709 EXPECT_EQ(result[1], 20);
1710 EXPECT_EQ(result[2], 30);
1711}
1712
1714{
1715 std::vector<int> v = {1, 2, 3, 4, 5};
1716
1717 int sum = 0;
1718 int call_count = 0;
1719
1720 // Lambda that modifies external state
1721 stl_for_each([&sum, &call_count](int x) {
1722 sum += x;
1723 ++call_count;
1724 }, v);
1725
1726 EXPECT_EQ(sum, 15);
1727 EXPECT_EQ(call_count, 5);
1728}
1729
1731{
1732 std::vector<int> v = {2, 4, 6, 8, 10};
1733
1734 int call_count = 0;
1735 bool result = stl_all([&call_count](int x) {
1736 ++call_count;
1737 return x % 2 == 0;
1738 }, v);
1739
1740 EXPECT_TRUE(result);
1741 EXPECT_EQ(call_count, 5);
1742}
1743
1745{
1746 std::vector<int> v = {1, 2, 3, 4, 5};
1747
1748 int call_count = 0;
1749 bool result = stl_exists([&call_count](int x) {
1750 ++call_count;
1751 return x == 2; // Found at second element
1752 }, v);
1753
1754 EXPECT_TRUE(result);
1755 EXPECT_EQ(call_count, 2); // Should stop after finding element
1756}
1757
1758//==============================================================================
1759// Edge Cases for Empty Containers
1760//==============================================================================
1761
1763{
1764 std::vector<int> empty;
1765 auto result = stl_last(empty);
1766 EXPECT_FALSE(result.has_value());
1767}
1768
1770{
1771 std::vector<int> empty;
1772 auto result = stl_min(empty);
1773 EXPECT_FALSE(result.has_value());
1774}
1775
1777{
1778 std::vector<int> empty;
1779 auto result = stl_max(empty);
1780 EXPECT_FALSE(result.has_value());
1781}
1782
1784{
1785 std::vector<int> empty;
1786 auto result = stl_product(empty);
1787 EXPECT_EQ(result, 0);
1788}
1789
1791{
1792 std::vector<int> empty;
1793 auto result = stl_sum(empty);
1794 EXPECT_EQ(result, 0);
1795}
1796
1798{
1799 std::vector<int> empty;
1800 auto result = stl_scan_left(42, [](int a, int b) { return a + b; }, empty);
1801
1802 EXPECT_EQ(result.size(), 1);
1803 EXPECT_EQ(result[0], 42);
1804}
1805
1807{
1808 std::vector<int> empty;
1809 auto result = stl_scan_right(42, [](int a, int b) { return a + b; }, empty);
1810
1811 EXPECT_EQ(result.size(), 1);
1812 EXPECT_EQ(result[0], 42);
1813}
1814
1816{
1817 std::vector<int> empty;
1818 auto result = stl_intersperse(0, empty);
1819 EXPECT_TRUE(result.empty());
1820}
1821
1823{
1824 std::vector<int> empty;
1825 auto result = stl_sliding_window(3, empty);
1826 EXPECT_TRUE(result.empty());
1827}
1828
1830{
1831 std::vector<int> empty;
1832 auto result = stl_chunks(3, empty);
1833 EXPECT_TRUE(result.empty());
1834}
1835
1836//==============================================================================
1837// Power Set Overflow Protection Test
1838//==============================================================================
1839
1841{
1842 // Create a container with 64 elements (would overflow 2^64)
1843 std::vector<int> large(64);
1844 std::iota(large.begin(), large.end(), 0);
1845
1846 EXPECT_THROW(stl_power_set(large), std::overflow_error);
1847}
1848
1850{
1851 std::vector<int> small = {1, 2, 3, 4, 5};
1852 auto result = stl_power_set(small);
1853
1854 EXPECT_EQ(result.size(), 32); // 2^5 = 32
1855}
1856
1857// Main
1858int main(int argc, char **argv)
1859{
1860 ::testing::InitGoogleTest(&argc, argv);
1861 return RUN_ALL_TESTS();
1862}
Functional programming utilities for C++ Standard Library containers.
int main()
long double w
Definition btreepic.C:153
size_t size_t int32_t value
Definition ca-c-api.h:116
Node belonging to a double circular linked list with header node.
Definition tpl_dnode.H:106
Doubly-linked list (defined in tpl_dynList.H).
Definition htlist.H:1155
Represents a point with rectangular coordinates in a 2D plane.
Definition point.H:221
bool operator==(const Point &point) const noexcept
Checks for exact equality between two points.
Definition point.H:259
#define TEST(name)
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
Freq_Node * pred
Predecessor node in level-order traversal.
static mpfr_t y
Definition mpfr_mul_d.c:3
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
auto stl_first(const Container &c)
Get first element.
std::vector< T > stl_scan_left(T init, Op &&op, const Container &c)
Scan left - fold with all intermediate results.
auto stl_span(Pred &&pred, const Container &c)
Split at predicate boundary (span in Haskell).
auto stl_take_last(size_t n, const Container &c)
Take last n elements.
auto stl_chunks(size_t n, const Container &c)
Split container into chunks of size n (each_slice in Ruby).
int stl_compare(const Container1 &c1, const Container2 &c2)
Compare two containers lexicographically.
auto stl_min_max(const Container &c)
Get both min and max in a single pass.
auto stl_last(const Container &c)
Get last element.
bool operator==(const DynList< T > &l1, const DynList< T > &l2)
Equality operator for DynList.
bool completed() const noexcept
Return true if all underlying iterators are finished.
Definition ah-zip.H:136
auto stl_distinct(const Container &c)
Remove all duplicates (keeps first occurrence).
auto stl_max(const Container &c)
Get maximum element.
size_t size(Node *root) noexcept
auto stl_flatten(const Container &c)
Flatten a container of containers.
auto stl_reject(Pred &&pred, const Container &c)
Filter out elements (reject in Ruby, opposite of filter).
auto stl_filter(Pred &&pred, const Container &c)
Filter elements satisfying predicate.
auto stl_arrangements(size_t k, const Container &c)
Generate all k-arrangements (k-permutations) of a container.
auto stl_drop(size_t n, const Container &c)
Drop first n elements, return the rest.
auto stl_enumerate_to_pairs(const Container &c)
Enumerate container (return pairs of index and element).
bool stl_equal(const Container1 &c1, const Container2 &c2)
Check equality of two containers.
auto stl_concat(const Container1 &c1, const Container2 &c2)
Concatenate two containers.
auto stl_combinations(size_t k, const Container &c)
Generate all k-combinations of a container.
auto stl_take_while(Pred &&pred, const Container &c)
Take elements while predicate is true.
auto stl_find_mapi(Op &&op, const Container &c)
Find and map with index (find_mapi in ML).
auto stl_nth(const size_t n, const Container &c)
Get n-th element.
auto stl_map(Op &&op, const Container &c)
Map operation - transform each element.
bool stl_mem(const T &target, const Container &c)
Check if element exists in container (mem in ML).
std::optional< size_t > stl_find_index(Pred &&pred, const Container &c)
Find index of first element satisfying predicate.
T stl_foldl(T init, Op &&op, const Container &c)
Left fold (foldl) - reduce from left to right.
auto stl_min_by(Key &&key, const Container &c)
Get minimum element by key function.
std::vector< T > stl_linspace(T start, T end, size_t n)
Generate n evenly spaced values between start and end.
bool stl_exists(Pred &&pred, const Container &c)
Check if any element satisfies predicate.
auto stl_take(size_t n, const Container &c)
Take first n elements.
auto stl_generate(size_t n, Gen &&gen)
Generate a vector using a generator function.
std::vector< T > stl_range(T start, T end, T step=1)
Generate a range of values [start, end] with given step.
auto stl_init(const Container &c)
Get all elements except the last (init in Haskell).
bool stl_traverse_permutations(Op &&op, const Container &c)
Traverse all permutations of a container.
size_t stl_count_value(const T &target, const Container &c)
Count occurrences of a value.
auto stl_sort(const Container &c)
Return sorted copy of container.
static void prefix(Node *root, DynList< Node * > &acc)
auto stl_permutations(const Container &c)
Generate all permutations of a container.
T product(const Container &container, const T &init=T{1})
Compute product of all elements.
auto stl_tally(const Container &c)
Count occurrences of each element (tally in Ruby, frequencies).
bool stl_all(Pred &&pred, const Container &c)
Check if all elements satisfy predicate.
auto stl_partition(Pred &&pred, const Container &c)
Partition elements by predicate.
auto stl_unique(const Container &c)
Remove consecutive duplicates.
auto stl_mapi(Op &&op, const Container &c)
Map with index (mapi in ML).
size_t stl_count(Pred &&pred, const Container &c)
Count elements satisfying predicate.
void stl_for_each_indexed(Op &&op, const Container &c)
Apply operation to each element with index.
auto stl_sum(const Container &c)
Sum all elements.
auto stl_sliding_window(size_t n, const Container &c)
Sliding window of size n over container (each_cons in Ruby).
auto stl_max_by(Key &&key, const Container &c)
Get maximum element by key function.
auto stl_group_by(Key &&key, const Container &c)
Group elements by key function.
auto stl_min(const Container &c)
Get minimum element.
bool stl_none(Pred &&pred, const Container &c)
Check if no element satisfies predicate.
auto stl_reverse(const Container &c)
Return reversed copy of container.
auto stl_flat_map(Op &&op, const Container &c)
Flat map - map then flatten.
std::vector< T > stl_rep(size_t n, const T &value)
Generate a vector of n repeated values.
T stl_foldr(T init, Op &&op, const Container &c)
Right fold (foldr) - reduce from right to left.
std::vector< T > stl_scan_right(T init, Op &&op, const Container &c)
Scan right - right fold with all intermediate results.
auto stl_unzip_pairs(const Container &c)
Unzip pairs into two vectors.
auto stl_drop_while(Pred &&pred, const Container &c)
Drop elements while predicate is true, return the rest.
auto stl_intersperse(const T &sep, const Container &c)
Insert element between each pair (intersperse in Haskell).
auto stl_cartesian_product(const std::vector< std::vector< T > > &containers)
Generate cartesian product of multiple containers.
auto stl_product(const Container &c)
Product of all elements.
auto stl_tail(const Container &c)
Get all elements except the first (tail in Haskell).
auto stl_filteri(Pred &&pred, const Container &c)
Filter with index (filteri in ML).
auto stl_find(Pred &&pred, const Container &c)
Find first element satisfying predicate.
void stl_for_each(Op &&op, const Container &c)
Apply operation to each element (for_each).
auto stl_split_at(size_t n, const Container &c)
Split at position n, returning (take n, drop n) in one pass.
auto stl_sort_by(Cmp &&cmp, const Container &c)
Return sorted copy using custom comparator.
auto stl_power_set(const Container &c)
Generate power set (all subsets) of a container.
auto stl_group(const Container &c)
Group consecutive equal elements.
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
Definition ahAlgo.H:127
auto stl_zip_to_pairs(const Container1 &c1, const Container2 &c2)
Zip two containers into pairs.
T sum(const Container &container, const T &init=T{})
Compute sum of all elements.
auto stl_find_last(Pred &&pred, const Container &c)
Find last element satisfying predicate.
STL namespace.
size_t operator()(const MoveTracker &m) const
size_t operator()(const Point &p) const
FooMap m(5, fst_unit_pair_hash, snd_unit_pair_hash)
gsl_rng * r
DynList< int > l