Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
ahSort_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
38#include <gtest/gtest.h>
39
40#include <vector>
41#include <deque>
42#include <algorithm>
43#include <functional>
44#include <random>
45#include <string>
46#include <type_traits>
47
48#include <ahSort.H>
49#include <tpl_dynArray.H>
50#include <tpl_dynList.H>
51#include <tpl_dynDlist.H>
52
53using namespace Aleph;
54using namespace std;
55
56namespace {
57
58template <class Compare>
59vector<size_t> stable_index_reference(const vector<int> &values,
60 const Compare &cmp)
61{
62 vector<size_t> ref(values.size());
63 for (size_t i = 0; i < ref.size(); ++i)
64 ref[i] = i;
65
66 std::stable_sort(ref.begin(), ref.end(), [&values, &cmp](size_t i, size_t j)
67 {
68 return cmp(values[i], values[j]);
69 });
70
71 return ref;
72}
73
74template <class Index>
75void expect_index_matches_reference(const Index &idx,
76 const vector<size_t> &ref)
77{
78 ASSERT_EQ(idx.size(), ref.size());
79 for (size_t i = 0; i < ref.size(); ++i)
80 EXPECT_EQ(idx(i), ref[i]) << "position " << i;
81}
82
83template <class Compare>
85{
86 constexpr size_t max_n = 7;
87 constexpr size_t alphabet = 3;
88
89 for (size_t n = 0; n <= max_n; ++n)
90 {
91 size_t cases = 1;
92 for (size_t i = 0; i < n; ++i)
93 cases *= alphabet;
94
95 for (size_t code = 0; code < cases; ++code)
96 {
97 vector<int> values(n);
98 size_t x = code;
99 for (size_t i = 0; i < n; ++i)
100 {
101 values[i] = static_cast<int>(x % alphabet);
102 x /= alphabet;
103 }
104
105 const auto idx = stable_argsort(values, cmp);
106 const auto ref = stable_index_reference(values, cmp);
108 }
109 }
110}
111
112} // namespace
113
114// ============================================================================
115// Test Fixtures
116// ============================================================================
117
118class DynListSortTest : public ::testing::Test
119{
120protected:
122
123 void SetUp() override
124 {
125 list = DynList<int>{5, 2, 8, 1, 9, 3, 7, 4, 6, 0};
126 }
127
128 DynList<int> build_list(std::initializer_list<int> items)
129 {
131 for (int x : items)
132 l.append(x);
133 return l;
134 }
135};
136
137class DynDlistSortTest : public ::testing::Test
138{
139protected:
141
142 void SetUp() override
143 {
144 for (int x : {5, 2, 8, 1, 9, 3, 7, 4, 6, 0})
145 list.append(x);
146 }
147
148 DynDlist<int> build_list(std::initializer_list<int> items)
149 {
151 for (int x : items)
152 l.append(x);
153 return l;
154 }
155};
156
157class DynArraySortTest : public ::testing::Test
158{
159protected:
161
162 void SetUp() override
163 {
164 arr.reserve(10);
165 int values[] = {5, 2, 8, 1, 9, 3, 7, 4, 6, 0};
166 for (size_t i = 0; i < 10; ++i)
167 arr(i) = values[i];
168 }
169
170 DynArray<int> build_array(std::initializer_list<int> items)
171 {
173 a.reserve(items.size());
174 size_t i = 0;
175 for (int x : items)
176 a(i++) = x;
177 return a;
178 }
179};
180
181class ArraySortTest : public ::testing::Test
182{
183protected:
185
186 void SetUp() override
187 {
188 int values[] = {5, 2, 8, 1, 9, 3, 7, 4, 6, 0};
189 for (int v : values)
190 arr.append(v);
191 }
192
193 Array<int> build_array(std::initializer_list<int> items)
194 {
195 Array<int> a;
196 for (int x : items)
197 a.append(x);
198 return a;
199 }
200};
201
202// ============================================================================
203// DynList sort() tests
204// ============================================================================
205
207{
208 auto sorted = sort(list);
209
210 // Original unchanged
211 EXPECT_EQ(list.get_first(), 5);
212
213 // Result is sorted
214 int prev = -1;
215 sorted.for_each([&prev](int x) {
216 EXPECT_GT(x, prev);
217 prev = x;
218 });
219}
220
222{
223 auto sorted = sort(list, std::greater<int>());
224
225 // Descending order
226 int prev = 100;
227 sorted.for_each([&prev](int x) {
228 EXPECT_LT(x, prev);
229 prev = x;
230 });
231}
232
234{
235 DynList<int> temp = build_list({3, 1, 2});
236 auto sorted = sort(std::move(temp));
237
238 // Original moved from
239 EXPECT_TRUE(temp.is_empty());
240
241 // Result is sorted
242 EXPECT_EQ(sorted.get_first(), 1);
243 EXPECT_EQ(sorted.get_last(), 3);
244}
245
247{
248 in_place_sort(list);
249
250 // Original is now sorted
251 int prev = -1;
252 list.for_each([&prev](int x) {
253 EXPECT_GT(x, prev);
254 prev = x;
255 });
256}
257
259{
260 auto & ref = in_place_sort(list);
261 EXPECT_EQ(&ref, &list);
262}
263
265{
266 DynList<int> empty;
267 auto sorted = sort(empty);
268 EXPECT_TRUE(sorted.is_empty());
269}
270
272{
274 single.append(42);
275 auto sorted = sort(single);
276 EXPECT_EQ(sorted.size(), 1u);
277 EXPECT_EQ(sorted.get_first(), 42);
278}
279
281{
282 DynList<int> already = build_list({1, 2, 3, 4, 5});
283 auto sorted = sort(already);
285}
286
288{
289 DynList<int> reversed = build_list({5, 4, 3, 2, 1});
290 auto sorted = sort(reversed);
292 EXPECT_EQ(sorted.get_first(), 1);
293}
294
296{
297 DynList<int> dups = build_list({3, 1, 3, 1, 2, 2});
298 auto sorted = sort(dups);
300}
301
302// ============================================================================
303// DynDlist sort() tests
304// ============================================================================
305
307{
308 auto sorted = sort(list);
310 EXPECT_EQ(list.get_first(), 5); // Original unchanged
311}
312
314{
315 auto sorted = sort(list, std::greater<int>());
316
317 int prev = 100;
318 sorted.for_each([&prev](int x) {
319 EXPECT_LT(x, prev);
320 prev = x;
321 });
322}
323
325{
326 DynDlist<int> temp = build_list({3, 1, 2});
327 auto sorted = sort(std::move(temp));
328 EXPECT_TRUE(temp.is_empty());
330}
331
337
338// ============================================================================
339// DynArray sort() tests
340// ============================================================================
341
343{
344 auto sorted = sort(arr);
345
346 // Original unchanged
347 EXPECT_EQ(arr(0), 5);
348
349 // Result is sorted
350 for (size_t i = 1; i < sorted.size(); ++i)
351 EXPECT_LE(sorted(i-1), sorted(i));
352}
353
355{
356 auto sorted = sort(arr, std::greater<int>());
357
358 for (size_t i = 1; i < sorted.size(); ++i)
359 EXPECT_GE(sorted(i-1), sorted(i));
360}
361
363{
364 DynArray<int> temp = build_array({3, 1, 2});
365 auto sorted = sort(std::move(temp));
366
367 // Original should be empty after move
368 EXPECT_EQ(temp.size(), 0u);
369
370 // Result is sorted
371 EXPECT_EQ(sorted(0), 1);
372 EXPECT_EQ(sorted(1), 2);
373 EXPECT_EQ(sorted(2), 3);
374}
375
377{
378 in_place_sort(arr);
379
380 for (size_t i = 1; i < arr.size(); ++i)
381 EXPECT_LE(arr(i-1), arr(i));
382}
383
385{
386 auto & ref = in_place_sort(arr);
387 EXPECT_EQ(&ref, &arr);
388}
389
391{
392 DynArray<int> empty;
393 auto sorted = sort(empty);
394 EXPECT_EQ(sorted.size(), 0u);
395}
396
398{
400 single.reserve(1);
401 single.touch(0) = 42;
402 auto sorted = sort(single);
403 EXPECT_EQ(sorted.size(), 1u);
404 EXPECT_EQ(sorted(0), 42);
405}
406
407// ============================================================================
408// Array sort() tests
409// ============================================================================
410
412{
413 auto sorted = sort(arr);
414 EXPECT_EQ(arr(0), 5); // Original unchanged
415
416 for (size_t i = 1; i < sorted.size(); ++i)
417 EXPECT_LE(sorted(i-1), sorted(i));
418}
419
421{
422 Array<int> temp = build_array({3, 1, 2});
423 auto sorted = sort(std::move(temp));
424 EXPECT_EQ(sorted(0), 1);
425 EXPECT_EQ(sorted(2), 3);
426}
427
429{
430 in_place_sort(arr);
431 for (size_t i = 1; i < arr.size(); ++i)
432 EXPECT_LE(arr(i-1), arr(i));
433}
434
435// ============================================================================
436// stdsort() tests
437// ============================================================================
438
440{
441 std::vector<int> v = {5, 2, 8, 1, 9};
442 auto sorted = stdsort(v);
443
444 EXPECT_EQ(v[0], 5); // Original unchanged
445 EXPECT_EQ(sorted, (std::vector<int>{1, 2, 5, 8, 9}));
446}
447
449{
450 std::vector<int> v = {5, 2, 8, 1, 9};
451 auto sorted = stdsort(v, std::greater<int>());
452 EXPECT_EQ(sorted, (std::vector<int>{9, 8, 5, 2, 1}));
453}
454
456{
457 std::deque<int> d = {5, 2, 8, 1, 9};
458 auto sorted = stdsort(d);
459 EXPECT_EQ(sorted, (std::deque<int>{1, 2, 5, 8, 9}));
460}
461
463{
464 std::vector<int> empty;
465 auto sorted = stdsort(empty);
466 EXPECT_TRUE(sorted.empty());
467}
468
469// ============================================================================
470// argsort() tests
471// ============================================================================
472
474{
475 Array<int> arr;
476 arr.append(30);
477 arr.append(10);
478 arr.append(20);
479
480 auto idx = argsort(arr);
481
482 static_assert(std::is_same_v<decltype(idx), Array<size_t>>);
483 ASSERT_EQ(idx.size(), arr.size());
484 EXPECT_EQ(idx(0), 1u);
485 EXPECT_EQ(idx(1), 2u);
486 EXPECT_EQ(idx(2), 0u);
487 EXPECT_EQ(arr(idx(0)), 10);
488 EXPECT_EQ(arr(idx(1)), 20);
489 EXPECT_EQ(arr(idx(2)), 30);
490}
491
493{
494 DynArray<int> arr;
495 arr.reserve(3);
496 arr(0) = 30;
497 arr(1) = 10;
498 arr(2) = 20;
499
500 auto idx = argsort(arr);
501
502 ASSERT_EQ(idx.size(), arr.size());
503 EXPECT_EQ(arr(idx(0)), 10);
504 EXPECT_EQ(arr(idx(1)), 20);
505 EXPECT_EQ(arr(idx(2)), 30);
506}
507
509{
510 vector<int> values = {30, 10, 20};
511
512 auto idx = argsort(values);
513
514 ASSERT_EQ(idx.size(), values.size());
515 EXPECT_EQ(idx(0), 1u);
516 EXPECT_EQ(idx(1), 2u);
517 EXPECT_EQ(idx(2), 0u);
518 EXPECT_EQ(values[idx(0)], 10);
519 EXPECT_EQ(values[idx(1)], 20);
520 EXPECT_EQ(values[idx(2)], 30);
521}
522
524{
525 vector<int> values;
526
527 auto idx = argsort(values);
528
529 EXPECT_TRUE(idx.is_empty());
530}
531
533{
534 vector<int> values = {10, 30, 20};
535
536 auto idx = argsort(values, std::greater<int>());
537
538 ASSERT_EQ(idx.size(), values.size());
539 EXPECT_EQ(values[idx(0)], 30);
540 EXPECT_EQ(values[idx(1)], 20);
541 EXPECT_EQ(values[idx(2)], 10);
542}
543
545{
546 DynArray<int> arr;
547 arr.reserve(5);
548 arr(0) = 5;
549 arr(1) = 1;
550 arr(2) = 4;
551 arr(3) = 2;
552 arr(4) = 3;
553
554 auto idx = argsort(arr);
555 auto ref = build_index(arr);
556
557 ASSERT_EQ(idx.size(), ref.size());
558 for (size_t i = 0; i < idx.size(); ++i)
559 EXPECT_EQ(idx(i), ref(i));
560}
561
563{
564 Array<int> arr;
565 arr.append(2);
566 arr.append(1);
567 arr.append(2);
568 arr.append(1);
569 arr.append(2);
570
571 auto idx = stable_argsort(arr);
572
573 static_assert(std::is_same_v<decltype(idx), Array<size_t>>);
574 ASSERT_EQ(idx.size(), arr.size());
575 EXPECT_EQ(idx(0), 1u);
576 EXPECT_EQ(idx(1), 3u);
577 EXPECT_EQ(idx(2), 0u);
578 EXPECT_EQ(idx(3), 2u);
579 EXPECT_EQ(idx(4), 4u);
580}
581
583{
584 DynArray<int> arr;
585 arr.reserve(5);
586 arr(0) = 2;
587 arr(1) = 1;
588 arr(2) = 2;
589 arr(3) = 1;
590 arr(4) = 2;
591
592 auto idx = stable_argsort(arr);
593
594 ASSERT_EQ(idx.size(), arr.size());
595 EXPECT_EQ(idx(0), 1u);
596 EXPECT_EQ(idx(1), 3u);
597 EXPECT_EQ(idx(2), 0u);
598 EXPECT_EQ(idx(3), 2u);
599 EXPECT_EQ(idx(4), 4u);
600}
601
603{
604 vector<int> values = {2, 1, 2, 1, 2};
605
606 auto idx = stable_argsort(values);
607
608 ASSERT_EQ(idx.size(), values.size());
609 EXPECT_EQ(idx(0), 1u);
610 EXPECT_EQ(idx(1), 3u);
611 EXPECT_EQ(idx(2), 0u);
612 EXPECT_EQ(idx(3), 2u);
613 EXPECT_EQ(idx(4), 4u);
614}
615
617{
618 vector<int> values(64, 7);
619
620 auto idx = stable_argsort(values);
621
622 ASSERT_EQ(idx.size(), values.size());
623 for (size_t i = 0; i < idx.size(); ++i)
624 EXPECT_EQ(idx(i), i);
625}
626
628{
629 vector<int> values;
630 for (size_t i = 0; i < 75; ++i)
631 values.push_back(static_cast<int>((i * 17) % 5));
632
633 auto idx = stable_argsort(values);
634
635 ASSERT_EQ(idx.size(), values.size());
636 for (size_t i = 1; i < idx.size(); ++i)
637 {
638 ASSERT_LE(values[idx(i - 1)], values[idx(i)]);
639 if (values[idx(i - 1)] == values[idx(i)])
640 EXPECT_LT(idx(i - 1), idx(i));
641 }
642}
643
648
653
655{
656 vector<int> values = {1, 3, 2, 3, 2};
657
658 auto idx = stable_argsort(values, std::greater<int>());
659
660 ASSERT_EQ(idx.size(), values.size());
661 EXPECT_EQ(idx(0), 1u);
662 EXPECT_EQ(idx(1), 3u);
663 EXPECT_EQ(idx(2), 2u);
664 EXPECT_EQ(idx(3), 4u);
665 EXPECT_EQ(idx(4), 0u);
666}
667
669{
670 DynArray<int> arr;
671 arr.reserve(5);
672 arr(0) = 2;
673 arr(1) = 1;
674 arr(2) = 2;
675 arr(3) = 1;
676 arr(4) = 2;
677
678 auto idx = stable_argsort(arr);
679 auto ref = stable_build_index(arr);
680
681 ASSERT_EQ(idx.size(), ref.size());
682 for (size_t i = 0; i < idx.size(); ++i)
683 EXPECT_EQ(idx(i), ref(i));
684}
685
686// ============================================================================
687// ranks() tests
688// ============================================================================
689
691{
692 DynArray<int> arr;
693 arr.reserve(3);
694 arr(0) = 30; // rank 2
695 arr(1) = 10; // rank 0
696 arr(2) = 20; // rank 1
697
698 auto r = ranks(arr);
699
700 EXPECT_EQ(r(0), 2u); // 30 is largest -> rank 2
701 EXPECT_EQ(r(1), 0u); // 10 is smallest -> rank 0
702 EXPECT_EQ(r(2), 1u); // 20 is middle -> rank 1
703}
704
706{
707 Array<int> arr;
708 arr.append(30);
709 arr.append(10);
710 arr.append(20);
711
712 auto r = ranks(arr);
713
714 EXPECT_EQ(r(0), 2u);
715 EXPECT_EQ(r(1), 0u);
716 EXPECT_EQ(r(2), 1u);
717}
718
720{
721 DynList<int> list;
722 list.append(30);
723 list.append(10);
724 list.append(20);
725
726 auto r = ranks(list);
727
728 EXPECT_EQ(r(0), 2u);
729 EXPECT_EQ(r(1), 0u);
730 EXPECT_EQ(r(2), 1u);
731}
732
734{
735 DynDlist<int> list;
736 list.append(30);
737 list.append(10);
738 list.append(20);
739
740 auto r = ranks(list);
741
742 EXPECT_EQ(r(0), 2u);
743 EXPECT_EQ(r(1), 0u);
744 EXPECT_EQ(r(2), 1u);
745}
746
748{
749 DynArray<int> empty;
750 auto r = ranks(empty);
751 EXPECT_EQ(r.size(), 0u);
752}
753
755{
757 single.reserve(1);
758 single.touch(0) = 42;
759 auto r = ranks(single);
760 EXPECT_EQ(r.size(), 1u);
761 EXPECT_EQ(r(0), 0u);
762}
763
765{
766 DynArray<int> arr;
767 arr.reserve(5);
768 for (size_t i = 0; i < 5; ++i)
769 arr(i) = static_cast<int>(i);
770
771 auto r = ranks(arr);
772
773 for (size_t i = 0; i < 5; ++i)
774 EXPECT_EQ(r(i), i);
775}
776
778{
779 DynArray<int> arr;
780 arr.reserve(5);
781 for (size_t i = 0; i < 5; ++i)
782 arr(i) = static_cast<int>(4 - i);
783
784 auto r = ranks(arr);
785
786 for (size_t i = 0; i < 5; ++i)
787 EXPECT_EQ(r(i), 4 - i);
788}
789
791{
792 DynArray<int> arr;
793 arr.reserve(6);
794 arr(0) = 5;
795 arr(1) = 1;
796 arr(2) = 5;
797 arr(3) = 2;
798 arr(4) = 2;
799 arr(5) = 1;
800
801 auto r = ranks(arr);
802 ASSERT_EQ(r.size(), arr.size());
803
804 // ranks() must be a permutation of 0..n-1
805 std::vector<size_t> seen(r.size(), 0);
806 for (size_t i = 0; i < r.size(); ++i)
807 {
808 ASSERT_LT(r(i), r.size());
809 ++seen[r(i)];
810 }
811 for (size_t k = 0; k < seen.size(); ++k)
812 EXPECT_EQ(seen[k], 1u);
813
814 // Ordering property: if a[i] < a[j] then r[i] < r[j]
815 for (size_t i = 0; i < arr.size(); ++i)
816 for (size_t j = 0; j < arr.size(); ++j)
817 if (arr(i) < arr(j))
818 EXPECT_LT(r(i), r(j));
819}
820
821// ============================================================================
822// pair_ranks() tests
823// ============================================================================
824
826{
827 DynArray<int> arr;
828 arr.reserve(3);
829 arr(0) = 30;
830 arr(1) = 10;
831 arr(2) = 20;
832
833 auto pr = pair_ranks(arr);
834
835 EXPECT_EQ(pr(0).first, 30);
836 EXPECT_EQ(pr(0).second, 2u);
837 EXPECT_EQ(pr(1).first, 10);
838 EXPECT_EQ(pr(1).second, 0u);
839 EXPECT_EQ(pr(2).first, 20);
840 EXPECT_EQ(pr(2).second, 1u);
841}
842
844{
845 Array<int> arr;
846 arr.append(30);
847 arr.append(10);
848 arr.append(20);
849
850 auto pr = pair_ranks(arr);
851
852 EXPECT_EQ(pr(0).first, 30);
853 EXPECT_EQ(pr(0).second, 2u);
854}
855
857{
858 DynList<int> list;
859 list.append(30);
860 list.append(10);
861 list.append(20);
862
863 auto pr = pair_ranks(list);
864
865 EXPECT_EQ(pr(0).first, 30);
866 EXPECT_EQ(pr(0).second, 2u);
867 EXPECT_EQ(pr(1).first, 10);
868 EXPECT_EQ(pr(1).second, 0u);
869}
870
872{
873 DynDlist<int> list;
874 list.append(30);
875 list.append(10);
876 list.append(20);
877
878 auto pr = pair_ranks(list);
879
880 EXPECT_EQ(pr(0).first, 30);
881 EXPECT_EQ(pr(0).second, 2u);
882}
883
884// ============================================================================
885// in_place_multisort_arrays() tests
886// ============================================================================
887
889{
890 std::vector<int> keys = {3, 1, 2};
891 std::vector<std::string> names = {"Charlie", "Alice", "Bob"};
892
893 in_place_multisort_arrays(std::less<int>(), keys, names);
894
895 EXPECT_EQ(keys, (std::vector<int>{1, 2, 3}));
896 EXPECT_EQ(names, (std::vector<std::string>{"Alice", "Bob", "Charlie"}));
897}
898
900{
901 std::vector<int> ids = {3, 1, 2};
902 std::vector<std::string> names = {"Charlie", "Alice", "Bob"};
903 std::vector<int> ages = {30, 25, 28};
904
905 in_place_multisort_arrays(std::less<int>(), ids, names, ages);
906
907 EXPECT_EQ(ids, (std::vector<int>{1, 2, 3}));
908 EXPECT_EQ(names, (std::vector<std::string>{"Alice", "Bob", "Charlie"}));
909 EXPECT_EQ(ages, (std::vector<int>{25, 28, 30}));
910}
911
913{
914 std::vector<int> keys = {1, 2, 3};
915 std::vector<char> values = {'a', 'b', 'c'};
916
917 in_place_multisort_arrays(std::greater<int>(), keys, values);
918
919 EXPECT_EQ(keys, (std::vector<int>{3, 2, 1}));
920 EXPECT_EQ(values, (std::vector<char>{'c', 'b', 'a'}));
921}
922
924{
925 std::vector<int> keys;
926 std::vector<int> values;
927
928 // Should not throw
929 in_place_multisort_arrays(std::less<int>(), keys, values);
930
931 EXPECT_TRUE(keys.empty());
932 EXPECT_TRUE(values.empty());
933}
934
936{
937 std::vector<int> keys = {42};
938 std::vector<std::string> values = {"answer"};
939
940 in_place_multisort_arrays(std::less<int>(), keys, values);
941
942 EXPECT_EQ(keys, (std::vector<int>{42}));
943 EXPECT_EQ(values, (std::vector<std::string>{"answer"}));
944}
945
947{
948 std::vector<int> keys = {2, 1, 2, 1, 2};
949 std::vector<char> aux = {'a', 'b', 'c', 'd', 'e'};
950
951 in_place_multisort_arrays(std::less<int>(), keys, aux);
952
953 EXPECT_EQ(keys, (std::vector<int>{1, 1, 2, 2, 2}));
954 // Stable: elements with equal keys preserve relative order
955 EXPECT_EQ(aux, (std::vector<char>{'b', 'd', 'a', 'c', 'e'}));
956}
957
959{
960 std::vector<int> keys = {1, 2, 3, 4, 5};
961 std::vector<int> values = {10, 20, 30, 40, 50};
962
963 in_place_multisort_arrays(std::less<int>(), keys, values);
964
965 EXPECT_EQ(keys, (std::vector<int>{1, 2, 3, 4, 5}));
966 EXPECT_EQ(values, (std::vector<int>{10, 20, 30, 40, 50}));
967}
968
970{
971 std::mt19937 rng(123456u);
972 std::uniform_int_distribution<int> key_dist(0, 5);
973
974 for (size_t trial = 0; trial < 50; ++trial)
975 {
976 const size_t n = 100;
977 std::vector<int> keys(n);
978 std::vector<size_t> pos(n);
979 for (size_t i = 0; i < n; ++i)
980 {
981 keys[i] = key_dist(rng);
982 pos[i] = i;
983 }
984
985 in_place_multisort_arrays(std::less<int>(), true, keys, pos);
986
987 for (size_t i = 1; i < n; ++i)
988 {
989 ASSERT_LE(keys[i - 1], keys[i]);
990 if (keys[i - 1] == keys[i])
991 ASSERT_LT(pos[i - 1], pos[i]);
992 }
993 }
994}
995
997{
998 std::mt19937 rng(78910u);
999 std::uniform_int_distribution<int> key_dist(0, 5);
1000
1001 const size_t n = 200;
1002 std::vector<int> keys(n);
1003 std::vector<size_t> pos(n);
1004 for (size_t i = 0; i < n; ++i)
1005 {
1006 keys[i] = key_dist(rng);
1007 pos[i] = i;
1008 }
1009
1010 in_place_multisort_arrays(std::less<int>(), false, keys, pos);
1011
1012 for (size_t i = 1; i < n; ++i)
1013 ASSERT_LE(keys[i - 1], keys[i]);
1014
1015 std::vector<size_t> seen(n, 0);
1016 for (auto p : pos)
1017 {
1018 ASSERT_LT(p, n);
1019 ++seen[p];
1020 }
1021 for (size_t k = 0; k < n; ++k)
1022 ASSERT_EQ(seen[k], 1u);
1023}
1024
1026{
1027 std::vector<int> keys = {5, 4, 3, 2, 1};
1028 std::vector<int> values = {50, 40, 30, 20, 10};
1029
1030 in_place_multisort_arrays(std::less<int>(), keys, values);
1031
1032 EXPECT_EQ(keys, (std::vector<int>{1, 2, 3, 4, 5}));
1033 EXPECT_EQ(values, (std::vector<int>{10, 20, 30, 40, 50}));
1034}
1035
1037{
1038 std::vector<int> keys = {1, 2};
1039 std::vector<int> values = {10};
1040
1041 EXPECT_THROW(in_place_multisort_arrays(std::less<int>(), keys, values),
1042 std::invalid_argument);
1043}
1044
1046{
1048 keys.append(3); keys.append(1); keys.append(2);
1049
1050 Array<std::string> values;
1051 values.append("c"); values.append("a"); values.append("b");
1052
1053 in_place_multisort_arrays(std::less<int>(), keys, values);
1054
1055 EXPECT_EQ(keys(0), 1);
1056 EXPECT_EQ(keys(1), 2);
1057 EXPECT_EQ(keys(2), 3);
1058 EXPECT_EQ(values(0), "a");
1059 EXPECT_EQ(values(1), "b");
1060 EXPECT_EQ(values(2), "c");
1061}
1062
1064{
1065 std::vector<int> keys = {2, 1, 2, 1, 2};
1066 std::vector<char> aux = {'a', 'b', 'c', 'd', 'e'};
1067
1068 in_place_multisort_arrays(std::less<int>(), true, keys, aux);
1069
1070 EXPECT_EQ(keys, (std::vector<int>{1, 1, 2, 2, 2}));
1071 EXPECT_EQ(aux, (std::vector<char>{'b', 'd', 'a', 'c', 'e'}));
1072}
1073
1075{
1076 std::vector<int> keys = {2, 1, 2, 1, 2};
1077 std::vector<char> aux = {'a', 'b', 'c', 'd', 'e'};
1078
1079 in_place_multisort_arrays(std::less<int>(), false, keys, aux);
1080
1081 EXPECT_EQ(keys, (std::vector<int>{1, 1, 2, 2, 2}));
1082 // Result order may differ from stable sort; only keys are guaranteed
1083 EXPECT_EQ(keys.size(), aux.size());
1084}
1085
1087{
1088 std::vector<std::string> keys = {"banana", "apple", "banana", "apple"};
1089 std::vector<int> values = {2, 1, 3, 4};
1090
1091 in_place_multisort_arrays(std::greater<std::string>(), false, keys, values);
1092
1093 EXPECT_EQ(keys, (std::vector<std::string>{"banana", "banana", "apple", "apple"}));
1094 EXPECT_EQ(values.size(), 4);
1095}
1096
1097// ============================================================================
1098// Type traits and compile-time checks
1099// ============================================================================
1100
1102{
1103 // The [[nodiscard]] attribute is tested implicitly:
1104 // If we call sort() without using the result, the compiler would warn.
1105 // This test just verifies the functions compile correctly.
1106 DynList<int> list;
1107 list.append(1);
1108 [[maybe_unused]] auto s1 = sort(list);
1109 [[maybe_unused]] auto s2 = sort(std::move(list));
1110}
1111
1113{
1114 DynArray<int> arr;
1115 arr.reserve(1);
1116 arr.touch(0) = 1;
1117 [[maybe_unused]] auto r = ranks(arr);
1118}
1119
1121{
1122 DynArray<int> arr;
1123 arr.reserve(1);
1124 arr.touch(0) = 1;
1125 [[maybe_unused]] auto pr = pair_ranks(arr);
1126}
1127
1128// ============================================================================
1129// Edge cases and stress tests
1130// ============================================================================
1131
1133{
1134 DynList<int> list;
1135 for (int i = 999; i >= 0; --i)
1136 list.append(i);
1137
1138 auto sorted = sort(list);
1140 EXPECT_EQ(sorted.get_first(), 0);
1141 EXPECT_EQ(sorted.get_last(), 999);
1142}
1143
1145{
1146 DynArray<int> arr;
1147 arr.reserve(1000);
1148 for (size_t i = 0; i < 1000; ++i)
1149 arr(i) = static_cast<int>(999 - i);
1150
1151 in_place_sort(arr);
1152
1153 for (size_t i = 1; i < arr.size(); ++i)
1154 EXPECT_LE(arr(i-1), arr(i));
1155}
1156
1158{
1159 DynList<int> list;
1160 for (int i = 0; i < 100; ++i)
1161 list.append(42);
1162
1163 auto sorted = sort(list);
1165
1166 sorted.for_each([](int x) {
1167 EXPECT_EQ(x, 42);
1168 });
1169}
1170
1172{
1174 list.append("banana");
1175 list.append("apple");
1176 list.append("cherry");
1177
1178 auto sorted = sort(list);
1179
1180 EXPECT_EQ(sorted.get_first(), "apple");
1181 EXPECT_EQ(sorted.get_last(), "cherry");
1182}
1183
1185{
1186 DynArray<int> arr;
1187 arr.reserve(5);
1188 arr(0) = 1; arr(1) = 2; arr(2) = 3; arr(3) = 4; arr(4) = 5;
1189
1190 // Sort by absolute difference from 3
1191 auto sorted = sort(arr, [](int a, int b) {
1192 return std::abs(a - 3) < std::abs(b - 3);
1193 });
1194
1195 EXPECT_EQ(sorted(0), 3); // difference 0
1196}
High-level sorting functions for Aleph containers.
TEST_F(DynListSortTest, SortReturnsSortedCopy)
Simple dynamic array with automatic resizing and functional operations.
Definition tpl_array.H:138
constexpr size_t size() const noexcept
Return the number of elements stored in the stack.
Definition tpl_array.H:365
T & append(const T &data)
Append a copy of data
Definition tpl_array.H:250
T & touch(const size_t i)
Touch the entry i.
size_t size() const noexcept
Return the current dimension of array.
void reserve(const size_t l, const size_t r)
Allocate a range of entries.
Dynamic doubly linked list with O(1) size and bidirectional access.
T & append(const T &item)
Append a copied item at the end of the list.
Doubly-linked list (defined in tpl_dynList.H).
Definition htlist.H:1155
T & append(const T &item)
Definition htlist.H:1271
void SetUp() override
Array< int > arr
Array< int > build_array(std::initializer_list< int > items)
DynArray< int > arr
void SetUp() override
DynArray< int > build_array(std::initializer_list< int > items)
DynDlist< int > list
void SetUp() override
DynDlist< int > build_list(std::initializer_list< int > items)
DynList< int > list
void SetUp() override
DynList< int > build_list(std::initializer_list< int > items)
#define TEST(name)
static mt19937 rng
int cmp(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Definition gmpfrxx.h:4129
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
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
bool is_sorted(const Container< T > &cont, const Compare &cmp=Compare())
Check if a container is sorted in ascending order.
Array< size_t > stable_build_index(const C &a, const Compare &cmp=Compare())
Build a stable index array for indirect sorting.
auto pair_ranks(const Array< T > &c)
Computes (value, rank) pairs for each element in an Array.
Definition ahSort.H:761
Array< size_t > stable_argsort(const C &a, const Compare &cmp=Compare())
Return stable sorted-order indices for an array-like container.
Definition ahSort.H:433
DynArray< T > sort(const DynArray< T > &a, Cmp &&cmp=Cmp())
Returns a sorted copy of a DynArray.
Definition ahSort.H:234
Array< size_t > build_index(const C &a, const Compare &cmp=Compare())
Build an index array for indirect sorting.
std::string code(Node *root)
Compute a string with the Lukasiewicz`s word of a tree.
DynArray< T > & in_place_sort(DynArray< T > &c, Cmp cmp=Cmp())
Sorts a DynArray in place.
Definition ahSort.H:328
Array< size_t > ranks(const Array< T > &array)
Computes the rank of each element in an Array.
Definition ahSort.H:698
Array< size_t > argsort(const C &a, const Compare &cmp=Compare())
Return indices that visit an array-like container in sorted order.
Definition ahSort.H:385
Container stdsort(const Container &c, Cmp cmp=Cmp())
Sorts an STL-compatible container using std::sort.
Definition ahSort.H:307
void in_place_multisort_arrays(Cmp cmp, const bool stable, C &first, Args &... args)
Sorts multiple arrays in place, using the first array as the key.
Definition ahSort.H:844
Array< T > build_array(Args... args)
Definition tpl_array.H:624
STL namespace.
int keys[]
static int * k
gsl_rng * r
Lazy and scalable dynamic array implementation.
Dynamic doubly linked list implementation.
Alias for htlist.H (DynList implementation).
DynList< int > l