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 <ah-stl-functional.H>
46
47#include <vector>
48#include <list>
49#include <deque>
50#include <string>
51
52using namespace Aleph;
53
54//==============================================================================
55// Range Generation Tests
56//==============================================================================
57
59{
60 auto r = stl_range(1, 5);
61 EXPECT_EQ(r.size(), 5);
62 EXPECT_EQ(r[0], 1);
63 EXPECT_EQ(r[4], 5);
64}
65
67{
68 auto r = stl_range(0, 10, 2);
69 EXPECT_EQ(r.size(), 6);
70 EXPECT_EQ(r[0], 0);
71 EXPECT_EQ(r[5], 10);
72}
73
75{
76 auto r = stl_range(5);
77 EXPECT_EQ(r.size(), 5);
78 EXPECT_EQ(r[0], 0);
79 EXPECT_EQ(r[4], 4);
80}
81
83{
84 auto r = stl_linspace(0.0, 1.0, 5);
85 EXPECT_EQ(r.size(), 5);
86 EXPECT_DOUBLE_EQ(r[0], 0.0);
87 EXPECT_DOUBLE_EQ(r[4], 1.0);
88}
89
91{
92 auto r = stl_rep(5, 42);
93 EXPECT_EQ(r.size(), 5);
94 for (int x : r)
95 EXPECT_EQ(x, 42);
96}
97
99{
100 auto r = stl_generate(5, [](size_t i) { return i * i; });
101 EXPECT_EQ(r.size(), 5);
102 EXPECT_EQ(r[0], 0);
103 EXPECT_EQ(r[2], 4);
104 EXPECT_EQ(r[4], 16);
105}
106
107//==============================================================================
108// Core Functional Operations Tests
109//==============================================================================
110
112{
113 std::vector<int> v = {1, 2, 3, 4, 5};
114 int sum = 0;
115 stl_for_each([&sum](int x) { sum += x; }, v);
116 EXPECT_EQ(sum, 15);
117}
118
120{
121 std::vector<std::string> v = {"a", "b", "c"};
122 std::vector<std::string> results;
123 stl_for_each_indexed([&results](size_t i, const std::string& s) {
124 results.push_back(std::to_string(i) + ":" + s);
125 }, v);
126
127 EXPECT_EQ(results[0], "0:a");
128 EXPECT_EQ(results[2], "2:c");
129}
130
132{
133 std::vector<int> v = {1, 2, 3, 4, 5};
134 auto squares = stl_map([](int x) { return x * x; }, v);
135
136 EXPECT_EQ(squares.size(), 5);
137 EXPECT_EQ(squares[0], 1);
138 EXPECT_EQ(squares[2], 9);
139 EXPECT_EQ(squares[4], 25);
140}
141
143{
144 std::vector<int> v = {1, 2, 3};
145 auto strings = stl_map([](int x) { return std::to_string(x); }, v);
146
147 EXPECT_EQ(strings[0], "1");
148 EXPECT_EQ(strings[2], "3");
149}
150
152{
153 std::vector<std::string> v = {"a", "b", "c"};
154 auto results = stl_mapi([](size_t i, const std::string& s) {
155 return std::to_string(i) + s;
156 }, v);
157
158 EXPECT_EQ(results[0], "0a");
159 EXPECT_EQ(results[2], "2c");
160}
161
163{
164 std::vector<int> v = {1, 2, 3, 4, 5, 6};
165 auto evens = stl_filter([](int x) { return x % 2 == 0; }, v);
166
167 EXPECT_EQ(evens.size(), 3);
168 EXPECT_EQ(evens[0], 2);
169 EXPECT_EQ(evens[2], 6);
170}
171
173{
174 std::vector<int> v = {10, 20, 30, 40, 50};
175 auto evens = stl_filteri([](size_t i, int) { return i % 2 == 0; }, v);
176
177 EXPECT_EQ(evens.size(), 3);
178 EXPECT_EQ(evens[0], 10);
179 EXPECT_EQ(evens[1], 30);
180 EXPECT_EQ(evens[2], 50);
181}
182
183//==============================================================================
184// Fold Tests
185//==============================================================================
186
188{
189 std::vector<int> v = {1, 2, 3, 4, 5};
190 int sum = stl_foldl(0, [](int acc, int x) { return acc + x; }, v);
191 EXPECT_EQ(sum, 15);
192}
193
195{
196 std::vector<int> v = {1, 2, 3, 4};
197 int product = stl_foldl(1, [](int acc, int x) { return acc * x; }, v);
198 EXPECT_EQ(product, 24);
199}
200
202{
203 // Right fold: 1 - (2 - (3 - 0)) = 1 - (2 - 3) = 1 - (-1) = 2
204 std::vector<int> v = {1, 2, 3};
205 int result = stl_foldr(0, [](int x, int acc) { return x - acc; }, v);
206 EXPECT_EQ(result, 2);
207}
208
210{
211 // Right fold to construct string: "1" + ("2" + ("3" + ""))
212 std::vector<int> v = {1, 2, 3};
213 std::string result = stl_foldr(std::string(""), [](int x, std::string acc) {
214 return std::to_string(x) + acc;
215 }, v);
216 EXPECT_EQ(result, "123");
217}
218
220{
221 std::vector<int> v = {1, 2, 3, 4};
222 auto sums = stl_scan_left(0, [](int acc, int x) { return acc + x; }, v);
223
224 EXPECT_EQ(sums.size(), 5);
225 EXPECT_EQ(sums[0], 0); // init
226 EXPECT_EQ(sums[1], 1); // 0 + 1
227 EXPECT_EQ(sums[2], 3); // 1 + 2
228 EXPECT_EQ(sums[3], 6); // 3 + 3
229 EXPECT_EQ(sums[4], 10); // 6 + 4
230}
231
233{
234 std::vector<int> v = {1, 2, 3};
235 auto results = stl_scan_right(0, [](int x, int acc) { return x + acc; }, v);
236
237 // scan_right [1,2,3] with + and 0: [6, 5, 3, 0]
238 EXPECT_EQ(results.size(), 4);
239 EXPECT_EQ(results[0], 6); // 1+2+3+0
240 EXPECT_EQ(results[1], 5); // 2+3+0
241 EXPECT_EQ(results[2], 3); // 3+0
242 EXPECT_EQ(results[3], 0); // init
243}
244
245//==============================================================================
246// Predicate Tests
247//==============================================================================
248
250{
251 std::vector<int> v = {2, 4, 6, 8};
252 EXPECT_TRUE(stl_all([](int x) { return x % 2 == 0; }, v));
253}
254
256{
257 std::vector<int> v = {2, 3, 6, 8};
258 EXPECT_FALSE(stl_all([](int x) { return x % 2 == 0; }, v));
259}
260
262{
263 std::vector<int> v = {1, 2, 3, 4, 5};
264 EXPECT_TRUE(stl_exists([](int x) { return x == 3; }, v));
265}
266
268{
269 std::vector<int> v = {1, 2, 3, 4, 5};
270 EXPECT_FALSE(stl_exists([](int x) { return x == 10; }, v));
271}
272
274{
275 std::vector<int> v = {1, 3, 5, 7};
276 EXPECT_TRUE(stl_none([](int x) { return x % 2 == 0; }, v));
277}
278
279//==============================================================================
280// Finding Tests
281//==============================================================================
282
284{
285 std::vector<int> v = {1, 2, 3, 4, 5};
286 auto result = stl_find([](int x) { return x > 3; }, v);
287
288 ASSERT_TRUE(result.has_value());
289 EXPECT_EQ(*result, 4);
290}
291
293{
294 std::vector<int> v = {1, 2, 3};
295 auto result = stl_find([](int x) { return x > 10; }, v);
296
297 EXPECT_FALSE(result.has_value());
298}
299
301{
302 std::vector<int> v = {1, 2, 3, 4, 5};
303 auto result = stl_find_last([](int x) { return x % 2 == 0; }, v);
304
305 ASSERT_TRUE(result.has_value());
306 EXPECT_EQ(*result, 4);
307}
308
310{
311 std::vector<std::string> v = {"a", "b", "c", "d"};
312 auto result = stl_find_index([](const std::string& s) { return s == "c"; }, v);
313
314 ASSERT_TRUE(result.has_value());
315 EXPECT_EQ(*result, 2);
316}
317
319{
320 std::vector<int> v = {1, 2, 3, 4, 5};
321 auto result = stl_find_mapi([](size_t i, int x) -> std::optional<std::string> {
322 if (x == 3)
323 return "found at " + std::to_string(i);
324 return std::nullopt;
325 }, v);
326
327 ASSERT_TRUE(result.has_value());
328 EXPECT_EQ(*result, "found at 2");
329}
330
332{
333 std::vector<int> v = {1, 2, 3, 4, 5};
334 EXPECT_TRUE(stl_mem(3, v));
335 EXPECT_FALSE(stl_mem(10, v));
336}
337
338//==============================================================================
339// Counting Tests
340//==============================================================================
341
343{
344 std::vector<int> v = {1, 2, 3, 4, 5, 6};
345 size_t count = stl_count([](int x) { return x % 2 == 0; }, v);
346 EXPECT_EQ(count, 3);
347}
348
350{
351 std::vector<int> v = {1, 2, 2, 3, 2, 4};
352 EXPECT_EQ(stl_count_value(2, v), 3);
353}
354
355//==============================================================================
356// Take and Drop Tests
357//==============================================================================
358
360{
361 std::vector<int> v = {1, 2, 3, 4, 5};
362 auto result = stl_take(3, v);
363
364 EXPECT_EQ(result.size(), 3);
365 EXPECT_EQ(result[0], 1);
366 EXPECT_EQ(result[2], 3);
367}
368
370{
371 std::vector<int> v = {1, 2, 3, 4, 5};
372 auto result = stl_drop(2, v);
373
374 EXPECT_EQ(result.size(), 3);
375 EXPECT_EQ(result[0], 3);
376 EXPECT_EQ(result[2], 5);
377}
378
380{
381 std::vector<int> v = {1, 2, 3, 4, 5};
382 auto result = stl_take_last(3, v);
383
384 EXPECT_EQ(result.size(), 3);
385 EXPECT_EQ(result[0], 3);
386 EXPECT_EQ(result[2], 5);
387}
388
390{
391 std::vector<int> v = {1, 2, 3, 10, 4, 5};
392 auto result = stl_take_while([](int x) { return x < 10; }, v);
393
394 EXPECT_EQ(result.size(), 3);
395 EXPECT_EQ(result[2], 3);
396}
397
399{
400 std::vector<int> v = {1, 2, 3, 10, 4, 5};
401 auto result = stl_drop_while([](int x) { return x < 10; }, v);
402
403 EXPECT_EQ(result.size(), 3);
404 EXPECT_EQ(result[0], 10);
405}
406
407//==============================================================================
408// Accessing Tests
409//==============================================================================
410
412{
413 std::vector<int> v = {10, 20, 30};
414 auto result = stl_first(v);
415
416 ASSERT_TRUE(result.has_value());
417 EXPECT_EQ(*result, 10);
418}
419
421{
422 std::vector<int> v;
423 auto result = stl_first(v);
424
425 EXPECT_FALSE(result.has_value());
426}
427
429{
430 std::vector<int> v = {10, 20, 30};
431 auto result = stl_last(v);
432
433 ASSERT_TRUE(result.has_value());
434 EXPECT_EQ(*result, 30);
435}
436
438{
439 std::vector<int> v = {10, 20, 30, 40, 50};
440 auto result = stl_nth(2, v);
441
442 ASSERT_TRUE(result.has_value());
443 EXPECT_EQ(*result, 30);
444}
445
446//==============================================================================
447// Min/Max Tests
448//==============================================================================
449
451{
452 std::vector<int> v = {3, 1, 4, 1, 5, 9};
453 auto result = stl_min(v);
454
455 ASSERT_TRUE(result.has_value());
456 EXPECT_EQ(*result, 1);
457}
458
460{
461 std::vector<int> v = {3, 1, 4, 1, 5, 9};
462 auto result = stl_max(v);
463
464 ASSERT_TRUE(result.has_value());
465 EXPECT_EQ(*result, 9);
466}
467
469{
470 std::vector<int> v = {3, 1, 4, 1, 5, 9};
471 auto result = stl_min_max(v);
472
473 ASSERT_TRUE(result.has_value());
474 EXPECT_EQ(result->first, 1);
475 EXPECT_EQ(result->second, 9);
476}
477
479{
480 std::vector<std::string> v = {"hello", "a", "world"};
481 auto result = stl_min_by([](const std::string& s) { return s.length(); }, v);
482
483 ASSERT_TRUE(result.has_value());
484 EXPECT_EQ(*result, "a");
485}
486
488{
489 std::vector<std::string> v = {"hello", "a", "world"};
490 auto result = stl_max_by([](const std::string& s) { return s.length(); }, v);
491
492 ASSERT_TRUE(result.has_value());
493 EXPECT_EQ(*result, "hello");
494}
495
496//==============================================================================
497// Sum and Product Tests
498//==============================================================================
499
501{
502 std::vector<int> v = {1, 2, 3, 4, 5};
503 EXPECT_EQ(stl_sum(v), 15);
504}
505
507{
508 std::vector<int> v = {1, 2, 3, 4};
509 EXPECT_EQ(stl_product(v), 24);
510}
511
512//==============================================================================
513// Partition Tests
514//==============================================================================
515
517{
518 std::vector<int> v = {1, 2, 3, 4, 5, 6};
519 auto [evens, odds] = stl_partition([](int x) { return x % 2 == 0; }, v);
520
521 EXPECT_EQ(evens.size(), 3);
522 EXPECT_EQ(odds.size(), 3);
523}
524
525//==============================================================================
526// Zip and Enumerate Tests
527//==============================================================================
528
530{
531 std::vector<int> v1 = {1, 2, 3};
532 std::vector<std::string> v2 = {"a", "b", "c"};
533
534 auto result = stl_zip_to_pairs(v1, v2);
535
536 EXPECT_EQ(result.size(), 3);
537 EXPECT_EQ(result[0].first, 1);
538 EXPECT_EQ(result[0].second, "a");
539}
540
542{
543 std::vector<std::pair<int, std::string>> v = {{1, "a"}, {2, "b"}, {3, "c"}};
544
545 auto [nums, strs] = stl_unzip_pairs(v);
546
547 EXPECT_EQ(nums.size(), 3);
548 EXPECT_EQ(strs.size(), 3);
549 EXPECT_EQ(nums[1], 2);
550 EXPECT_EQ(strs[1], "b");
551}
552
554{
555 std::vector<std::string> v = {"a", "b", "c"};
556
557 auto result = stl_enumerate_to_pairs(v);
558
559 EXPECT_EQ(result.size(), 3);
560 EXPECT_EQ(result[0].first, 0);
561 EXPECT_EQ(result[0].second, "a");
562 EXPECT_EQ(result[2].first, 2);
563}
564
565//==============================================================================
566// Comparison Tests
567//==============================================================================
568
570{
571 std::vector<int> v1 = {1, 2, 3};
572 std::vector<int> v2 = {1, 2, 3};
573
574 EXPECT_TRUE(stl_equal(v1, v2));
575}
576
578{
579 std::vector<int> v1 = {1, 2, 3};
580 std::vector<int> v2 = {1, 2, 4};
581
582 EXPECT_FALSE(stl_equal(v1, v2));
583}
584
586{
587 std::vector<int> v1 = {1, 2, 3};
588 std::vector<int> v2 = {1, 2, 3};
589
590 EXPECT_EQ(stl_compare(v1, v2), 0);
591}
592
594{
595 std::vector<int> v1 = {1, 2, 3};
596 std::vector<int> v2 = {1, 2, 4};
597
598 EXPECT_EQ(stl_compare(v1, v2), -1);
599}
600
602{
603 std::vector<int> v1 = {1, 2, 4};
604 std::vector<int> v2 = {1, 2, 3};
605
606 EXPECT_EQ(stl_compare(v1, v2), 1);
607}
608
609//==============================================================================
610// Reverse and Sort Tests
611//==============================================================================
612
614{
615 std::vector<int> v = {1, 2, 3, 4, 5};
616 auto result = stl_reverse(v);
617
618 EXPECT_EQ(result[0], 5);
619 EXPECT_EQ(result[4], 1);
620}
621
623{
624 std::vector<int> v = {3, 1, 4, 1, 5, 9};
625 auto result = stl_sort(v);
626
627 EXPECT_EQ(result[0], 1);
628 EXPECT_EQ(result[5], 9);
629}
630
632{
633 std::vector<std::string> v = {"hello", "a", "world"};
634 auto result = stl_sort_by([](const std::string& a, const std::string& b) {
635 return a.length() < b.length();
636 }, v);
637
638 EXPECT_EQ(result[0], "a");
639 EXPECT_EQ(result[2], "world");
640}
641
642//==============================================================================
643// Uniqueness Tests
644//==============================================================================
645
647{
648 std::vector<int> v = {1, 1, 2, 2, 2, 3, 3};
649 auto result = stl_unique(v);
650
651 EXPECT_EQ(result.size(), 3);
652 EXPECT_EQ(result[0], 1);
653 EXPECT_EQ(result[1], 2);
654 EXPECT_EQ(result[2], 3);
655}
656
658{
659 std::vector<int> v = {1, 2, 1, 3, 2, 4};
660 auto result = stl_distinct(v);
661
662 EXPECT_EQ(result.size(), 4);
663}
664
665//==============================================================================
666// Concat and Flatten Tests
667//==============================================================================
668
670{
671 std::vector<int> v1 = {1, 2, 3};
672 std::vector<int> v2 = {4, 5, 6};
673
674 auto result = stl_concat(v1, v2);
675
676 EXPECT_EQ(result.size(), 6);
677 EXPECT_EQ(result[0], 1);
678 EXPECT_EQ(result[5], 6);
679}
680
682{
683 std::vector<std::vector<int>> v = {{1, 2}, {3, 4}, {5}};
684
685 auto result = stl_flatten(v);
686
687 EXPECT_EQ(result.size(), 5);
688 EXPECT_EQ(result[0], 1);
689 EXPECT_EQ(result[4], 5);
690}
691
693{
694 std::vector<int> v = {1, 2, 3};
695 auto result = stl_flat_map([](int x) {
696 return std::vector<int>{x, x * 10};
697 }, v);
698
699 EXPECT_EQ(result.size(), 6);
700 EXPECT_EQ(result[0], 1);
701 EXPECT_EQ(result[1], 10);
702 EXPECT_EQ(result[4], 3);
703 EXPECT_EQ(result[5], 30);
704}
705
706//==============================================================================
707// Grouping Tests
708//==============================================================================
709
711{
712 std::vector<int> v = {1, 1, 2, 2, 2, 3};
713
714 auto result = stl_group(v);
715
716 EXPECT_EQ(result.size(), 3);
717 EXPECT_EQ(result[0].size(), 2); // {1, 1}
718 EXPECT_EQ(result[1].size(), 3); // {2, 2, 2}
719 EXPECT_EQ(result[2].size(), 1); // {3}
720}
721
723{
724 std::vector<std::string> v = {"a", "bb", "c", "dd", "eee"};
725
726 auto result = stl_group_by([](const std::string& s) { return s.length(); }, v);
727
728 EXPECT_EQ(result.size(), 3); // lengths 1, 2, 3
729}
730
731//==============================================================================
732// Works with Different Container Types
733//==============================================================================
734
736{
737 std::list<int> l = {1, 2, 3, 4, 5};
738
739 auto squares = stl_map([](int x) { return x * x; }, l);
740 EXPECT_EQ(squares.size(), 5);
741 EXPECT_EQ(squares[4], 25);
742
743 int sum = stl_foldl(0, [](int acc, int x) { return acc + x; }, l);
744 EXPECT_EQ(sum, 15);
745
746 // foldr works with list (has rbegin/rend)
747 int result = stl_foldr(0, [](int x, int acc) { return x - acc; }, l);
748 EXPECT_EQ(result, 3); // 1-(2-(3-(4-(5-0)))) = 1-(2-(3-(4-5))) = ...
749}
750
752{
753 std::deque<int> d = {1, 2, 3, 4, 5};
754
755 auto evens = stl_filter([](int x) { return x % 2 == 0; }, d);
756 EXPECT_EQ(evens.size(), 2);
757}
758
759//==============================================================================
760// Combinatorics Tests
761//==============================================================================
762
764{
765 std::vector<int> v = {1, 2, 3};
766 auto perms = stl_permutations(v);
767
768 EXPECT_EQ(perms.size(), 6); // 3! = 6
769}
770
772{
773 std::vector<int> v = {1, 2, 3};
774 int count = 0;
775
776 bool completed = stl_traverse_permutations([&count](const auto&) {
777 ++count;
778 return count < 3; // stop after 3
779 }, v);
780
782 EXPECT_EQ(count, 3);
783}
784
786{
787 std::vector<int> v = {1, 2, 3, 4};
788 auto combos = stl_combinations(2, v);
789
790 // C(4,2) = 6
791 EXPECT_EQ(combos.size(), 6);
792
793 // Verify one combination
794 EXPECT_EQ(combos[0][0], 1);
795 EXPECT_EQ(combos[0][1], 2);
796}
797
799{
800 std::vector<int> v = {1, 2, 3, 4, 5};
801 auto combos = stl_combinations(3, v);
802
803 // C(5,3) = 10
804 EXPECT_EQ(combos.size(), 10);
805}
806
808{
809 std::vector<int> v = {1, 2, 3};
810 auto arrs = stl_arrangements(2, v);
811
812 // P(3,2) = 3!/(3-2)! = 6
813 EXPECT_EQ(arrs.size(), 6);
814}
815
817{
818 std::vector<std::vector<int>> sets = {{1, 2}, {3, 4}};
820
821 // 2 * 2 = 4
822 EXPECT_EQ(product.size(), 4);
823}
824
826{
827 std::vector<int> v = {1, 2, 3};
828 auto ps = stl_power_set(v);
829
830 // 2^3 = 8
831 EXPECT_EQ(ps.size(), 8);
832}
833
834//==============================================================================
835// Ruby/ML Operations Tests
836//==============================================================================
837
839{
840 std::vector<int> v = {1, 2, 3, 4, 5};
841 auto windows = stl_sliding_window(3, v);
842
843 EXPECT_EQ(windows.size(), 3);
844 EXPECT_EQ(windows[0], (std::vector<int>{1, 2, 3}));
845 EXPECT_EQ(windows[1], (std::vector<int>{2, 3, 4}));
846 EXPECT_EQ(windows[2], (std::vector<int>{3, 4, 5}));
847}
848
850{
851 std::vector<int> v = {1, 2, 3, 4, 5};
852 auto chunks = stl_chunks(2, v);
853
854 EXPECT_EQ(chunks.size(), 3);
855 EXPECT_EQ(chunks[0], (std::vector<int>{1, 2}));
856 EXPECT_EQ(chunks[1], (std::vector<int>{3, 4}));
857 EXPECT_EQ(chunks[2], (std::vector<int>{5}));
858}
859
861{
862 std::vector<int> v = {1, 2, 3};
863 auto result = stl_intersperse(0, v);
864
865 EXPECT_EQ(result, (std::vector<int>{1, 0, 2, 0, 3}));
866}
867
869{
870 std::vector<int> v = {1, 2, 3, 4, 5};
871 auto [first, second] = stl_split_at(2, v);
872
873 EXPECT_EQ(first, (std::vector<int>{1, 2}));
874 EXPECT_EQ(second, (std::vector<int>{3, 4, 5}));
875}
876
878{
879 std::vector<int> v = {1, 2, 3, 10, 4, 5};
880 auto [first, second] = stl_span([](int x) { return x < 10; }, v);
881
882 EXPECT_EQ(first, (std::vector<int>{1, 2, 3}));
883 EXPECT_EQ(second, (std::vector<int>{10, 4, 5}));
884}
885
887{
888 std::vector<int> v = {1, 2, 3, 4, 5};
889 auto result = stl_init(v);
890
891 EXPECT_EQ(result, (std::vector<int>{1, 2, 3, 4}));
892}
893
895{
896 std::vector<int> v = {1, 2, 3, 4, 5};
897 auto result = stl_tail(v);
898
899 EXPECT_EQ(result, (std::vector<int>{2, 3, 4, 5}));
900}
901
903{
904 std::vector<int> v = {1, 2, 2, 3, 3, 3};
905 auto result = stl_tally(v);
906
907 EXPECT_EQ(result.size(), 3);
908 EXPECT_EQ(result[0].first, 1);
909 EXPECT_EQ(result[0].second, 1);
910 EXPECT_EQ(result[1].first, 2);
911 EXPECT_EQ(result[1].second, 2);
912 EXPECT_EQ(result[2].first, 3);
913 EXPECT_EQ(result[2].second, 3);
914}
915
917{
918 std::vector<int> v = {1, 2, 3, 4, 5, 6};
919 auto result = stl_reject([](int x) { return x % 2 == 0; }, v);
920
921 EXPECT_EQ(result, (std::vector<int>{1, 3, 5}));
922}
923
924//==============================================================================
925// Performance Tests - Large Containers (Hash Path)
926//==============================================================================
927
929{
930 // Create container with 1000 elements, 100 distinct values
931 std::vector<int> large;
932 large.reserve(1000);
933 for (int i = 0; i < 1000; ++i)
934 large.push_back(i % 100);
935
936 auto result = stl_distinct(large);
937
938 EXPECT_EQ(result.size(), 100);
939 // Verify order preserved (first occurrence)
940 EXPECT_EQ(result[0], 0);
941 EXPECT_EQ(result[1], 1);
942 EXPECT_EQ(result[99], 99);
943}
944
946{
947 // 10000 elements, 500 distinct
948 std::vector<int> very_large;
949 very_large.reserve(10000);
950 for (int i = 0; i < 10000; ++i)
951 very_large.push_back(i % 500);
952
953 auto result = stl_distinct(very_large);
954
955 EXPECT_EQ(result.size(), 500);
956}
957
959{
960 std::vector<int> large;
961 large.reserve(1000);
962 for (int i = 0; i < 1000; ++i)
963 large.push_back(i % 100);
964
965 auto result = stl_tally(large);
966
967 EXPECT_EQ(result.size(), 100);
968 // Each value appears 10 times
969 for (const auto & [val, count] : result)
970 EXPECT_EQ(count, 10);
971}
972
974{
975 std::vector<int> large;
976 large.reserve(1000);
977 for (int i = 0; i < 1000; ++i)
978 large.push_back(i);
979
980 // Group by last digit
981 auto result = stl_group_by([](int x) { return x % 10; }, large);
982
983 EXPECT_EQ(result.size(), 10);
984 for (const auto & [key, group] : result)
985 EXPECT_EQ(group.size(), 100);
986}
987
988//==============================================================================
989// Edge Cases
990//==============================================================================
991
993{
994 std::vector<int> empty;
995 auto result = stl_distinct(empty);
996 EXPECT_TRUE(result.empty());
997}
998
1000{
1001 std::vector<int> single = {42};
1002 auto result = stl_distinct(single);
1003 EXPECT_EQ(result.size(), 1);
1004 EXPECT_EQ(result[0], 42);
1005}
1006
1008{
1009 std::vector<int> all_same(100, 42);
1010 auto result = stl_distinct(all_same);
1011 EXPECT_EQ(result.size(), 1);
1012 EXPECT_EQ(result[0], 42);
1013}
1014
1016{
1017 auto input = stl_range(0, 99);
1018 auto result = stl_distinct(input);
1019 EXPECT_EQ(result.size(), 100);
1020}
1021
1023{
1024 std::vector<int> empty;
1025 auto result = stl_tally(empty);
1026 EXPECT_TRUE(result.empty());
1027}
1028
1030{
1031 std::vector<int> single = {42};
1032 auto result = stl_tally(single);
1033 EXPECT_EQ(result.size(), 1);
1034 EXPECT_EQ(result[0].first, 42);
1035 EXPECT_EQ(result[0].second, 1);
1036}
1037
1039{
1040 std::vector<int> empty;
1041 auto result = stl_group_by([](int x) { return x; }, empty);
1042 EXPECT_TRUE(result.empty());
1043}
1044
1046{
1047 std::vector<int> single = {42};
1048 auto result = stl_group_by([](int x) { return x % 10; }, single);
1049 EXPECT_EQ(result.size(), 1);
1050 EXPECT_EQ(result[0].first, 2);
1051 EXPECT_EQ(result[0].second.size(), 1);
1052}
1053
1055{
1056 std::vector<int> v = {10, 20, 30, 40, 50};
1057 auto result = stl_group_by([](int x) { return x % 10; }, v);
1058 EXPECT_EQ(result.size(), 1);
1059 EXPECT_EQ(result[0].first, 0);
1060 EXPECT_EQ(result[0].second.size(), 5);
1061}
1062
1063//==============================================================================
1064// Small Container Tests (Linear Path - threshold <= 64)
1065//==============================================================================
1066
1068{
1069 // Exactly at threshold
1070 std::vector<int> at_threshold;
1071 for (int i = 0; i < 64; ++i)
1072 at_threshold.push_back(i % 32);
1073
1074 auto result = stl_distinct(at_threshold);
1075 EXPECT_EQ(result.size(), 32);
1076}
1077
1079{
1080 std::vector<int> small = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
1081 auto result = stl_tally(small);
1082
1083 EXPECT_EQ(result.size(), 4);
1084 EXPECT_EQ(result[0].second, 1); // 1 appears once
1085 EXPECT_EQ(result[1].second, 2); // 2 appears twice
1086 EXPECT_EQ(result[2].second, 3); // 3 appears three times
1087 EXPECT_EQ(result[3].second, 4); // 4 appears four times
1088}
1089
1090//==============================================================================
1091// Custom Types Tests
1092//==============================================================================
1093
1094namespace {
1095
1096struct Point
1097{
1098 int x, y;
1099
1100 bool operator==(const Point & other) const
1101 {
1102 return x == other.x && y == other.y;
1103 }
1104};
1105
1106struct PointHash
1107{
1108 size_t operator()(const Point & p) const
1109 {
1110 return std::hash<int>{}(p.x) ^ (std::hash<int>{}(p.y) << 1);
1111 }
1112};
1113
1114// Make Point hashable for std::unordered_set/map
1115} // anonymous namespace
1116
1117namespace std {
1118template<>
1119struct hash<Point>
1120{
1121 size_t operator()(const Point & p) const
1122 {
1123 return hash<int>{}(p.x) ^ (hash<int>{}(p.y) << 1);
1124 }
1125};
1126} // namespace std
1127
1129{
1130 std::vector<Point> points = {{1, 2}, {3, 4}, {1, 2}, {5, 6}, {3, 4}};
1131 auto result = stl_distinct(points);
1132
1133 EXPECT_EQ(result.size(), 3);
1134 EXPECT_EQ(result[0].x, 1);
1135 EXPECT_EQ(result[0].y, 2);
1136}
1137
1139{
1140 std::vector<Point> points;
1141 points.reserve(200);
1142 for (int i = 0; i < 200; ++i)
1143 points.push_back({i % 50, i % 25});
1144
1145 auto result = stl_distinct(points);
1146 // 50 * 25 = 1250 possible, but we only have 200 elements with some repeats
1147 EXPECT_LE(result.size(), 200);
1148 EXPECT_GT(result.size(), 0);
1149}
1150
1152{
1153 std::vector<Point> points = {{1, 2}, {3, 4}, {1, 2}, {5, 6}, {1, 2}};
1154 auto result = stl_tally(points);
1155
1156 EXPECT_EQ(result.size(), 3);
1157 // Find the count for {1,2}
1158 auto it = std::find_if(result.begin(), result.end(),
1159 [](const auto & p) { return p.first.x == 1 && p.first.y == 2; });
1160 ASSERT_NE(it, result.end());
1161 EXPECT_EQ(it->second, 3);
1162}
1163
1165{
1166 std::vector<Point> points = {
1167 {1, 1}, {-1, 1}, {-1, -1}, {1, -1},
1168 {2, 3}, {-2, 3}, {-2, -3}, {2, -3}
1169 };
1170
1171 auto quadrant = [](const Point & p) {
1172 if (p.x >= 0 && p.y >= 0) return 1;
1173 if (p.x < 0 && p.y >= 0) return 2;
1174 if (p.x < 0 && p.y < 0) return 3;
1175 return 4;
1176 };
1177
1178 auto result = stl_group_by(quadrant, points);
1179
1180 EXPECT_EQ(result.size(), 4);
1181 for (const auto & [quad, pts] : result)
1182 EXPECT_EQ(pts.size(), 2);
1183}
1184
1185//==============================================================================
1186// Move Semantics and Forwarding Tests
1187//==============================================================================
1188
1189namespace {
1190
1191struct MoveTracker
1192{
1193 int value;
1194 static int move_count;
1195 static int copy_count;
1196
1197 MoveTracker(int v = 0) : value(v) {}
1198
1199 MoveTracker(const MoveTracker & other) : value(other.value)
1200 {
1201 ++copy_count;
1202 }
1203
1204 MoveTracker(MoveTracker && other) noexcept : value(other.value)
1205 {
1206 other.value = -1;
1207 ++move_count;
1208 }
1209
1210 MoveTracker & operator=(const MoveTracker & other)
1211 {
1212 value = other.value;
1213 ++copy_count;
1214 return *this;
1215 }
1216
1217 MoveTracker & operator=(MoveTracker && other) noexcept
1218 {
1219 value = other.value;
1220 other.value = -1;
1221 ++move_count;
1222 return *this;
1223 }
1224
1225 bool operator==(const MoveTracker & other) const
1226 {
1227 return value == other.value;
1228 }
1229
1230 static void reset()
1231 {
1232 move_count = 0;
1233 copy_count = 0;
1234 }
1235};
1236
1237int MoveTracker::move_count = 0;
1238int MoveTracker::copy_count = 0;
1239
1240} // anonymous namespace
1241
1242namespace std {
1243template<>
1244struct hash<MoveTracker>
1245{
1246 size_t operator()(const MoveTracker & m) const
1247 {
1248 return hash<int>{}(m.value);
1249 }
1250};
1251} // namespace std
1252
1254{
1255 std::vector<int> v = {1, 2, 3};
1256 std::string prefix = "num_";
1257
1258 auto result = stl_map([&prefix](int x) {
1259 return prefix + std::to_string(x);
1260 }, v);
1261
1262 EXPECT_EQ(result[0], "num_1");
1263 EXPECT_EQ(result[1], "num_2");
1264 EXPECT_EQ(result[2], "num_3");
1265}
1266
1268{
1269 std::vector<int> v = {1, 2, 3, 4, 5};
1270 int threshold = 3;
1271
1272 // Mutable lambda that modifies captured state
1273 int call_count = 0;
1274 auto result = stl_filter([&call_count, threshold](int x) mutable {
1275 ++call_count;
1276 return x > threshold;
1277 }, v);
1278
1279 EXPECT_EQ(result.size(), 2);
1280 EXPECT_EQ(call_count, 5);
1281}
1282
1284{
1285 std::vector<std::string> words = {"hello", " ", "world"};
1286
1287 auto result = stl_foldl(std::string{}, [](std::string acc, const std::string & w) {
1288 return acc + w;
1289 }, words);
1290
1291 EXPECT_EQ(result, "hello world");
1292}
1293
1294//==============================================================================
1295// Different Container Types
1296//==============================================================================
1297
1299{
1300 std::list<int> l = {1, 2, 1, 3, 2, 4};
1301 auto result = stl_distinct(l);
1302 EXPECT_EQ(result.size(), 4);
1303}
1304
1306{
1307 std::deque<int> d = {1, 2, 1, 3, 2, 4};
1308 auto result = stl_distinct(d);
1309 EXPECT_EQ(result.size(), 4);
1310}
1311
1313{
1314 std::list<int> l = {1, 2, 2, 3, 3, 3};
1315 auto result = stl_tally(l);
1316 EXPECT_EQ(result.size(), 3);
1317}
1318
1320{
1321 std::list<std::string> l = {"a", "bb", "ccc", "dd", "e"};
1322 auto result = stl_group_by([](const std::string & s) { return s.length(); }, l);
1323 EXPECT_EQ(result.size(), 3);
1324}
1325
1326//==============================================================================
1327// Order Preservation Tests
1328//==============================================================================
1329
1331{
1332 std::vector<int> v = {5, 3, 5, 1, 3, 7, 1, 5};
1333 auto result = stl_distinct(v);
1334
1335 ASSERT_EQ(result.size(), 4);
1336 EXPECT_EQ(result[0], 5); // First occurrence
1337 EXPECT_EQ(result[1], 3);
1338 EXPECT_EQ(result[2], 1);
1339 EXPECT_EQ(result[3], 7);
1340}
1341
1343{
1344 // Test with hash path
1345 std::vector<int> v;
1346 v.reserve(200);
1347 for (int i = 199; i >= 0; --i)
1348 v.push_back(i % 100);
1349
1350 auto result = stl_distinct(v);
1351
1352 ASSERT_EQ(result.size(), 100);
1353 // First occurrence of 99 is at index 0 (199 % 100 = 99)
1354 EXPECT_EQ(result[0], 99);
1355 // First occurrence of 98 is at index 1 (198 % 100 = 98)
1356 EXPECT_EQ(result[1], 98);
1357}
1358
1360{
1361 std::vector<int> v = {5, 3, 5, 1, 3, 7, 1, 5};
1362 auto result = stl_tally(v);
1363
1364 ASSERT_EQ(result.size(), 4);
1365 EXPECT_EQ(result[0].first, 5);
1366 EXPECT_EQ(result[0].second, 3);
1367 EXPECT_EQ(result[1].first, 3);
1368 EXPECT_EQ(result[1].second, 2);
1369 EXPECT_EQ(result[2].first, 1);
1370 EXPECT_EQ(result[2].second, 2);
1371 EXPECT_EQ(result[3].first, 7);
1372 EXPECT_EQ(result[3].second, 1);
1373}
1374
1376{
1377 std::vector<int> v = {15, 23, 31, 42, 54};
1378 auto result = stl_group_by([](int x) { return x % 10; }, v);
1379
1380 ASSERT_EQ(result.size(), 5);
1381 // First key seen is 5 (from 15)
1382 EXPECT_EQ(result[0].first, 5);
1383 // Second key seen is 3 (from 23)
1384 EXPECT_EQ(result[1].first, 3);
1385}
1386
1387//==============================================================================
1388// String Tests
1389//==============================================================================
1390
1392{
1393 std::vector<std::string> v = {"apple", "banana", "apple", "cherry", "banana"};
1394 auto result = stl_distinct(v);
1395
1396 ASSERT_EQ(result.size(), 3);
1397 EXPECT_EQ(result[0], "apple");
1398 EXPECT_EQ(result[1], "banana");
1399 EXPECT_EQ(result[2], "cherry");
1400}
1401
1403{
1404 std::vector<std::string> v;
1405 v.reserve(200);
1406 for (int i = 0; i < 200; ++i)
1407 v.push_back("str_" + std::to_string(i % 50));
1408
1409 auto result = stl_distinct(v);
1410 EXPECT_EQ(result.size(), 50);
1411}
1412
1414{
1415 std::vector<std::string> v = {"a", "bb", "ccc", "dd", "eee", "f"};
1416 auto result = stl_group_by([](const std::string & s) { return s.length(); }, v);
1417
1418 EXPECT_EQ(result.size(), 3);
1419}
1420
1422{
1423 std::vector<std::string> v = {"apple", "apricot", "banana", "blueberry", "cherry"};
1424 auto result = stl_group_by([](const std::string & s) { return s[0]; }, v);
1425
1426 EXPECT_EQ(result.size(), 3); // a, b, c
1427}
1428
1429//==============================================================================
1430// Boundary Tests (around threshold = 64)
1431//==============================================================================
1432
1434{
1435 std::vector<int> v;
1436 for (int i = 0; i < 63; ++i)
1437 v.push_back(i % 30);
1438
1439 auto result = stl_distinct(v);
1440 EXPECT_EQ(result.size(), 30);
1441}
1442
1444{
1445 std::vector<int> v;
1446 for (int i = 0; i < 64; ++i)
1447 v.push_back(i % 30);
1448
1449 auto result = stl_distinct(v);
1450 EXPECT_EQ(result.size(), 30);
1451}
1452
1454{
1455 std::vector<int> v;
1456 for (int i = 0; i < 65; ++i)
1457 v.push_back(i % 30);
1458
1459 auto result = stl_distinct(v);
1460 EXPECT_EQ(result.size(), 30);
1461}
1462
1463//==============================================================================
1464// Composition Tests
1465//==============================================================================
1466
1468{
1469 std::vector<int> v = {1, 2, 1, 3, 2, 4};
1470 auto distinct = stl_distinct(v);
1471 auto squared = stl_map([](int x) { return x * x; }, distinct);
1472
1473 EXPECT_EQ(squared, (std::vector<int>{1, 4, 9, 16}));
1474}
1475
1477{
1478 std::vector<int> v = {1, 2, 3, 4, 5, 6, 1, 2, 3};
1479 auto evens = stl_filter([](int x) { return x % 2 == 0; }, v);
1481
1482 EXPECT_EQ(unique_evens, (std::vector<int>{2, 4, 6}));
1483}
1484
1486{
1487 std::vector<int> v = {1, 2, 3, 4, 5, 6};
1488 auto groups = stl_group_by([](int x) { return x % 2; }, v);
1489 auto sums = stl_map([](const auto & p) {
1490 return std::make_pair(p.first, stl_foldl(0, std::plus<int>{}, p.second));
1491 }, groups);
1492
1493 EXPECT_EQ(sums.size(), 2);
1494}
1495
1496//==============================================================================
1497// forward_list Compatibility Tests (containers without size())
1498//==============================================================================
1499
1500#include <forward_list>
1501
1503{
1504 std::forward_list<int> fl = {1, 2, 3, 4, 5};
1505 auto result = stl_map([](int x) { return x * 2; }, fl);
1506
1507 EXPECT_EQ(result.size(), 5);
1508 EXPECT_EQ(result[0], 2);
1509 EXPECT_EQ(result[4], 10);
1510}
1511
1513{
1514 std::forward_list<int> fl = {1, 2, 3, 4, 5, 6};
1515 auto result = stl_filter([](int x) { return x % 2 == 0; }, fl);
1516
1517 EXPECT_EQ(result.size(), 3);
1518 EXPECT_EQ(result[0], 2);
1519}
1520
1522{
1523 std::forward_list<int> fl = {1, 2, 3, 4, 5};
1524 int sum = stl_foldl(0, [](int acc, int x) { return acc + x; }, fl);
1525
1526 EXPECT_EQ(sum, 15);
1527}
1528
1530{
1531 std::forward_list<int> fl = {1, 2, 1, 3, 2, 4};
1532 auto result = stl_distinct(fl);
1533
1534 EXPECT_EQ(result.size(), 4);
1535}
1536
1538{
1539 std::forward_list<int> fl = {1, 2, 2, 3, 3, 3};
1540 auto result = stl_tally(fl);
1541
1542 EXPECT_EQ(result.size(), 3);
1543}
1544
1546{
1547 std::forward_list<int> fl = {1, 2, 3, 4, 5, 6};
1548 auto result = stl_group_by([](int x) { return x % 2; }, fl);
1549
1550 EXPECT_EQ(result.size(), 2);
1551}
1552
1554{
1555 std::forward_list<int> fl = {1, 2, 3, 4, 5};
1556 auto result = stl_last(fl);
1557
1558 ASSERT_TRUE(result.has_value());
1559 EXPECT_EQ(*result, 5);
1560}
1561
1563{
1564 std::forward_list<int> fl = {1, 2, 3, 4, 5};
1565 auto result = stl_take_last(3, fl);
1566
1567 EXPECT_EQ(result.size(), 3);
1568 EXPECT_EQ(result[0], 3);
1569 EXPECT_EQ(result[2], 5);
1570}
1571
1573{
1574 std::forward_list<int> fl = {1, 2, 3, 4, 5};
1575 auto result = stl_drop(2, fl);
1576
1577 EXPECT_EQ(result.size(), 3);
1578 EXPECT_EQ(result[0], 3);
1579}
1580
1581//==============================================================================
1582// Non-Hashable Type Tests (uses linear path only)
1583//==============================================================================
1584
1585namespace {
1586
1587// A type that is NOT hashable (no std::hash specialization)
1588struct NonHashable
1589{
1590 int x, y;
1591
1592 bool operator==(const NonHashable & other) const
1593 {
1594 return x == other.x && y == other.y;
1595 }
1596};
1597
1598} // anonymous namespace
1599
1601{
1602 std::vector<NonHashable> v = {{1, 2}, {3, 4}, {1, 2}, {5, 6}};
1603 auto result = stl_distinct(v);
1604
1605 EXPECT_EQ(result.size(), 3);
1606}
1607
1609{
1610 // Even with large container, non-hashable types use linear path
1611 std::vector<NonHashable> v;
1612 v.reserve(200);
1613 for (int i = 0; i < 200; ++i)
1614 v.push_back({i % 50, i % 25});
1615
1616 auto result = stl_distinct(v);
1617
1618 EXPECT_GT(result.size(), 0);
1619 EXPECT_LE(result.size(), 200);
1620}
1621
1623{
1624 std::vector<NonHashable> v = {{1, 2}, {3, 4}, {1, 2}, {1, 2}};
1625 auto result = stl_tally(v);
1626
1627 EXPECT_EQ(result.size(), 2);
1628 // Find the count for {1,2}
1629 auto it = std::find_if(result.begin(), result.end(),
1630 [](const auto & p) { return p.first.x == 1 && p.first.y == 2; });
1631 ASSERT_NE(it, result.end());
1632 EXPECT_EQ(it->second, 3);
1633}
1634
1636{
1637 // Group by a non-hashable key type
1638 std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8};
1639
1640 // Key function returns NonHashable
1641 auto result = stl_group_by([](int x) {
1642 return NonHashable{x % 2, x % 3};
1643 }, v);
1644
1645 // With modulo (2,3), we can have up to 6 different keys
1646 EXPECT_GT(result.size(), 0);
1647 EXPECT_LE(result.size(), 6);
1648}
1649
1650//==============================================================================
1651// Stateful Callable Tests (verifies fix for std::forward in loops)
1652//==============================================================================
1653
1654namespace {
1655
1656struct StatefulCallable
1657{
1658 int call_count = 0;
1659 int threshold;
1660
1661 explicit StatefulCallable(int t) : threshold(t) {}
1662
1663 bool operator()(int x)
1664 {
1665 ++call_count;
1666 return x > threshold;
1667 }
1668};
1669
1670struct StatefulMapper
1671{
1672 int multiplier;
1673 int call_count = 0;
1674
1675 explicit StatefulMapper(int m) : multiplier(m) {}
1676
1677 int operator()(int x)
1678 {
1679 ++call_count;
1680 return x * multiplier;
1681 }
1682};
1683
1684} // anonymous namespace
1685
1687{
1688 std::vector<int> v = {1, 2, 3, 4, 5};
1689
1690 // Use a stateful callable
1691 StatefulCallable pred(3);
1692 auto result = stl_filter(pred, v);
1693
1694 EXPECT_EQ(result.size(), 2);
1695 EXPECT_EQ(result[0], 4);
1696 EXPECT_EQ(result[1], 5);
1697}
1698
1700{
1701 std::vector<int> v = {1, 2, 3};
1702
1703 StatefulMapper mapper(10);
1704 auto result = stl_map(mapper, v);
1705
1706 EXPECT_EQ(result.size(), 3);
1707 EXPECT_EQ(result[0], 10);
1708 EXPECT_EQ(result[1], 20);
1709 EXPECT_EQ(result[2], 30);
1710}
1711
1713{
1714 std::vector<int> v = {1, 2, 3, 4, 5};
1715
1716 int sum = 0;
1717 int call_count = 0;
1718
1719 // Lambda that modifies external state
1720 stl_for_each([&sum, &call_count](int x) {
1721 sum += x;
1722 ++call_count;
1723 }, v);
1724
1725 EXPECT_EQ(sum, 15);
1726 EXPECT_EQ(call_count, 5);
1727}
1728
1730{
1731 std::vector<int> v = {2, 4, 6, 8, 10};
1732
1733 int call_count = 0;
1734 bool result = stl_all([&call_count](int x) {
1735 ++call_count;
1736 return x % 2 == 0;
1737 }, v);
1738
1739 EXPECT_TRUE(result);
1740 EXPECT_EQ(call_count, 5);
1741}
1742
1744{
1745 std::vector<int> v = {1, 2, 3, 4, 5};
1746
1747 int call_count = 0;
1748 bool result = stl_exists([&call_count](int x) {
1749 ++call_count;
1750 return x == 2; // Found at second element
1751 }, v);
1752
1753 EXPECT_TRUE(result);
1754 EXPECT_EQ(call_count, 2); // Should stop after finding element
1755}
1756
1757//==============================================================================
1758// Edge Cases for Empty Containers
1759//==============================================================================
1760
1762{
1763 std::vector<int> empty;
1764 auto result = stl_last(empty);
1765 EXPECT_FALSE(result.has_value());
1766}
1767
1769{
1770 std::vector<int> empty;
1771 auto result = stl_min(empty);
1772 EXPECT_FALSE(result.has_value());
1773}
1774
1776{
1777 std::vector<int> empty;
1778 auto result = stl_max(empty);
1779 EXPECT_FALSE(result.has_value());
1780}
1781
1783{
1784 std::vector<int> empty;
1785 auto result = stl_product(empty);
1786 EXPECT_EQ(result, 0);
1787}
1788
1790{
1791 std::vector<int> empty;
1792 auto result = stl_sum(empty);
1793 EXPECT_EQ(result, 0);
1794}
1795
1797{
1798 std::vector<int> empty;
1799 auto result = stl_scan_left(42, [](int a, int b) { return a + b; }, empty);
1800
1801 EXPECT_EQ(result.size(), 1);
1802 EXPECT_EQ(result[0], 42);
1803}
1804
1806{
1807 std::vector<int> empty;
1808 auto result = stl_scan_right(42, [](int a, int b) { return a + b; }, empty);
1809
1810 EXPECT_EQ(result.size(), 1);
1811 EXPECT_EQ(result[0], 42);
1812}
1813
1815{
1816 std::vector<int> empty;
1817 auto result = stl_intersperse(0, empty);
1818 EXPECT_TRUE(result.empty());
1819}
1820
1822{
1823 std::vector<int> empty;
1824 auto result = stl_sliding_window(3, empty);
1825 EXPECT_TRUE(result.empty());
1826}
1827
1829{
1830 std::vector<int> empty;
1831 auto result = stl_chunks(3, empty);
1832 EXPECT_TRUE(result.empty());
1833}
1834
1835//==============================================================================
1836// Power Set Overflow Protection Test
1837//==============================================================================
1838
1840{
1841 // Create a container with 64 elements (would overflow 2^64)
1842 std::vector<int> large(64);
1843 std::iota(large.begin(), large.end(), 0);
1844
1845 EXPECT_THROW(stl_power_set(large), std::overflow_error);
1846}
1847
1849{
1850 std::vector<int> small = {1, 2, 3, 4, 5};
1851 auto result = stl_power_set(small);
1852
1853 EXPECT_EQ(result.size(), 32); // 2^5 = 32
1854}
1855
1856// Main
1857int main(int argc, char **argv)
1858{
1859 ::testing::InitGoogleTest(&argc, argv);
1860 return RUN_ALL_TESTS();
1861}
Functional programming utilities for C++ Standard Library containers.
int main()
long double w
Definition btreepic.C:153
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
Rectangular point in the plane.
Definition point.H:156
Geom_Number x
Definition point.H:161
Geom_Number y
Definition point.H:162
bool operator==(const Point &point) const
Definition point.H:185
iterator end() noexcept
Return an STL-compatible end iterator.
iterator begin() noexcept
Return an STL-compatible iterator to the first element.
#define TEST(name)
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:140
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.
DynList< T > maps(const C &c, Op op)
Classic map operation.
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
DynList< int > l