|
4 | 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying |
5 | 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
6 | 6 |
|
7 | | -// Regression test: hpx::is_sorted, hpx::is_sorted_until, and |
8 | | -// hpx::is_partitioned did not expose a projection parameter in their CPO |
9 | | -// (tag_fallback_invoke) overloads, despite the internal algorithm |
10 | | -// implementations fully supporting projections. This file validates that |
11 | | -// all three algorithms accept a projection with seq and par policies. |
12 | | - |
13 | 7 | #include <hpx/algorithm.hpp> |
14 | 8 | #include <hpx/init.hpp> |
15 | 9 | #include <hpx/modules/testing.hpp> |
|
19 | 13 | #include <utility> |
20 | 14 | #include <vector> |
21 | 15 |
|
22 | | -// --------------------------------------------------------------------------- |
23 | | -// is_sorted with projection |
24 | | -// --------------------------------------------------------------------------- |
25 | 16 | void test_is_sorted_projection() |
26 | 17 | { |
27 | 18 | using namespace hpx::execution; |
28 | 19 | using element = std::pair<int, int>; |
29 | 20 |
|
30 | | - // sorted by .second: 1, 3, 5, 8 |
31 | 21 | std::vector<element> sorted_c = {{10, 1}, {20, 3}, {30, 5}, {40, 8}}; |
32 | | - // NOT sorted by .second: 1, 5, 3, 8 |
33 | 22 | std::vector<element> unsorted_c = {{10, 1}, {20, 5}, {30, 3}, {40, 8}}; |
34 | 23 |
|
35 | 24 | auto proj = [](element const& p) { return p.second; }; |
36 | 25 |
|
37 | | - // sequential, no policy |
38 | 26 | HPX_TEST(hpx::is_sorted( |
39 | 27 | sorted_c.begin(), sorted_c.end(), std::less<int>{}, proj)); |
40 | 28 | HPX_TEST(!hpx::is_sorted( |
41 | 29 | unsorted_c.begin(), unsorted_c.end(), std::less<int>{}, proj)); |
42 | 30 |
|
43 | | - // seq policy |
44 | 31 | HPX_TEST(hpx::is_sorted( |
45 | 32 | seq, sorted_c.begin(), sorted_c.end(), std::less<int>{}, proj)); |
46 | 33 | HPX_TEST(!hpx::is_sorted( |
47 | 34 | seq, unsorted_c.begin(), unsorted_c.end(), std::less<int>{}, proj)); |
48 | 35 |
|
49 | | - // par policy |
50 | 36 | HPX_TEST(hpx::is_sorted( |
51 | 37 | par, sorted_c.begin(), sorted_c.end(), std::less<int>{}, proj)); |
52 | 38 | HPX_TEST(!hpx::is_sorted( |
53 | 39 | par, unsorted_c.begin(), unsorted_c.end(), std::less<int>{}, proj)); |
54 | 40 |
|
55 | | - // par(task) policy |
56 | 41 | HPX_TEST(hpx::is_sorted( |
57 | 42 | par(task), sorted_c.begin(), sorted_c.end(), std::less<int>{}, proj) |
58 | 43 | .get()); |
59 | 44 | HPX_TEST(!hpx::is_sorted( |
60 | 45 | par(task), unsorted_c.begin(), unsorted_c.end(), std::less<int>{}, proj) |
61 | 46 | .get()); |
62 | 47 |
|
63 | | - // empty range always returns true |
64 | 48 | HPX_TEST(hpx::is_sorted( |
65 | 49 | par, sorted_c.begin(), sorted_c.begin(), std::less<int>{}, proj)); |
66 | | - // single element range always returns true |
67 | 50 | HPX_TEST(hpx::is_sorted( |
68 | 51 | par, sorted_c.begin(), sorted_c.begin() + 1, std::less<int>{}, proj)); |
69 | 52 | } |
70 | 53 |
|
71 | | -// --------------------------------------------------------------------------- |
72 | | -// is_sorted_until with projection |
73 | | -// --------------------------------------------------------------------------- |
74 | 54 | void test_is_sorted_until_projection() |
75 | 55 | { |
76 | 56 | using namespace hpx::execution; |
77 | 57 | using element = std::pair<int, int>; |
78 | 58 |
|
79 | | - // sorted by .second: 1, 3, 8; then unsorted at index 3 (value 5) |
80 | 59 | std::vector<element> c = {{10, 1}, {20, 3}, {30, 8}, {40, 5}, {50, 9}}; |
81 | 60 |
|
82 | 61 | auto proj = [](element const& p) { return p.second; }; |
83 | 62 |
|
84 | | - // sequential, no policy |
85 | 63 | auto it_seq = |
86 | 64 | hpx::is_sorted_until(c.begin(), c.end(), std::less<int>{}, proj); |
87 | 65 | HPX_TEST(it_seq != c.end()); |
88 | 66 | HPX_TEST_EQ(it_seq->second, 5); |
89 | 67 |
|
90 | | - // seq policy |
91 | 68 | auto it_seq2 = |
92 | 69 | hpx::is_sorted_until(seq, c.begin(), c.end(), std::less<int>{}, proj); |
93 | 70 | HPX_TEST(it_seq2 != c.end()); |
94 | 71 | HPX_TEST_EQ(it_seq2->second, 5); |
95 | 72 |
|
96 | | - // par policy |
97 | 73 | auto it_par = |
98 | 74 | hpx::is_sorted_until(par, c.begin(), c.end(), std::less<int>{}, proj); |
99 | 75 | HPX_TEST(it_par != c.end()); |
100 | 76 | HPX_TEST_EQ(it_par->second, 5); |
101 | 77 |
|
102 | | - // par(task) policy |
103 | 78 | auto it_task = hpx::is_sorted_until( |
104 | 79 | par(task), c.begin(), c.end(), std::less<int>{}, proj) |
105 | 80 | .get(); |
106 | 81 | HPX_TEST(it_task != c.end()); |
107 | 82 | HPX_TEST_EQ(it_task->second, 5); |
108 | 83 |
|
109 | | - // fully sorted range should return end |
110 | 84 | std::vector<element> fully_sorted = {{10, 1}, {20, 3}, {30, 5}}; |
111 | 85 | auto it_end = hpx::is_sorted_until( |
112 | 86 | par, fully_sorted.begin(), fully_sorted.end(), std::less<int>{}, proj); |
113 | 87 | HPX_TEST(it_end == fully_sorted.end()); |
114 | 88 |
|
115 | | - // empty range should return end (begin == end) |
116 | 89 | auto it_empty = hpx::is_sorted_until(par, fully_sorted.begin(), |
117 | 90 | fully_sorted.begin(), std::less<int>{}, proj); |
118 | 91 | HPX_TEST(it_empty == fully_sorted.begin()); |
119 | 92 | } |
120 | 93 |
|
121 | | -// --------------------------------------------------------------------------- |
122 | | -// is_partitioned with projection |
123 | | -// --------------------------------------------------------------------------- |
124 | 94 | void test_is_partitioned_projection() |
125 | 95 | { |
126 | 96 | using namespace hpx::execution; |
127 | 97 | using element = std::pair<int, int>; |
128 | 98 |
|
129 | | - // partitioned by .second % 2 == 0: all even seconds first, then odd |
130 | | - // second values: 2, 4, 1, 3 => partitioned (even before odd) |
131 | 99 | std::vector<element> partitioned_c = {{10, 2}, {20, 4}, {30, 1}, {40, 3}}; |
132 | | - // NOT partitioned by .second % 2 == 0: 2, 1, 4, 3 |
133 | 100 | std::vector<element> not_partitioned_c = { |
134 | 101 | {10, 2}, {20, 1}, {30, 4}, {40, 3}}; |
135 | 102 |
|
136 | 103 | auto proj = [](element const& p) { return p.second; }; |
137 | 104 | auto pred = [](int v) { return v % 2 == 0; }; |
138 | 105 |
|
139 | | - // sequential, no policy |
140 | 106 | HPX_TEST(hpx::is_partitioned( |
141 | 107 | partitioned_c.begin(), partitioned_c.end(), pred, proj)); |
142 | 108 | HPX_TEST(!hpx::is_partitioned( |
143 | 109 | not_partitioned_c.begin(), not_partitioned_c.end(), pred, proj)); |
144 | 110 |
|
145 | | - // seq policy |
146 | 111 | HPX_TEST(hpx::is_partitioned( |
147 | 112 | seq, partitioned_c.begin(), partitioned_c.end(), pred, proj)); |
148 | 113 | HPX_TEST(!hpx::is_partitioned( |
149 | 114 | seq, not_partitioned_c.begin(), not_partitioned_c.end(), pred, proj)); |
150 | 115 |
|
151 | | - // par policy |
152 | 116 | HPX_TEST(hpx::is_partitioned( |
153 | 117 | par, partitioned_c.begin(), partitioned_c.end(), pred, proj)); |
154 | 118 | HPX_TEST(!hpx::is_partitioned( |
155 | 119 | par, not_partitioned_c.begin(), not_partitioned_c.end(), pred, proj)); |
156 | 120 |
|
157 | | - // par(task) policy |
158 | 121 | HPX_TEST(hpx::is_partitioned( |
159 | 122 | par(task), partitioned_c.begin(), partitioned_c.end(), pred, proj) |
160 | 123 | .get()); |
161 | 124 | HPX_TEST(!hpx::is_partitioned(par(task), not_partitioned_c.begin(), |
162 | 125 | not_partitioned_c.end(), pred, proj) |
163 | 126 | .get()); |
164 | 127 |
|
165 | | - // empty range is always partitioned |
166 | 128 | HPX_TEST(hpx::is_partitioned( |
167 | 129 | par, partitioned_c.begin(), partitioned_c.begin(), pred, proj)); |
168 | | - // single element range is always partitioned |
169 | 130 | HPX_TEST(hpx::is_partitioned( |
170 | 131 | par, partitioned_c.begin(), partitioned_c.begin() + 1, pred, proj)); |
171 | 132 | } |
|
0 commit comments