Skip to content

Commit fafdf97

Browse files
authored
[libc++] Simplify vector<bool>::flip() and add new tests (#119607)
This PR simplifies the internal bitwise logic of the `flip()` function for `vector<bool>`, and creates new tests to validate the changes.
1 parent e6b2495 commit fafdf97

File tree

2 files changed

+57
-10
lines changed

2 files changed

+57
-10
lines changed

libcxx/include/__vector/vector_bool.h

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,18 +1049,11 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<bool, _Allocator>::resize(size_type __
10491049

10501050
template <class _Allocator>
10511051
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<bool, _Allocator>::flip() _NOEXCEPT {
1052-
// do middle whole words
1053-
size_type __n = __size_;
1052+
// Flip each storage word entirely, including the last potentially partial word.
1053+
// The unused bits in the last word are safe to flip as they won't be accessed.
10541054
__storage_pointer __p = __begin_;
1055-
for (; __n >= __bits_per_word; ++__p, __n -= __bits_per_word)
1055+
for (size_type __n = __external_cap_to_internal(size()); __n != 0; ++__p, --__n)
10561056
*__p = ~*__p;
1057-
// do last partial word
1058-
if (__n > 0) {
1059-
__storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
1060-
__storage_type __b = *__p & __m;
1061-
*__p &= ~__m;
1062-
*__p |= ~__b & __m;
1063-
}
10641057
}
10651058

10661059
template <class _Allocator>
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// <vector>
10+
11+
// void flip();
12+
13+
#include <cassert>
14+
#include <memory>
15+
#include <vector>
16+
17+
#include "min_allocator.h"
18+
#include "test_allocator.h"
19+
#include "test_macros.h"
20+
21+
template <typename Allocator>
22+
TEST_CONSTEXPR_CXX20 void test_vector_flip(std::size_t n, Allocator a) {
23+
std::vector<bool, Allocator> v(n, false, a);
24+
for (std::size_t i = 0; i < n; ++i)
25+
v[i] = i & 1;
26+
std::vector<bool, Allocator> original = v;
27+
v.flip();
28+
for (size_t i = 0; i < n; ++i)
29+
assert(v[i] == !original[i]);
30+
v.flip();
31+
assert(v == original);
32+
}
33+
34+
TEST_CONSTEXPR_CXX20 bool tests() {
35+
// Test small vectors with different allocators
36+
test_vector_flip(3, std::allocator<bool>());
37+
test_vector_flip(3, min_allocator<bool>());
38+
test_vector_flip(3, test_allocator<bool>(5));
39+
40+
// Test large vectors with different allocators
41+
test_vector_flip(1000, std::allocator<bool>());
42+
test_vector_flip(1000, min_allocator<bool>());
43+
test_vector_flip(1000, test_allocator<bool>(5));
44+
45+
return true;
46+
}
47+
48+
int main(int, char**) {
49+
tests();
50+
#if TEST_STD_VER >= 20
51+
static_assert(tests());
52+
#endif
53+
return 0;
54+
}

0 commit comments

Comments
 (0)