[libcxx-commits] [libcxx] [libc++] Simplify vector<bool>::flip() and add new tests (PR #119607)
Peng Liu via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Dec 16 08:40:15 PST 2024
https://github.com/winner245 updated https://github.com/llvm/llvm-project/pull/119607
>From 55deea07f006f9e56a9f6c0bf6172da09ec833c3 Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Wed, 11 Dec 2024 14:25:56 -0500
Subject: [PATCH 1/3] Simplify vector<bool>::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 36eb7f350ac406..1021465a9325b9 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<bool, _Allocator>::resize(size_type __
template <class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<bool, _Allocator>::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 <class _Allocator>
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 00000000000000..5be52bffc5ffb5
--- /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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// flip()
+
+#include <cassert>
+#include <vector>
+
+#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<bool> 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<bool, min_allocator<bool> > 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<bool, test_allocator<bool> > v(test_allocator<bool>(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<bool> v(1000);
+ for (std::size_t i = 0; i < v.size(); ++i)
+ v[i] = i & 1;
+ std::vector<bool> original = v;
+ v.flip();
+ for (size_t i = 0; i < v.size(); ++i) {
+ assert(v[i] == !original[i]);
+ }
+ }
+ {
+ std::vector<bool, min_allocator<bool> > v(1000, false, min_allocator<bool>());
+ for (std::size_t i = 0; i < v.size(); ++i)
+ v[i] = i & 1;
+ std::vector<bool, min_allocator<bool> > 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<bool, test_allocator<bool> > v(1000, false, test_allocator<bool>(5));
+ for (std::size_t i = 0; i < v.size(); ++i)
+ v[i] = i & 1;
+ std::vector<bool, test_allocator<bool> > 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 bcbc121fce284cd514473f645cf8cfc9c9cdcc7e Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
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 1021465a9325b9..d6574596802497 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<bool, _Allocator>::resize(size_type __
template <class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<bool, _Allocator>::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 <class _Allocator>
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 5be52bffc5ffb5..2c3d4c8f53fdff 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 @@
// <vector>
-// flip()
+// void flip();
#include <cassert>
#include <vector>
>From 36a146826b905402d74b7ab1cf6677b56b0e3774 Mon Sep 17 00:00:00 2001
From: Peng Liu <winner245 at hotmail.com>
Date: Sat, 14 Dec 2024 08:02:37 -0500
Subject: [PATCH 3/3] Refactor test file
---
.../sequences/vector.bool/flip.pass.cpp | 100 ++++++------------
1 file changed, 31 insertions(+), 69 deletions(-)
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 2c3d4c8f53fdff..44a60f7a29a1fe 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,51 @@
// void flip();
#include <cassert>
+#include <memory>
#include <vector>
#include "min_allocator.h"
#include "test_allocator.h"
#include "test_macros.h"
+template <typename Allocator = std::allocator<bool> >
+TEST_CONSTEXPR_CXX20 void test_small_vector_flip(Allocator a) {
+ bool b[] = {true, false, true};
+ std::vector<bool, Allocator> v(b, b + 3, a);
+ v.flip();
+ assert(!v[0] && v[1] && !v[2]);
+}
+
+template <typename Allocator = std::allocator<bool> >
+TEST_CONSTEXPR_CXX20 void test_large_vector_flip(Allocator a) {
+ std::vector<bool, Allocator > v(1000, false, a);
+ for (std::size_t i = 0; i < v.size(); ++i)
+ v[i] = i & 1;
+ std::vector<bool, Allocator > original = v;
+ v.flip();
+ for (size_t i = 0; i < v.size(); ++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<bool> 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<bool, min_allocator<bool> > 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<bool, test_allocator<bool> > v(test_allocator<bool>(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_small_vector_flip(std::allocator<bool>());
+ test_small_vector_flip(min_allocator<bool>());
+ test_small_vector_flip(test_allocator<bool>(5));
- //
- // Testing flip() function with larger vectors
- //
- {
- std::vector<bool> v(1000);
- for (std::size_t i = 0; i < v.size(); ++i)
- v[i] = i & 1;
- std::vector<bool> original = v;
- v.flip();
- for (size_t i = 0; i < v.size(); ++i) {
- assert(v[i] == !original[i]);
- }
- }
- {
- std::vector<bool, min_allocator<bool> > v(1000, false, min_allocator<bool>());
- for (std::size_t i = 0; i < v.size(); ++i)
- v[i] = i & 1;
- std::vector<bool, min_allocator<bool> > 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<bool, test_allocator<bool> > v(1000, false, test_allocator<bool>(5));
- for (std::size_t i = 0; i < v.size(); ++i)
- v[i] = i & 1;
- std::vector<bool, test_allocator<bool> > 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_large_vector_flip(std::allocator<bool>());
+ test_large_vector_flip(min_allocator<bool>());
+ test_large_vector_flip(test_allocator<bool>(5));
return true;
}
int main(int, char**) {
tests();
-#if TEST_STD_VER > 17
+#if TEST_STD_VER >= 20
static_assert(tests());
#endif
return 0;
More information about the libcxx-commits
mailing list