Skip to content

Commit aa949ce

Browse files
committed
Augment ranges::{fill, fill_n, find} with missing tests
1 parent 5450954 commit aa949ce

File tree

7 files changed

+151
-96
lines changed

7 files changed

+151
-96
lines changed

Diff for: libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/fill.pass.cpp

+10-42
Original file line numberDiff line numberDiff line change
@@ -84,48 +84,16 @@ TEST_CONSTEXPR_CXX20 void test_bititer_with_custom_sized_types() {
8484
TEST_CONSTEXPR_CXX20 bool test() {
8585
types::for_each(types::forward_iterator_list<char*>(), Test<char>());
8686
types::for_each(types::forward_iterator_list<int*>(), Test<int>());
87-
{ // test vector<bool>::iterator optimization
88-
{ // simple case
89-
std::vector<bool> in(4, false);
90-
std::vector<bool> expected(4, true);
91-
std::fill(in.begin(), in.end(), true);
92-
assert(in == expected);
93-
}
94-
{ // partial byte in the front is not filled
95-
std::vector<bool> in(8, false);
96-
std::vector<bool> expected(8, true);
97-
expected[0] = false;
98-
expected[1] = false;
99-
std::fill(in.begin() + 2, in.end(), true);
100-
assert(in == expected);
101-
}
102-
{ // partial byte in the back is not filled
103-
std::vector<bool> in(8, false);
104-
std::vector<bool> expected(8, true);
105-
expected[6] = false;
106-
expected[7] = false;
107-
std::fill(in.begin(), in.end() - 2, true);
108-
assert(in == expected);
109-
}
110-
{ // partial byte in the front and back is not filled
111-
std::vector<bool> in(16, false);
112-
std::vector<bool> expected(16, true);
113-
expected[0] = false;
114-
expected[1] = false;
115-
expected[14] = false;
116-
expected[15] = false;
117-
std::fill(in.begin() + 2, in.end() - 2, true);
118-
assert(in == expected);
119-
}
120-
{ // only a few bits of a byte are set
121-
std::vector<bool> in(8, false);
122-
std::vector<bool> expected(8, true);
123-
expected[0] = false;
124-
expected[1] = false;
125-
expected[6] = false;
126-
expected[7] = false;
127-
std::fill(in.begin() + 2, in.end() - 2, true);
128-
assert(in == expected);
87+
88+
{ // Test vector<bool>::iterator optimization
89+
for (std::size_t N = 8; N <= 256; N *= 2) {
90+
// Test with both full and partial bytes
91+
for (std::size_t offset = 0; offset <= 4; offset += 4) {
92+
std::vector<bool> in(N + 2 * offset);
93+
std::vector<bool> expected(N, true);
94+
std::fill(in.begin() + offset, in.end() - offset, true);
95+
assert(std::equal(in.begin() + offset, in.end() - offset, expected.begin()));
96+
}
12997
}
13098
}
13199

Diff for: libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/fill_n.pass.cpp

+15-2
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,21 @@ TEST_CONSTEXPR_CXX20 bool test() {
169169
types::for_each(types::forward_iterator_list<int*>(), Test<int>());
170170

171171
test_int_array();
172-
test_struct_array();
173-
test_int_array_struct_source();
172+
test_struct_array();
173+
test_int_array_struct_source();
174+
175+
{ // Test vector<bool>::iterator optimization
176+
for (std::size_t N = 8; N <= 256; N *= 2) {
177+
// Test with both full and partial bytes
178+
for (std::size_t offset = 0; offset <= 4; offset += 4) {
179+
std::vector<bool> in(N + 2 * offset);
180+
std::vector<bool> expected(N, true);
181+
std::fill_n(in.begin() + offset, N + offset, true);
182+
assert(std::equal(in.begin() + offset, in.end() - offset, expected.begin()));
183+
}
184+
}
185+
}
186+
174187
test_bititer_with_custom_sized_types();
175188

176189
return true;

Diff for: libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/ranges.fill.pass.cpp

+13-1
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,19 @@ constexpr bool test() {
173173
}
174174
}
175175

176-
#if TEST_STD_VER >= 23
176+
#if TEST_STD_VER >= 23
177+
{ // Test vector<bool>::iterator optimization
178+
for (std::size_t N = 8; N <= 256; N *= 2) {
179+
// Test with both full and partial bytes
180+
for (std::size_t offset : {0, 4}) {
181+
std::vector<bool> in(N + 2 * offset);
182+
std::vector<bool> expected(N, true);
183+
std::ranges::fill(std::ranges::begin(in) + offset, std::ranges::end(in) - offset, true);
184+
assert(std::equal(in.begin() + offset, in.end() - offset, expected.begin()));
185+
}
186+
}
187+
}
188+
177189
test_bititer_with_custom_sized_types();
178190
#endif
179191

Diff for: libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/ranges.fill_n.pass.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,18 @@ constexpr bool test() {
122122
}
123123

124124
#if TEST_STD_VER >= 23
125+
{ // Test vector<bool>::iterator optimization
126+
for (std::size_t N = 8; N <= 256; N *= 2) {
127+
// Test with both full and partial bytes
128+
for (std::size_t offset : {0, 4}) {
129+
std::vector<bool> in(N + 2 * offset);
130+
std::vector<bool> expected(N, true);
131+
std::ranges::fill_n(std::ranges::begin(in) + offset, N, true);
132+
assert(std::equal(in.begin() + offset, in.end() - offset, expected.begin()));
133+
}
134+
}
135+
}
136+
125137
test_bititer_with_custom_sized_types();
126138
#endif
127139

Diff for: libcxx/test/std/algorithms/alg.nonmodifying/alg.count/ranges.count.pass.cpp

+46-33
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,13 @@ constexpr void test_iterators() {
6767
{
6868
// simple test
6969
{
70-
int a[] = {1, 2, 3, 4};
70+
int a[] = {1, 2, 3, 4};
7171
std::same_as<std::ptrdiff_t> auto ret = std::ranges::count(It(a), Sent(It(a + 4)), 3);
7272
assert(ret == 1);
7373
}
7474
{
75-
int a[] = {1, 2, 3, 4};
76-
auto range = std::ranges::subrange(It(a), Sent(It(a + 4)));
75+
int a[] = {1, 2, 3, 4};
76+
auto range = std::ranges::subrange(It(a), Sent(It(a + 4)));
7777
std::same_as<std::ptrdiff_t> auto ret = std::ranges::count(range, 3);
7878
assert(ret == 1);
7979
}
@@ -83,13 +83,13 @@ constexpr void test_iterators() {
8383
// check that an empty range works
8484
{
8585
std::array<int, 0> a = {};
86-
auto ret = std::ranges::count(It(a.data()), Sent(It(a.data() + a.size())), 1);
86+
auto ret = std::ranges::count(It(a.data()), Sent(It(a.data() + a.size())), 1);
8787
assert(ret == 0);
8888
}
8989
{
9090
std::array<int, 0> a = {};
91-
auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data() + a.size())));
92-
auto ret = std::ranges::count(range, 1);
91+
auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data() + a.size())));
92+
auto ret = std::ranges::count(range, 1);
9393
assert(ret == 0);
9494
}
9595
}
@@ -98,13 +98,13 @@ constexpr void test_iterators() {
9898
// check that a range with a single element works
9999
{
100100
std::array a = {2};
101-
auto ret = std::ranges::count(It(a.data()), Sent(It(a.data() + a.size())), 2);
101+
auto ret = std::ranges::count(It(a.data()), Sent(It(a.data() + a.size())), 2);
102102
assert(ret == 1);
103103
}
104104
{
105105
std::array a = {2};
106-
auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data() + a.size())));
107-
auto ret = std::ranges::count(range, 2);
106+
auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data() + a.size())));
107+
auto ret = std::ranges::count(range, 2);
108108
assert(ret == 1);
109109
}
110110
}
@@ -113,13 +113,13 @@ constexpr void test_iterators() {
113113
// check that 0 is returned with no match
114114
{
115115
std::array a = {1, 1, 1};
116-
auto ret = std::ranges::count(It(a.data()), Sent(It(a.data() + a.size())), 0);
116+
auto ret = std::ranges::count(It(a.data()), Sent(It(a.data() + a.size())), 0);
117117
assert(ret == 0);
118118
}
119119
{
120120
std::array a = {1, 1, 1};
121-
auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data() + a.size())));
122-
auto ret = std::ranges::count(range, 0);
121+
auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data() + a.size())));
122+
auto ret = std::ranges::count(range, 0);
123123
assert(ret == 0);
124124
}
125125
}
@@ -128,13 +128,13 @@ constexpr void test_iterators() {
128128
// check that more than one element is counted
129129
{
130130
std::array a = {3, 3, 4, 3, 3};
131-
auto ret = std::ranges::count(It(a.data()), Sent(It(a.data() + a.size())), 3);
131+
auto ret = std::ranges::count(It(a.data()), Sent(It(a.data() + a.size())), 3);
132132
assert(ret == 4);
133133
}
134134
{
135135
std::array a = {3, 3, 4, 3, 3};
136-
auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data() + a.size())));
137-
auto ret = std::ranges::count(range, 3);
136+
auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data() + a.size())));
137+
auto ret = std::ranges::count(range, 3);
138138
assert(ret == 4);
139139
}
140140
}
@@ -143,13 +143,13 @@ constexpr void test_iterators() {
143143
// check that all elements are counted
144144
{
145145
std::array a = {5, 5, 5, 5};
146-
auto ret = std::ranges::count(It(a.data()), Sent(It(a.data() + a.size())), 5);
146+
auto ret = std::ranges::count(It(a.data()), Sent(It(a.data() + a.size())), 5);
147147
assert(ret == 4);
148148
}
149149
{
150150
std::array a = {5, 5, 5, 5};
151-
auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data() + a.size())));
152-
auto ret = std::ranges::count(range, 5);
151+
auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data() + a.size())));
152+
auto ret = std::ranges::count(range, 5);
153153
assert(ret == 4);
154154
}
155155
}
@@ -167,38 +167,46 @@ constexpr bool test() {
167167
{
168168
// check that projections are used properly and that they are called with the iterator directly
169169
{
170-
int a[] = {1, 2, 3, 4};
170+
int a[] = {1, 2, 3, 4};
171171
auto ret = std::ranges::count(a, a + 4, a + 3, [](int& i) { return &i; });
172172
assert(ret == 1);
173173
}
174174
{
175-
int a[] = {1, 2, 3, 4};
175+
int a[] = {1, 2, 3, 4};
176176
auto ret = std::ranges::count(a, a + 3, [](int& i) { return &i; });
177177
assert(ret == 1);
178178
}
179179
}
180180

181181
{
182182
// check that std::invoke is used
183-
struct S { int i; };
184-
S a[] = { S{1}, S{3}, S{2} };
183+
struct S {
184+
int i;
185+
};
186+
S a[] = {S{1}, S{3}, S{2}};
185187
std::same_as<std::ptrdiff_t> auto ret = std::ranges::count(a, 4, &S::i);
186188
assert(ret == 0);
187189
}
188190

189191
{
190192
// count invocations of the projection
191193
{
192-
int a[] = {1, 2, 3, 4};
194+
int a[] = {1, 2, 3, 4};
193195
int projection_count = 0;
194-
auto ret = std::ranges::count(a, a + 4, 2, [&](int i) { ++projection_count; return i; });
196+
auto ret = std::ranges::count(a, a + 4, 2, [&](int i) {
197+
++projection_count;
198+
return i;
199+
});
195200
assert(ret == 1);
196201
assert(projection_count == 4);
197202
}
198203
{
199-
int a[] = {1, 2, 3, 4};
204+
int a[] = {1, 2, 3, 4};
200205
int projection_count = 0;
201-
auto ret = std::ranges::count(a, 2, [&](int i) { ++projection_count; return i; });
206+
auto ret = std::ranges::count(a, 2, [&](int i) {
207+
++projection_count;
208+
return i;
209+
});
202210
assert(ret == 1);
203211
assert(projection_count == 4);
204212
}
@@ -208,20 +216,20 @@ constexpr bool test() {
208216
// check that an immobile type works
209217
struct NonMovable {
210218
NonMovable(const NonMovable&) = delete;
211-
NonMovable(NonMovable&&) = delete;
219+
NonMovable(NonMovable&&) = delete;
212220
constexpr NonMovable(int i_) : i(i_) {}
213221
int i;
214222

215223
bool operator==(const NonMovable&) const = default;
216224
};
217225
{
218226
NonMovable a[] = {9, 8, 4, 3};
219-
auto ret = std::ranges::count(a, a + 4, NonMovable(8));
227+
auto ret = std::ranges::count(a, a + 4, NonMovable(8));
220228
assert(ret == 1);
221229
}
222230
{
223231
NonMovable a[] = {9, 8, 4, 3};
224-
auto ret = std::ranges::count(a, NonMovable(8));
232+
auto ret = std::ranges::count(a, NonMovable(8));
225233
assert(ret == 1);
226234
}
227235
}
@@ -230,15 +238,18 @@ constexpr bool test() {
230238
// check that difference_type is used
231239
struct DiffTypeIterator {
232240
using difference_type = signed char;
233-
using value_type = int;
241+
using value_type = int;
234242

235243
int* it = nullptr;
236244

237245
constexpr DiffTypeIterator() = default;
238246
constexpr DiffTypeIterator(int* i) : it(i) {}
239247

240248
constexpr int& operator*() const { return *it; }
241-
constexpr DiffTypeIterator& operator++() { ++it; return *this; }
249+
constexpr DiffTypeIterator& operator++() {
250+
++it;
251+
return *this;
252+
}
242253
constexpr void operator++(int) { ++it; }
243254

244255
bool operator==(const DiffTypeIterator&) const = default;
@@ -251,7 +262,7 @@ constexpr bool test() {
251262
assert(ret == 1);
252263
}
253264
{
254-
int a[] = {5, 5, 4, 3, 2, 1};
265+
int a[] = {5, 5, 4, 3, 2, 1};
255266
auto range = std::ranges::subrange(DiffTypeIterator(a), DiffTypeIterator(a + 6));
256267
std::same_as<signed char> decltype(auto) ret = std::ranges::count(range, 4);
257268
assert(ret == 1);
@@ -264,7 +275,9 @@ constexpr bool test() {
264275
for (size_t offset = 0; offset != 64; ++offset) {
265276
std::fill(vec.begin(), vec.end(), false);
266277
std::fill(vec.begin() + offset, vec.begin() + i + offset, true);
267-
assert(std::ranges::count(vec.begin() + offset, vec.begin() + offset + 256, true) == i);
278+
279+
// check both (range) and (iterator, sentinel) overloads
280+
assert(std::ranges::count(vec, true) == i);
268281
assert(std::ranges::count(vec.begin() + offset, vec.begin() + offset + 256, false) == 256 - i);
269282
}
270283
}

Diff for: libcxx/test/std/algorithms/alg.nonmodifying/alg.find/find.pass.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
// MSVC warning C4389: '==': signed/unsigned mismatch
1515
// MSVC warning C4805: '==': unsafe mix of type 'char' and type 'bool' in operation
1616
// ADDITIONAL_COMPILE_FLAGS(cl-style-warnings): /wd4245 /wd4305 /wd4310 /wd4389 /wd4805
17+
// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=20000000
18+
// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-ops-limit): -fconstexpr-ops-limit=80000000
1719

1820
// <algorithm>
1921

@@ -24,6 +26,7 @@
2426

2527
#include <algorithm>
2628
#include <cassert>
29+
#include <cstddef>
2730
#include <deque>
2831
#include <vector>
2932
#include <type_traits>
@@ -225,6 +228,18 @@ TEST_CONSTEXPR_CXX20 bool test() {
225228

226229
types::for_each(types::integral_types(), TestIntegerPromotions());
227230

231+
{ // Test vector<bool>::iterator optimization
232+
std::vector<bool> vec(256 + 8);
233+
for (ptrdiff_t i = 8; i <= 256; i *= 2) {
234+
for (size_t offset = 0; offset < 8; offset += 2) {
235+
std::fill(vec.begin(), vec.end(), false);
236+
std::fill(vec.begin() + offset, vec.begin() + i + offset, true);
237+
assert(std::find(vec.begin(), vec.begin() + i + offset, true) == vec.begin() + offset);
238+
assert(std::find(vec.begin() + offset, vec.end(), false) == vec.begin() + offset + i);
239+
}
240+
}
241+
}
242+
228243
return true;
229244
}
230245

0 commit comments

Comments
 (0)