From bb31bba77d25c690df461d839556366e39ce5361 Mon Sep 17 00:00:00 2001 From: Peng Liu Date: Wed, 11 Dec 2024 14:25:56 -0500 Subject: [PATCH 1/3] Simplify vector::flip() and add new tests --- libcxx/include/__vector/vector_bool.h | 12 +-- .../sequences/vector.bool/flip.pass.cpp | 100 ++++++++++++++++++ 2 files changed, 104 insertions(+), 8 deletions(-) create mode 100644 libcxx/test/std/containers/sequences/vector.bool/flip.pass.cpp diff --git a/libcxx/include/__vector/vector_bool.h b/libcxx/include/__vector/vector_bool.h index 36eb7f350ac40..1021465a9325b 100644 --- a/libcxx/include/__vector/vector_bool.h +++ b/libcxx/include/__vector/vector_bool.h @@ -1049,18 +1049,14 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::resize(size_type __ template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::flip() _NOEXCEPT { - // do middle whole words + // Process the whole words in the front size_type __n = __size_; __storage_pointer __p = __begin_; for (; __n >= __bits_per_word; ++__p, __n -= __bits_per_word) *__p = ~*__p; - // do last partial word - if (__n > 0) { - __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); - __storage_type __b = *__p & __m; - *__p &= ~__m; - *__p |= ~__b & __m; - } + // Process the last partial word, if it exists + if (__n > 0) + *__p ^= ~__storage_type(0) >> (__bits_per_word - __n); } template diff --git a/libcxx/test/std/containers/sequences/vector.bool/flip.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/flip.pass.cpp new file mode 100644 index 0000000000000..5be52bffc5ffb --- /dev/null +++ b/libcxx/test/std/containers/sequences/vector.bool/flip.pass.cpp @@ -0,0 +1,100 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// flip() + +#include +#include + +#include "min_allocator.h" +#include "test_allocator.h" +#include "test_macros.h" + +TEST_CONSTEXPR_CXX20 bool tests() { + // + // Testing flip() function with small vectors and various allocators + // + { + std::vector v; + v.push_back(true); + v.push_back(false); + v.push_back(true); + v.flip(); + assert(!v[0]); + assert(v[1]); + assert(!v[2]); + } + { + std::vector > v; + v.push_back(true); + v.push_back(false); + v.push_back(true); + v.flip(); + assert(!v[0]); + assert(v[1]); + assert(!v[2]); + } + { + std::vector > v(test_allocator(5)); + v.push_back(true); + v.push_back(false); + v.push_back(true); + v.flip(); + assert(!v[0]); + assert(v[1]); + assert(!v[2]); + } + + // + // Testing flip() function with larger vectors + // + { + std::vector v(1000); + for (std::size_t i = 0; i < v.size(); ++i) + v[i] = i & 1; + std::vector original = v; + v.flip(); + for (size_t i = 0; i < v.size(); ++i) { + assert(v[i] == !original[i]); + } + } + { + std::vector > v(1000, false, min_allocator()); + for (std::size_t i = 0; i < v.size(); ++i) + v[i] = i & 1; + std::vector > original = v; + v.flip(); + for (size_t i = 0; i < v.size(); ++i) + assert(v[i] == !original[i]); + v.flip(); + assert(v == original); + } + { + std::vector > v(1000, false, test_allocator(5)); + for (std::size_t i = 0; i < v.size(); ++i) + v[i] = i & 1; + std::vector > original = v; + v.flip(); + for (size_t i = 0; i < v.size(); ++i) + assert(v[i] == !original[i]); + v.flip(); + assert(v == original); + } + + return true; +} + +int main(int, char**) { + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; +} From a1d4c0c6a92f0cacd121cc2b237ca4028206d238 Mon Sep 17 00:00:00 2001 From: Peng Liu Date: Thu, 12 Dec 2024 11:22:17 -0500 Subject: [PATCH 2/3] Unconditionally flip the last word --- libcxx/include/__vector/vector_bool.h | 9 +++------ .../std/containers/sequences/vector.bool/flip.pass.cpp | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/libcxx/include/__vector/vector_bool.h b/libcxx/include/__vector/vector_bool.h index 1021465a9325b..d657459680249 100644 --- a/libcxx/include/__vector/vector_bool.h +++ b/libcxx/include/__vector/vector_bool.h @@ -1049,14 +1049,11 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::resize(size_type __ template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::flip() _NOEXCEPT { - // Process the whole words in the front - size_type __n = __size_; + // Flip each storage word entirely, including the last potentially partial word. + // The unused bits in the last word are safe to flip as they won't be accessed. __storage_pointer __p = __begin_; - for (; __n >= __bits_per_word; ++__p, __n -= __bits_per_word) + for (size_type __n = __external_cap_to_internal(size()); __n; ++__p, --__n) *__p = ~*__p; - // Process the last partial word, if it exists - if (__n > 0) - *__p ^= ~__storage_type(0) >> (__bits_per_word - __n); } template diff --git a/libcxx/test/std/containers/sequences/vector.bool/flip.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/flip.pass.cpp index 5be52bffc5ffb..2c3d4c8f53fdf 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/flip.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/flip.pass.cpp @@ -8,7 +8,7 @@ // -// flip() +// void flip(); #include #include From 4c38c1ef77f935e0feb75aa2f98eabf34e45a51a Mon Sep 17 00:00:00 2001 From: Peng Liu Date: Sat, 14 Dec 2024 08:02:37 -0500 Subject: [PATCH 3/3] Refactor test file --- libcxx/include/__vector/vector_bool.h | 2 +- .../sequences/vector.bool/flip.pass.cpp | 92 +++++-------------- 2 files changed, 24 insertions(+), 70 deletions(-) diff --git a/libcxx/include/__vector/vector_bool.h b/libcxx/include/__vector/vector_bool.h index d657459680249..525fc35b26cc9 100644 --- a/libcxx/include/__vector/vector_bool.h +++ b/libcxx/include/__vector/vector_bool.h @@ -1052,7 +1052,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::flip() _NOEXCEPT { // Flip each storage word entirely, including the last potentially partial word. // The unused bits in the last word are safe to flip as they won't be accessed. __storage_pointer __p = __begin_; - for (size_type __n = __external_cap_to_internal(size()); __n; ++__p, --__n) + for (size_type __n = __external_cap_to_internal(size()); __n != 0; ++__p, --__n) *__p = ~*__p; } diff --git a/libcxx/test/std/containers/sequences/vector.bool/flip.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/flip.pass.cpp index 2c3d4c8f53fdf..f8f575cdc0e21 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/flip.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/flip.pass.cpp @@ -11,89 +11,43 @@ // void flip(); #include +#include #include #include "min_allocator.h" #include "test_allocator.h" #include "test_macros.h" +template +TEST_CONSTEXPR_CXX20 void test_vector_flip(std::size_t n, Allocator a) { + std::vector v(n, false, a); + for (std::size_t i = 0; i < n; ++i) + v[i] = i & 1; + std::vector original = v; + v.flip(); + for (size_t i = 0; i < n; ++i) + assert(v[i] == !original[i]); + v.flip(); + assert(v == original); +} + TEST_CONSTEXPR_CXX20 bool tests() { - // - // Testing flip() function with small vectors and various allocators - // - { - std::vector v; - v.push_back(true); - v.push_back(false); - v.push_back(true); - v.flip(); - assert(!v[0]); - assert(v[1]); - assert(!v[2]); - } - { - std::vector > v; - v.push_back(true); - v.push_back(false); - v.push_back(true); - v.flip(); - assert(!v[0]); - assert(v[1]); - assert(!v[2]); - } - { - std::vector > v(test_allocator(5)); - v.push_back(true); - v.push_back(false); - v.push_back(true); - v.flip(); - assert(!v[0]); - assert(v[1]); - assert(!v[2]); - } + // Test small vectors with different allocators + test_vector_flip(3, std::allocator()); + test_vector_flip(3, min_allocator()); + test_vector_flip(3, test_allocator(5)); - // - // Testing flip() function with larger vectors - // - { - std::vector v(1000); - for (std::size_t i = 0; i < v.size(); ++i) - v[i] = i & 1; - std::vector original = v; - v.flip(); - for (size_t i = 0; i < v.size(); ++i) { - assert(v[i] == !original[i]); - } - } - { - std::vector > v(1000, false, min_allocator()); - for (std::size_t i = 0; i < v.size(); ++i) - v[i] = i & 1; - std::vector > original = v; - v.flip(); - for (size_t i = 0; i < v.size(); ++i) - assert(v[i] == !original[i]); - v.flip(); - assert(v == original); - } - { - std::vector > v(1000, false, test_allocator(5)); - for (std::size_t i = 0; i < v.size(); ++i) - v[i] = i & 1; - std::vector > original = v; - v.flip(); - for (size_t i = 0; i < v.size(); ++i) - assert(v[i] == !original[i]); - v.flip(); - assert(v == original); - } + // Test large vectors with different allocators + test_vector_flip(1000, std::allocator()); + test_vector_flip(1000, min_allocator()); + test_vector_flip(1000, test_allocator(5)); return true; } int main(int, char**) { tests(); -#if TEST_STD_VER > 17 +#if TEST_STD_VER >= 20 static_assert(tests()); #endif return 0;