Skip to content

Commit 56379b2

Browse files
authored
Simplify flip() for std::bitset (llvm#120807)
This PR simplifies the internal bitwise logic of the `flip()` function for `std::bitset`.
1 parent 0f6240c commit 56379b2

File tree

3 files changed

+37
-17
lines changed

3 files changed

+37
-17
lines changed

libcxx/include/bitset

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -329,12 +329,10 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void __bitset<_N_words, _Siz
329329
for (; __n >= __bits_per_word; ++__p, __n -= __bits_per_word)
330330
*__p = ~*__p;
331331
// do last partial word
332-
if (__n > 0) {
333-
__storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
334-
__storage_type __b = *__p & __m;
335-
*__p &= ~__m;
336-
*__p |= ~__b & __m;
337-
}
332+
// Ensure trailing padding bits are zeroed as part of the ABI for consistent hashing behavior. std::hash<bitset>
333+
// assumes trailing bits are zeroed; otherwise, identical bitsets could hash differently.
334+
if (__n > 0)
335+
*__p ^= (__storage_type(1) << __n) - 1;
338336
}
339337

340338
template <size_t _N_words, size_t _Size>
@@ -514,9 +512,7 @@ __bitset<1, _Size>::operator^=(const __bitset& __v) _NOEXCEPT {
514512

515513
template <size_t _Size>
516514
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void __bitset<1, _Size>::flip() _NOEXCEPT {
517-
__storage_type __m = ~__storage_type(0) >> (__bits_per_word - _Size);
518-
__first_ = ~__first_;
519-
__first_ &= __m;
515+
__first_ ^= ~__storage_type(0) >> (__bits_per_word - _Size);
520516
}
521517

522518
template <size_t _Size>

libcxx/test/std/utilities/template.bitset/bitset.members/flip_all.pass.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,21 @@
1818

1919
template <std::size_t N>
2020
TEST_CONSTEXPR_CXX23 void test_flip_all() {
21-
std::vector<std::bitset<N> > const cases = get_test_cases<N>();
22-
for (std::size_t c = 0; c != cases.size(); ++c) {
23-
std::bitset<N> v1 = cases[c];
24-
std::bitset<N> v2 = v1;
25-
v2.flip();
26-
for (std::size_t i = 0; i < v1.size(); ++i)
27-
assert(v2[i] == ~v1[i]);
28-
}
21+
std::vector<std::bitset<N> > const cases = get_test_cases<N>();
22+
for (std::size_t c = 0; c != cases.size(); ++c) {
23+
std::bitset<N> v1 = cases[c];
24+
std::bitset<N> v2 = v1;
25+
v2.flip();
26+
for (std::size_t i = 0; i < v1.size(); ++i)
27+
assert(v2[i] == ~v1[i]);
28+
}
2929
}
3030

3131
TEST_CONSTEXPR_CXX23 bool test() {
3232
test_flip_all<0>();
3333
test_flip_all<1>();
34+
test_flip_all<2>();
35+
test_flip_all<5>();
3436
test_flip_all<31>();
3537
test_flip_all<32>();
3638
test_flip_all<33>();

libcxx/test/std/utilities/template.bitset/bitset_test_cases.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,28 @@ TEST_CONSTEXPR_CXX23 inline std::vector<std::bitset<2> > get_test_cases<2>() {
4343
return cases;
4444
}
4545

46+
template <>
47+
TEST_CONSTEXPR_CXX23 inline std::vector<std::bitset<5> > get_test_cases<5>() {
48+
std::vector<std::bitset<5> > cases;
49+
cases.push_back(std::bitset<5>("00000"));
50+
cases.push_back(std::bitset<5>("00001"));
51+
cases.push_back(std::bitset<5>("10000"));
52+
cases.push_back(std::bitset<5>("00010"));
53+
cases.push_back(std::bitset<5>("01000"));
54+
cases.push_back(std::bitset<5>("00011"));
55+
cases.push_back(std::bitset<5>("11000"));
56+
cases.push_back(std::bitset<5>("00100"));
57+
cases.push_back(std::bitset<5>("11011"));
58+
cases.push_back(std::bitset<5>("00101"));
59+
cases.push_back(std::bitset<5>("10100"));
60+
cases.push_back(std::bitset<5>("00110"));
61+
cases.push_back(std::bitset<5>("01100"));
62+
cases.push_back(std::bitset<5>("00111"));
63+
cases.push_back(std::bitset<5>("11100"));
64+
cases.push_back(std::bitset<5>("11111"));
65+
return cases;
66+
}
67+
4668
template <>
4769
TEST_CONSTEXPR_CXX23 inline std::vector<std::bitset<31> > get_test_cases<31>() {
4870
std::vector<std::bitset<31> > cases;

0 commit comments

Comments
 (0)