From d3fdd4dc10fa150dd961bf3fccea95de458015a8 Mon Sep 17 00:00:00 2001 From: Peter McLean Date: Wed, 25 Jun 2025 13:24:47 -0400 Subject: [PATCH 01/13] Pipecleaning policy and casting issues --- include/bitlib/bit-algorithms/accumulate.hpp | 1 - include/bitlib/bit-containers/bit_array.hpp | 10 +++--- .../bit_array_dynamic_extent.hpp | 25 +++++++------ .../bitlib/bit-containers/bit_array_ref.hpp | 4 +-- include/bitlib/bit-containers/bit_span.hpp | 36 +++++++++---------- include/bitlib/bit-iterator/bit_reference.hpp | 6 ++++ 6 files changed, 45 insertions(+), 37 deletions(-) diff --git a/include/bitlib/bit-algorithms/accumulate.hpp b/include/bitlib/bit-algorithms/accumulate.hpp index f01c0833..52887fda 100644 --- a/include/bitlib/bit-algorithms/accumulate.hpp +++ b/include/bitlib/bit-algorithms/accumulate.hpp @@ -90,7 +90,6 @@ constexpr auto accumulate_while( BinaryOperationSubword binary_op_subword) { using word_type = typename bit_iterator::word_type; using size_type = typename bit_iterator::size_type; - using difference_type = typename bit_iterator::difference_type; constexpr size_type digits = bitsof(); size_type total_bits_to_op = distance(first, last); diff --git a/include/bitlib/bit-containers/bit_array.hpp b/include/bitlib/bit-containers/bit_array.hpp index 23263fc0..e90f8fbf 100644 --- a/include/bitlib/bit-containers/bit_array.hpp +++ b/include/bitlib/bit-containers/bit_array.hpp @@ -39,7 +39,7 @@ template >, T>, - typename Policy = policy::typical> + typename Policy = policy::typical>> class array; template >, - typename Policy = policy::typical> + typename Policy = policy::typical>> using bit_array = array; namespace detail { @@ -108,10 +108,10 @@ class array : public array_base, T, N, W, Policy, detail::array_i this->from_integral(integral); } - constexpr array(const array& other) noexcept + constexpr array(const array& other) noexcept : storage(other.storage) {} - constexpr array(const array&& other) noexcept + constexpr array(const array&& other) noexcept : storage(other.storage) {} constexpr array(const bit_sized_range auto& other) { @@ -209,7 +209,7 @@ class array : public array_base, T, N, W, Policy, detail::array_i /* * Operations */ - constexpr void swap(array& other) noexcept { + constexpr void swap(array& other) noexcept { std::swap(this->storage, other.storage); } diff --git a/include/bitlib/bit-containers/bit_array_dynamic_extent.hpp b/include/bitlib/bit-containers/bit_array_dynamic_extent.hpp index 57907fbd..90845d9d 100644 --- a/include/bitlib/bit-containers/bit_array_dynamic_extent.hpp +++ b/include/bitlib/bit-containers/bit_array_dynamic_extent.hpp @@ -58,7 +58,10 @@ class array private: using word_type_ptr = word_type*; + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wsizeof-pointer-div" static const size_type FixedWords = sizeof(word_type_ptr) / sizeof(word_type); + #pragma GCC diagnostic pop static const size_type FixedBits = FixedWords * bitsof(); const size_type m_size; @@ -181,15 +184,15 @@ class array } constexpr array(const bit_sized_range auto& other, const Allocator& allocator = Allocator()) - : array(other.size(), allocator, detail::uninitialized) { + : m_size(other.size()), storage(Words(size()), allocator, detail::uninitialized) { ::bit::copy(other.begin(), other.end(), this->begin()); } - constexpr array(array&& other) + constexpr array(array&& other) : m_size(other.size()), storage(Words(size()), std::move(other.storage)) { } - constexpr array(array&& other, const Allocator& allocator) + constexpr array(array&& other, const Allocator& allocator) : m_size(other.size()), storage(Words(size()), std::move(other.storage), allocator) { } @@ -202,7 +205,7 @@ class array #if 0 No known conversion from bool to bit_value bit_value has explicit constructor from bool to bit_value so this doesnt work - constexpr array::array(const std::initializer_list init) + constexpr array::array(const std::initializer_list init) : storage(std::make_unique(Words(init.size()))), m_size(init.size()) { std::copy(init.begin(), init.end(), this->begin()); @@ -231,9 +234,9 @@ class array /* * Assignment */ - constexpr array& operator=(const array& other) { + constexpr array& operator=(const array& other) { if (nullptr == data() || size() != other.size()) { - throw std::invalid_argument("Cannot reassign array size"); + throw std::invalid_argument("Cannot reassign array size"); } if (this == &other) [[unlikely]] { return *this; @@ -242,7 +245,7 @@ class array return *this; } - constexpr array& operator=(const bit_sized_range auto& other) { + constexpr array& operator=(const bit_sized_range auto& other) { if (other.size() != this->size()) [[unlikely]] { throw std::invalid_argument("other bit_range contains an invalid number of bits for array."); } @@ -250,11 +253,11 @@ class array return *this; }; - constexpr array& operator=(array&& other) { + constexpr array& operator=(array&& other) { if (nullptr == data() || size() != other.size()) { - throw std::invalid_argument("Cannot reassign array size"); + throw std::invalid_argument("Cannot reassign array size"); } - array temp(std::move(other)); + array temp(std::move(other)); swap(temp); return *this; } @@ -307,7 +310,7 @@ class array /* * Operations */ - constexpr void swap(array& other) noexcept { + constexpr void swap(array& other) noexcept { assert(size() == other.size()); if (size() > FixedBits) { std::swap(this->storage.pointer, other.storage.pointer); diff --git a/include/bitlib/bit-containers/bit_array_ref.hpp b/include/bitlib/bit-containers/bit_array_ref.hpp index 5706b6e0..78ef8497 100644 --- a/include/bitlib/bit-containers/bit_array_ref.hpp +++ b/include/bitlib/bit-containers/bit_array_ref.hpp @@ -25,10 +25,10 @@ namespace bit { -template > +template >> class array_ref; -template > +template >> using bit_array_ref = array_ref; namespace detail { diff --git a/include/bitlib/bit-containers/bit_span.hpp b/include/bitlib/bit-containers/bit_span.hpp index d7afe202..6241dd1c 100644 --- a/include/bitlib/bit-containers/bit_span.hpp +++ b/include/bitlib/bit-containers/bit_span.hpp @@ -34,7 +34,7 @@ struct bit_span_storage { bit_span_storage(std::size_t size) : size_(size) {} }; -template > +template >> class bit_span : private bit_span_storage { public: using word_type = WordType; @@ -125,22 +125,22 @@ class bit_span : private bit_span_storage { // Creates a subspan starting at offset with count bits. template - constexpr auto subspan() const noexcept -> bit_span()>; - constexpr bit_span subspan(size_type offset, size_type count = std::dynamic_extent) const noexcept + constexpr auto subspan() const noexcept -> bit_span(), Policy>; + constexpr bit_span subspan(size_type offset, size_type count = std::dynamic_extent) const noexcept requires(Extent == std::dynamic_extent); constexpr bit_array_ref operator()(size_type begin, size_type end) const noexcept; template - constexpr bit_span first() const noexcept + constexpr bit_span first() const noexcept requires(NewExtent != std::dynamic_extent); - constexpr bit_span first(size_type offset) const noexcept + constexpr bit_span first(size_type offset) const noexcept requires(Extent == std::dynamic_extent); template - constexpr bit_span last() const noexcept + constexpr bit_span last() const noexcept requires(RevOffset != std::dynamic_extent); - constexpr bit_span last(size_type offset) const noexcept + constexpr bit_span last(size_type offset) const noexcept requires(Extent == std::dynamic_extent); }; @@ -284,8 +284,8 @@ constexpr bit_span::iterator bit_span template constexpr auto bit_span::subspan() const noexcept - -> bit_span()> { - using NewSpanType = bit_span()>; + -> bit_span(), Policy> { + using NewSpanType = bit_span(), Policy>; if constexpr (NewExtent == std::dynamic_extent) { return NewSpanType(begin() + NewOffset, size() - NewOffset); @@ -296,11 +296,11 @@ constexpr auto bit_span::subspan() const noexcept // Creates a subspan starting at offset with count bits. template -constexpr bit_span bit_span::subspan(size_type offset, size_type count) const noexcept +constexpr bit_span bit_span::subspan(size_type offset, size_type count) const noexcept requires(Extent == std::dynamic_extent) { size_type new_count = (count == std::dynamic_extent) ? size() - offset : count; - return bit_span(begin() + offset, new_count); + return bit_span(begin() + offset, new_count); } template @@ -310,29 +310,29 @@ constexpr bit_array_ref bit_span::op template template -constexpr bit_span bit_span::first() const noexcept +constexpr bit_span bit_span::first() const noexcept requires(NewExtent != std::dynamic_extent) { - return bit_span(data_); + return bit_span(data_); } template -constexpr bit_span bit_span::first(size_type offset) const noexcept +constexpr bit_span bit_span::first(size_type offset) const noexcept requires(Extent == std::dynamic_extent) { - return bit_span(begin() + offset); + return bit_span(begin() + offset); } template template -constexpr bit_span bit_span::last() const noexcept +constexpr bit_span bit_span::last() const noexcept requires(RevOffset != std::dynamic_extent) { - return bit_span(begin() + size() - RevOffset); + return bit_span(begin() + size() - RevOffset); } template -constexpr bit_span bit_span::last(size_type offset) const noexcept +constexpr bit_span bit_span::last(size_type offset) const noexcept requires(Extent == std::dynamic_extent) { } diff --git a/include/bitlib/bit-iterator/bit_reference.hpp b/include/bitlib/bit-iterator/bit_reference.hpp index 55fc4bf7..69faa83f 100644 --- a/include/bitlib/bit-iterator/bit_reference.hpp +++ b/include/bitlib/bit-iterator/bit_reference.hpp @@ -80,6 +80,7 @@ class bit_reference { // Access public: constexpr bit_pointer operator&() const noexcept; + constexpr bit_pointer operator&() noexcept; // Swap members public: @@ -227,6 +228,11 @@ template constexpr bit_pointer> bit_reference::operator&() const noexcept { return bit_pointer(&_ref, _tzcnt(_mask)); } + +template +constexpr bit_pointer> bit_reference::operator&() noexcept { + return bit_pointer(&_ref, _tzcnt(_mask)); +} // -------------------------------------------------------------------------- // From b5e9d7ed61ebdb17ad0d7c3b28c8fcdedc775beb Mon Sep 17 00:00:00 2001 From: Peter McLean Date: Wed, 25 Jun 2025 13:56:58 -0400 Subject: [PATCH 02/13] Fix policy/conversion issues --- include/bitlib/bit-containers/bit_array_base.hpp | 4 ++-- include/bitlib/bit-containers/bit_policy.hpp | 16 ++++------------ 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/include/bitlib/bit-containers/bit_array_base.hpp b/include/bitlib/bit-containers/bit_array_base.hpp index af75d2bc..4f386449 100644 --- a/include/bitlib/bit-containers/bit_array_base.hpp +++ b/include/bitlib/bit-containers/bit_array_base.hpp @@ -193,7 +193,7 @@ class array_base { ::bit::copy(derived().begin(), end(), bit_pointer(&integral)); } if (derived().size() < bitsof()) { - Policy::extension::template to_integral(derived(), integral); + Policy::extension::template to_integral(derived(), integral, detail::uninitialized); } } else { if constexpr (N > bitsof()) { @@ -202,7 +202,7 @@ class array_base { ::bit::copy(derived().begin(), end(), bit_pointer(&integral)); } if constexpr (N < bitsof()) { - Policy::extension::template to_integral(derived(), integral); + Policy::extension::template to_integral(derived(), integral, detail::uninitialized); } } diff --git a/include/bitlib/bit-containers/bit_policy.hpp b/include/bitlib/bit-containers/bit_policy.hpp index 03943f0e..fddc8104 100644 --- a/include/bitlib/bit-containers/bit_policy.hpp +++ b/include/bitlib/bit-containers/bit_policy.hpp @@ -64,13 +64,9 @@ struct sign_extend { constexpr static void to_integral(const bit_sized_range auto& value, U& integral, detail::uninitialized_t) noexcept { bit_pointer integral_begin(&integral); if constexpr (N == std::dynamic_extent) { - if constexpr (std::is_signed_v) { - ::bit::fill(integral_begin + value.size(), integral_begin + bitsof(), value.last()[-1]); - } + ::bit::fill(integral_begin + value.size(), integral_begin + bitsof(), value.end()[-1]); } else { - if constexpr (std::is_signed_v) { - ::bit::fill(integral_begin + N, integral_begin + bitsof(), value.begin()[N - 1]); - } + ::bit::fill(integral_begin + N, integral_begin + bitsof(), value.begin()[N - 1]); } } template @@ -92,13 +88,9 @@ struct sign_extend { template constexpr static void from_integral(bit_sized_range auto& value, const U& integral, detail::uninitialized_t) noexcept { if constexpr (N == std::dynamic_extent) { - if constexpr (std::is_signed_v) { - ::bit::fill(value.begin() + bitsof(), value.end(), (integral < 0) ? bit1 : bit0); - } + ::bit::fill(value.begin() + bitsof(), value.end(), (integral < 0) ? bit1 : bit0); } else { - if constexpr (std::is_signed_v) { - ::bit::fill(value.begin() + N, value.end(), (integral < 0) ? bit1 : bit0); - } + ::bit::fill(value.begin() + N, value.end(), (integral < 0) ? bit1 : bit0); } } }; From 79b7f866fdb63ac3b4d77bb46e58c8dc9d3d18cf Mon Sep 17 00:00:00 2001 From: Peter McLean Date: Fri, 27 Jun 2025 13:23:45 -0400 Subject: [PATCH 03/13] mdspan_accessor was templated incorrectly. bad constructor for bit_reference causes unexpected behavior --- include/bitlib/bit-algorithms/bit_algorithm.hpp | 2 +- include/bitlib/bit-algorithms/to_from_string.hpp | 5 ++++- include/bitlib/bit-containers/bit_mdspan_accessor.hpp | 2 +- include/bitlib/bit-containers/bit_vector.hpp | 3 ++- include/bitlib/bit-iterator/bit_reference.hpp | 5 ----- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/include/bitlib/bit-algorithms/bit_algorithm.hpp b/include/bitlib/bit-algorithms/bit_algorithm.hpp index 6266e640..af07236a 100644 --- a/include/bitlib/bit-algorithms/bit_algorithm.hpp +++ b/include/bitlib/bit-algorithms/bit_algorithm.hpp @@ -33,7 +33,7 @@ #include "rotate.hpp" #include "shift.hpp" #include "swap_ranges.hpp" -#include "to_string.hpp" +#include "to_from_string.hpp" #include "transform.hpp" #include "type_traits.hpp" // ========================================================================== // diff --git a/include/bitlib/bit-algorithms/to_from_string.hpp b/include/bitlib/bit-algorithms/to_from_string.hpp index faf98b0e..12454518 100644 --- a/include/bitlib/bit-algorithms/to_from_string.hpp +++ b/include/bitlib/bit-algorithms/to_from_string.hpp @@ -14,7 +14,7 @@ #include "bitlib/bit-algorithms/accumulate.hpp" #include "bitlib/bit-algorithms/count.hpp" -#include "bitlib/bit-containers/array_dynamic_extent.hpp" +#include "bitlib/bit-containers/bit_array_dynamic_extent.hpp" #include "bitlib/bit-containers/bit_vector.hpp" #include "bitlib/bit_concepts.hpp" @@ -81,6 +81,9 @@ constexpr std::string to_string(const bit_iterator& first, const int skip_leading_bits = meta.str_sign_extend_zeros ? 0 : count_msb(first, last, bit0); int str_len = (distance(first, last) - skip_leading_bits); + if (str_len == 0) { + return prefix + "0"; + } str_len += (0 != (str_len % base_bits)); std::string& str = prefix; str.resize(str.length() + str_len); diff --git a/include/bitlib/bit-containers/bit_mdspan_accessor.hpp b/include/bitlib/bit-containers/bit_mdspan_accessor.hpp index a948a117..e75048fe 100644 --- a/include/bitlib/bit-containers/bit_mdspan_accessor.hpp +++ b/include/bitlib/bit-containers/bit_mdspan_accessor.hpp @@ -18,7 +18,7 @@ template struct bit_default_accessor { using element_type = bit_value; using data_handle_type = bit_pointer; - using reference = bit_reference; + using reference = bit_reference; using offset_policy = bit_default_accessor; constexpr reference access(data_handle_type p, std::size_t i) const noexcept { return p[i]; diff --git a/include/bitlib/bit-containers/bit_vector.hpp b/include/bitlib/bit-containers/bit_vector.hpp index 147a62ea..cb5703d2 100644 --- a/include/bitlib/bit-containers/bit_vector.hpp +++ b/include/bitlib/bit-containers/bit_vector.hpp @@ -22,8 +22,9 @@ #include // Project sources #include "bitlib/bit-algorithms/bit_algorithm.hpp" -#include "bitlib/bit-iterator/bit.hpp" #include "bitlib/bit_concepts.hpp" +#include "bitlib/bit-containers/bit_array_ref.hpp" +#include "bitlib/bit-iterator/bit.hpp" // Third-party libraries // Miscellaneous diff --git a/include/bitlib/bit-iterator/bit_reference.hpp b/include/bitlib/bit-iterator/bit_reference.hpp index 69faa83f..6a706c6a 100644 --- a/include/bitlib/bit-iterator/bit_reference.hpp +++ b/include/bitlib/bit-iterator/bit_reference.hpp @@ -49,11 +49,6 @@ class bit_reference { // Lifecycle public: - template - requires(std::is_const_v> == std::is_const_v>) - constexpr bit_reference(const bit_reference& other) noexcept - : _ref(other._ref), _mask(other._mask) { - } constexpr bit_reference(const bit_reference& other) noexcept; explicit constexpr bit_reference(WordRef ref) noexcept; constexpr bit_reference(WordRef ref, size_type pos); From 1ed8f5b87d718edcc0007e4062eb2ace38eed67d Mon Sep 17 00:00:00 2001 From: Peter McLean Date: Fri, 27 Jun 2025 13:34:08 -0400 Subject: [PATCH 04/13] More missing policy templating --- include/bitlib/bit-containers/bit_array.hpp | 4 ++-- include/bitlib/bit-containers/bit_array_dynamic_extent.hpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/bitlib/bit-containers/bit_array.hpp b/include/bitlib/bit-containers/bit_array.hpp index e90f8fbf..af3a0b90 100644 --- a/include/bitlib/bit-containers/bit_array.hpp +++ b/include/bitlib/bit-containers/bit_array.hpp @@ -68,9 +68,9 @@ struct array_iterator_types { } // namespace detail template -class array : public array_base, T, N, W, Policy, detail::array_iterator_types> { +class array : public array_base, T, N, W, Policy, detail::array_iterator_types> { public: - using base = array_base, T, N, W, Policy, detail::array_iterator_types>; + using base = array_base, T, N, W, Policy, detail::array_iterator_types>; using base::end; using typename base::const_iterator; using typename base::const_pointer; diff --git a/include/bitlib/bit-containers/bit_array_dynamic_extent.hpp b/include/bitlib/bit-containers/bit_array_dynamic_extent.hpp index 90845d9d..ca128480 100644 --- a/include/bitlib/bit-containers/bit_array_dynamic_extent.hpp +++ b/include/bitlib/bit-containers/bit_array_dynamic_extent.hpp @@ -40,9 +40,9 @@ struct array_dextent_iterator_types { } // namespace detail template class array - : public array_base, T, std::dynamic_extent, W, Policy, detail::array_dextent_iterator_types> { + : public array_base, T, std::dynamic_extent, W, Policy, detail::array_dextent_iterator_types> { public: - using base = array_base, T, std::dynamic_extent, W, Policy, detail::array_dextent_iterator_types>; + using base = array_base, T, std::dynamic_extent, W, Policy, detail::array_dextent_iterator_types>; using base::end; using typename base::const_iterator; using typename base::const_pointer; From 9b967dcbef538293f62809e85d08998a34fab2bc Mon Sep 17 00:00:00 2001 From: Peter McLean Date: Fri, 27 Jun 2025 13:41:16 -0400 Subject: [PATCH 05/13] Correct static assert target class --- include/bitlib/bit-containers/bit_array_dynamic_extent.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/bitlib/bit-containers/bit_array_dynamic_extent.hpp b/include/bitlib/bit-containers/bit_array_dynamic_extent.hpp index ca128480..6ac6bcf1 100644 --- a/include/bitlib/bit-containers/bit_array_dynamic_extent.hpp +++ b/include/bitlib/bit-containers/bit_array_dynamic_extent.hpp @@ -322,8 +322,8 @@ class array } }; -static_assert(bit_range>, "array<> does not satisfy bit_contiguous_range concept!"); -static_assert(bit_sized_range>, "array<> does not satisfy bit_contiguous_sized_range concept!"); +static_assert(bit_range>, "array<> does not satisfy bit_contiguous_range concept!"); +static_assert(bit_sized_range>, "array<> does not satisfy bit_contiguous_sized_range concept!"); #ifdef CONTIGUOUS_RANGE static_assert(bit_contiguous_range>, "array<> does not satisfy bit_contiguous_range concept!"); static_assert(bit_contiguous_sized_range>, "array<> does not satisfy bit_contiguous_sized_range concept!"); From f5f5bad860299fbb29e3b194899913171d5e587a Mon Sep 17 00:00:00 2001 From: Peter McLean Date: Fri, 27 Jun 2025 13:56:19 -0400 Subject: [PATCH 06/13] Disable from_string temporarily as include DAG is misordered with it --- include/bitlib/bit-algorithms/to_from_string.hpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/include/bitlib/bit-algorithms/to_from_string.hpp b/include/bitlib/bit-algorithms/to_from_string.hpp index 12454518..4008e440 100644 --- a/include/bitlib/bit-algorithms/to_from_string.hpp +++ b/include/bitlib/bit-algorithms/to_from_string.hpp @@ -14,8 +14,6 @@ #include "bitlib/bit-algorithms/accumulate.hpp" #include "bitlib/bit-algorithms/count.hpp" -#include "bitlib/bit-containers/bit_array_dynamic_extent.hpp" -#include "bitlib/bit-containers/bit_vector.hpp" #include "bitlib/bit_concepts.hpp" namespace bit { @@ -81,9 +79,6 @@ constexpr std::string to_string(const bit_iterator& first, const int skip_leading_bits = meta.str_sign_extend_zeros ? 0 : count_msb(first, last, bit0); int str_len = (distance(first, last) - skip_leading_bits); - if (str_len == 0) { - return prefix + "0"; - } str_len += (0 != (str_len % base_bits)); std::string& str = prefix; str.resize(str.length() + str_len); @@ -112,6 +107,9 @@ constexpr std::string to_string(const bit_sized_range auto& bits, std::string pr return to_string(bits.begin(), bits.end(), prefix); } +/* +Commenting this out temporarily as the reference to bit_vector/bit_array messes up include dependency DAG + template , typename RandomAccessIt> constexpr void from_string( Policy, @@ -148,7 +146,7 @@ constexpr bit_vector<> from_string(const char* first, const char* last) { bits += base_bits; } if (bits) { - vec.append_range(array<>(bits, work)); + vec.append_range(bit_array<>(bits, work)); } } return vec; @@ -161,6 +159,7 @@ template constexpr bit_vector<> from_string(const std::string& str) { return from_string(str.c_str(), str.c_str() + str.length()); } +*/ } // namespace bit From c0c08e4f7c6b1b2c6848d10ed5bf6b101bbfd133 Mon Sep 17 00:00:00 2001 From: Peter McLean Date: Fri, 27 Jun 2025 17:56:11 -0400 Subject: [PATCH 07/13] Fix to_integral --- include/bitlib/bit-containers/bit_policy.hpp | 12 ++++++++++-- .../bitlib/bit-iterator/bit_word_pointer_adapter.hpp | 2 +- test/src/fixtures.hpp | 2 +- test/src/test-iterator_adapter.cpp | 2 +- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/include/bitlib/bit-containers/bit_policy.hpp b/include/bitlib/bit-containers/bit_policy.hpp index fddc8104..844ecd93 100644 --- a/include/bitlib/bit-containers/bit_policy.hpp +++ b/include/bitlib/bit-containers/bit_policy.hpp @@ -64,9 +64,17 @@ struct sign_extend { constexpr static void to_integral(const bit_sized_range auto& value, U& integral, detail::uninitialized_t) noexcept { bit_pointer integral_begin(&integral); if constexpr (N == std::dynamic_extent) { - ::bit::fill(integral_begin + value.size(), integral_begin + bitsof(), value.end()[-1]); + if constexpr (std::is_signed_v) { + ::bit::fill(integral_begin + value.size(), integral_begin + bitsof(), value.end()[-1]); + } else { + ::bit::fill(integral_begin + value.size(), integral_begin + bitsof(), bit0); + } } else { - ::bit::fill(integral_begin + N, integral_begin + bitsof(), value.begin()[N - 1]); + if constexpr (std::is_signed_v) { + ::bit::fill(integral_begin + value.size(), integral_begin + bitsof(), value.begin()[N - 1]); + } else { + ::bit::fill(integral_begin + value.size(), integral_begin + bitsof(), bit0); + } } } template diff --git a/include/bitlib/bit-iterator/bit_word_pointer_adapter.hpp b/include/bitlib/bit-iterator/bit_word_pointer_adapter.hpp index 797fcd1e..d9c207a6 100644 --- a/include/bitlib/bit-iterator/bit_word_pointer_adapter.hpp +++ b/include/bitlib/bit-iterator/bit_word_pointer_adapter.hpp @@ -202,7 +202,7 @@ constexpr auto operator-( auto main = (lhs._source - rhs._source); return main * static_cast>(bit_word_pointer_adapter::ratio) + (static_cast(lhs._index) - static_cast(rhs._index)); } else { - // “small→large” mode: each base‐step is 1 small word, but difference is in big words: + // "small→large" mode: each base‐step is 1 small word, but difference is in big words: auto small_diff = (lhs._source - rhs._source); return small_diff / static_cast>(bit_word_pointer_adapter::ratio); } diff --git a/test/src/fixtures.hpp b/test/src/fixtures.hpp index 099d038f..515dbeb0 100644 --- a/test/src/fixtures.hpp +++ b/test/src/fixtures.hpp @@ -231,7 +231,7 @@ class MixedDoubleRangeTest : public testing::Test { bitvecs.push_back(bv); boolvecs.push_back(boolvec_from_bitvec(bv)); } - // “big” runs around (big_size-1)*digits +/-4 + // "big" runs around (big_size-1)*digits +/-4 const auto max_digits = std::max(bit::bitsof(), bit::bitsof()); for (int i = -4; i < 4; ++i) { size_t cont_size = big_bit_size - max_digits + i; diff --git a/test/src/test-iterator_adapter.cpp b/test/src/test-iterator_adapter.cpp index f8be23d5..7607d420 100644 --- a/test/src/test-iterator_adapter.cpp +++ b/test/src/test-iterator_adapter.cpp @@ -23,7 +23,7 @@ // // GoogleTest suite for bit::bit_word_pointer_adapter. -// Covers both “big‐to‐small” and “small‐to‐large” modes. +// Covers both "big‐to‐small" and "small‐to‐large" modes. // // Assumes a little‐endian platform (so that reinterpret_cast<…> of bytes From 5e9ce7585167c46478ac1d2312694f6ab5770e52 Mon Sep 17 00:00:00 2001 From: Peter McLean Date: Sat, 5 Jul 2025 22:27:17 -0400 Subject: [PATCH 08/13] compile-time array_ref extent. word accessor --- include/bitlib/bit-containers/bit_array.hpp | 5 +- .../bitlib/bit-containers/bit_array_base.hpp | 15 ++-- .../bit_array_dynamic_extent.hpp | 40 +++++------ .../bitlib/bit-containers/bit_array_ref.hpp | 64 +++++++++-------- .../bit-containers/bit_mdspan_accessor.hpp | 26 +++++++ include/bitlib/bit-containers/bit_span.hpp | 6 +- include/bitlib/bit-iterator/bit_details.hpp | 28 ++++++++ test/src/test-mdspan.cpp | 69 +++++++++++++++++++ 8 files changed, 192 insertions(+), 61 deletions(-) diff --git a/include/bitlib/bit-containers/bit_array.hpp b/include/bitlib/bit-containers/bit_array.hpp index af3a0b90..d49e8e7c 100644 --- a/include/bitlib/bit-containers/bit_array.hpp +++ b/include/bitlib/bit-containers/bit_array.hpp @@ -68,10 +68,11 @@ struct array_iterator_types { } // namespace detail template -class array : public array_base, T, N, W, Policy, detail::array_iterator_types> { +class array : public array_base, T, N, W, false, Policy, detail::array_iterator_types> { public: - using base = array_base, T, N, W, Policy, detail::array_iterator_types>; + using base = array_base, T, N, W, false, Policy, detail::array_iterator_types>; using base::end; + using base::size; using typename base::const_iterator; using typename base::const_pointer; using typename base::const_reference; diff --git a/include/bitlib/bit-containers/bit_array_base.hpp b/include/bitlib/bit-containers/bit_array_base.hpp index 4f386449..0fe78af2 100644 --- a/include/bitlib/bit-containers/bit_array_base.hpp +++ b/include/bitlib/bit-containers/bit_array_base.hpp @@ -28,7 +28,7 @@ namespace bit { -template +template class array_ref; template -class array_base { +template +class array_base : public detail::container_size_storage { protected: constexpr Derived& derived() noexcept { return static_cast(*this); @@ -73,6 +73,11 @@ class array_base { using iterator = Iterators::iterator; using const_iterator = Iterators::const_iterator; + constexpr array_base() noexcept : detail::container_size_storage() {} + constexpr array_base(const size_type& size) noexcept + requires(N == std::dynamic_extent) + : detail::container_size_storage(size) {} + // Element access constexpr reference operator[](size_type pos) { return derived().begin()[pos]; @@ -163,14 +168,14 @@ class array_base { * @brief Slice operations - returns a array_ref */ constexpr auto operator()(size_type offset, size_type right) const noexcept { - return array_ref(&this->at(offset), right - offset); + return array_ref(&this->at(offset), right - offset); } /** * @brief Slice operations - returns a array_ref */ constexpr auto operator()(size_type offset, size_type right) noexcept { - return array_ref(&this->at(offset), right - offset); + return array_ref(&this->at(offset), right - offset); } // Common operations diff --git a/include/bitlib/bit-containers/bit_array_dynamic_extent.hpp b/include/bitlib/bit-containers/bit_array_dynamic_extent.hpp index 6ac6bcf1..206212aa 100644 --- a/include/bitlib/bit-containers/bit_array_dynamic_extent.hpp +++ b/include/bitlib/bit-containers/bit_array_dynamic_extent.hpp @@ -40,10 +40,11 @@ struct array_dextent_iterator_types { } // namespace detail template class array - : public array_base, T, std::dynamic_extent, W, Policy, detail::array_dextent_iterator_types> { + : public array_base, T, std::dynamic_extent, W, false, Policy, detail::array_dextent_iterator_types> { public: - using base = array_base, T, std::dynamic_extent, W, Policy, detail::array_dextent_iterator_types>; + using base = array_base, T, std::dynamic_extent, W, false, Policy, detail::array_dextent_iterator_types>; using base::end; + using base::size; using typename base::const_iterator; using typename base::const_pointer; using typename base::const_reference; @@ -64,8 +65,6 @@ class array #pragma GCC diagnostic pop static const size_type FixedBits = FixedWords * bitsof(); - const size_type m_size; - struct Storage { union { word_type_ptr pointer; @@ -156,49 +155,49 @@ class array array() = delete; constexpr array(const size_type size, const Allocator& allocator = Allocator()) - : m_size(size), storage(Words(size), allocator) { + : base(size), storage(Words(size), allocator) { } template constexpr array(const size_type size, const U& integral, const Allocator& allocator = Allocator()) - : m_size(size), storage(Words(size), allocator, detail::uninitialized) { + : base(size), storage(Words(size), allocator, detail::uninitialized) { this->from_integral(integral); } constexpr array(const size_type size, const word_type val, const Allocator& allocator = Allocator()) - : m_size(size), storage(Words(size), val, allocator) { + : base(size), storage(Words(size), val, allocator) { } constexpr array(const size_type size, const value_type bit_val, const Allocator& allocator = Allocator()) requires(!std::is_same::value) - : m_size(size), storage(Words(size), allocator, detail::uninitialized) { + : base(size), storage(Words(size), allocator, detail::uninitialized) { this->fill(bit_val); } constexpr array(const array& other) - : m_size(other.size()), storage(Words(size()), other.storage) { + : base(other.size()), storage(Words(size()), other.storage) { } constexpr array(const array& other, const Allocator& allocator) - : m_size(other.size()), storage(Words(size()), other.storage, allocator) { + : base(other.size()), storage(Words(size()), other.storage, allocator) { } constexpr array(const bit_sized_range auto& other, const Allocator& allocator = Allocator()) - : m_size(other.size()), storage(Words(size()), allocator, detail::uninitialized) { + : base(other.size()), storage(Words(size()), allocator, detail::uninitialized) { ::bit::copy(other.begin(), other.end(), this->begin()); } constexpr array(array&& other) - : m_size(other.size()), storage(Words(size()), std::move(other.storage)) { + : base(other.size()), storage(Words(size()), std::move(other.storage)) { } constexpr array(array&& other, const Allocator& allocator) - : m_size(other.size()), storage(Words(size()), std::move(other.storage), allocator) { + : base(other.size()), storage(Words(size()), std::move(other.storage), allocator) { } constexpr array(const std::initializer_list init, const Allocator& allocator = Allocator()) requires(!std::is_same_v) - : m_size(init.size()), storage(Words(size()), allocator, detail::uninitialized) { + : base(init.size()), storage(Words(size()), allocator, detail::uninitialized) { std::copy(init.begin(), init.end(), this->begin()); } @@ -207,20 +206,20 @@ class array bit_value has explicit constructor from bool to bit_value so this doesnt work constexpr array::array(const std::initializer_list init) : storage(std::make_unique(Words(init.size()))), - m_size(init.size()) { + base(init.size()) { std::copy(init.begin(), init.end(), this->begin()); } #endif template constexpr array(const std::initializer_list init, const Allocator& allocator = Allocator()) - : m_size(bitsof() * init.size()), storage(Words(size()), allocator, detail::uninitialized) { + : base(bitsof() * init.size()), storage(Words(size()), allocator, detail::uninitialized) { std::copy(init.begin(), init.end(), data()); } constexpr array(const std::string_view s, const Allocator& allocator = Allocator()) requires(std::is_same_v) - : m_size(std::count(s.begin(), s.end(), '0') + std::count(s.begin(), s.end(), '1')), storage(Words(size()), allocator, detail::uninitialized) { + : base(std::count(s.begin(), s.end(), '0') + std::count(s.begin(), s.end(), '1')), storage(Words(size()), allocator, detail::uninitialized) { size_type i = 0; for (char c : s) { if (c == '0') { @@ -300,13 +299,6 @@ class array } } - /* - * Capacity - */ - constexpr size_type size() const noexcept { - return m_size; - } - /* * Operations */ diff --git a/include/bitlib/bit-containers/bit_array_ref.hpp b/include/bitlib/bit-containers/bit_array_ref.hpp index 78ef8497..8f90ad74 100644 --- a/include/bitlib/bit-containers/bit_array_ref.hpp +++ b/include/bitlib/bit-containers/bit_array_ref.hpp @@ -25,11 +25,11 @@ namespace bit { -template >> +template >> class array_ref; -template >> -using bit_array_ref = array_ref; +template >> +using bit_array_ref = array_ref; namespace detail { template @@ -48,12 +48,13 @@ struct array_ref_iterator_types { * @tparam T The value type (typically bit_value) * @tparam W The word type used for storage */ -template +template class array_ref - : public array_base, T, std::dynamic_extent, W, Policy, detail::array_ref_iterator_types> { + : public array_base, T, N, W, false, Policy, detail::array_ref_iterator_types> { public: - using base = array_base, T, std::dynamic_extent, W, Policy, detail::array_ref_iterator_types>; + using base = array_base, T, N, W, false, Policy, detail::array_ref_iterator_types>; using base::end; + using base::size; using typename base::const_iterator; using typename base::const_pointer; using typename base::const_reference; @@ -67,7 +68,6 @@ class array_ref private: const bit_pointer m_storage; - const size_type m_size; public: // Constructors @@ -80,8 +80,12 @@ class array_ref * @param size Number of bits */ constexpr array_ref(word_type* storage, size_type size) - : m_storage(storage), - m_size(size) { + requires(N == std::dynamic_extent) + : base(size), m_storage(storage) { + } + constexpr array_ref(word_type* storage) + requires(N != std::dynamic_extent) + : base(), m_storage(storage) { } /** @@ -91,8 +95,12 @@ class array_ref * @param size Number of bits */ constexpr array_ref(bit_pointer storage, size_type size) - : m_storage(storage), - m_size(size) { + requires(N == std::dynamic_extent) + : base(size), m_storage(storage) { + } + constexpr array_ref(bit_pointer storage) + requires(N != std::dynamic_extent) + : base(), m_storage(storage) { } /** @@ -101,10 +109,15 @@ class array_ref * @param other bit_sized_range */ constexpr array_ref(bit_range auto& other, size_type size) - : m_storage(&(*other.begin())), - m_size(size) { + requires(N == std::dynamic_extent) + : base(size), m_storage(&(*other.begin())) { assert(size <= (other.end() - other.begin())); } + constexpr array_ref(bit_range auto& other) + requires(N != std::dynamic_extent) + : base(), m_storage(&(*other.begin())) { + assert(N <= (other.end() - other.begin())); + } /** * @brief Constructs a non-owning reference to a bit array from a bit_sized_range @@ -112,11 +125,15 @@ class array_ref * @param other bit_sized_range */ constexpr array_ref(const bit_range auto& other, size_type size) - requires(std::is_const_v) - : m_storage(&(*other.begin())), - m_size(size) { + requires((N == std::dynamic_extent) && std::is_const_v) + : base(size), m_storage(&(*other.begin())) { assert(size <= (other.end() - other.begin())); } + constexpr array_ref(const bit_range auto& other) + requires((N != std::dynamic_extent) && std::is_const_v) + : base(), m_storage(&(*other.begin())) { + assert(N <= (other.end() - other.begin())); + } /** * @brief Copy constructor @@ -132,7 +149,7 @@ class array_ref * @brief Range Assignment operator - copies content but doesn't rebind */ constexpr array_ref& operator=(const bit_sized_range auto& other) { - if (m_size != other.size()) { + if (size() != other.size()) { throw std::invalid_argument("Cannot assign from array_ref of different size"); } ::bit::copy(other.begin(), other.end(), this->begin()); @@ -144,7 +161,7 @@ class array_ref */ constexpr array_ref& operator=(const array_ref& other) { if (this != &other) { - if (m_size != other.m_size) { + if (size() != other.size()) { throw std::invalid_argument("Cannot assign from array_ref of different size"); } ::bit::copy(other.begin(), other.end(), this->begin()); @@ -157,7 +174,7 @@ class array_ref */ constexpr array_ref& operator=(array_ref&& other) { if (this != &other) { - if (m_size != other.size()) { + if (size() != other.size()) { throw std::invalid_argument("Cannot assign from array_ref of different size"); } ::bit::copy(other.begin(), other.end(), this->begin()); @@ -181,18 +198,11 @@ class array_ref return const_iterator(m_storage); } - /* - * Capacity - */ - constexpr size_type size() const noexcept { - return m_size; - } - /* * Operations */ constexpr void swap(array_ref& other) { - if (m_size != other.m_size) { + if (size() != other.size()) { throw std::invalid_argument("Cannot swap array_ref of different sizes"); } swap_ranges(begin(), end(), other.begin()); diff --git a/include/bitlib/bit-containers/bit_mdspan_accessor.hpp b/include/bitlib/bit-containers/bit_mdspan_accessor.hpp index e75048fe..9b8cd82b 100644 --- a/include/bitlib/bit-containers/bit_mdspan_accessor.hpp +++ b/include/bitlib/bit-containers/bit_mdspan_accessor.hpp @@ -27,6 +27,32 @@ struct bit_default_accessor { return p + i; } }; + +template +struct bit_word_accessor : private detail::container_size_storage { + using element_type = bit_array; + using data_handle_type = bit_pointer; + using reference = bit_array_ref; + using offset_policy = bit_word_accessor; + constexpr reference access(data_handle_type p, std::size_t i) const noexcept + requires(N == std::dynamic_extent) + { + return reference(p + i * this->size(), this->size()); + } + constexpr reference access(data_handle_type p, std::size_t i) const noexcept + requires(N != std::dynamic_extent) + { + return reference(p + i * this->size()); + } + constexpr data_handle_type offset(data_handle_type p, std::size_t i) const noexcept { + return p + i * this->size(); + } + constexpr bit_word_accessor() : detail::container_size_storage() {} + constexpr bit_word_accessor(const size_t& size) + requires(N == std::dynamic_extent) + : detail::container_size_storage(size) {} +}; + } // namespace bit #endif diff --git a/include/bitlib/bit-containers/bit_span.hpp b/include/bitlib/bit-containers/bit_span.hpp index 6241dd1c..7eaf466b 100644 --- a/include/bitlib/bit-containers/bit_span.hpp +++ b/include/bitlib/bit-containers/bit_span.hpp @@ -129,7 +129,7 @@ class bit_span : private bit_span_storage { constexpr bit_span subspan(size_type offset, size_type count = std::dynamic_extent) const noexcept requires(Extent == std::dynamic_extent); - constexpr bit_array_ref operator()(size_type begin, size_type end) const noexcept; + constexpr bit_array_ref operator()(size_type begin, size_type end) const noexcept; template constexpr bit_span first() const noexcept @@ -304,8 +304,8 @@ constexpr bit_span bit_span -constexpr bit_array_ref bit_span::operator()(size_type begin, size_type end) const noexcept { - return bit_array_ref(&(this->begin()[begin]), end - begin); +constexpr bit_array_ref bit_span::operator()(size_type begin, size_type end) const noexcept { + return bit_array_ref(&(this->begin()[begin]), end - begin); } template diff --git a/include/bitlib/bit-iterator/bit_details.hpp b/include/bitlib/bit-iterator/bit_details.hpp index bd602267..13908488 100644 --- a/include/bitlib/bit-iterator/bit_details.hpp +++ b/include/bitlib/bit-iterator/bit_details.hpp @@ -1112,6 +1112,34 @@ struct uninitialized_t { }; inline constexpr uninitialized_t uninitialized{}; +template +struct container_size_storage { + constexpr size_type size() const noexcept { + return Extent; + } + + constexpr container_size_storage() noexcept {} +}; + +template +struct container_size_storage { + using maybe_const_size_type = std::conditional_t>; + + maybe_const_size_type size_; + constexpr size_type size() const noexcept { + return size_; + } + constexpr void resize(const size_type& new_size) + requires(resizeable) + { + size_ = new_size; + } + + constexpr container_size_storage() noexcept : size_() {} + constexpr container_size_storage(const size_type& size) noexcept + : size_(size) {} +}; + } // namespace detail // ========================================================================== // diff --git a/test/src/test-mdspan.cpp b/test/src/test-mdspan.cpp index 78729830..a3d66615 100644 --- a/test/src/test-mdspan.cpp +++ b/test/src/test-mdspan.cpp @@ -41,3 +41,72 @@ TEST(MdSpanTest, BitDefaultLayout) { } } } + +TEST(MdSpanTest, BitFixedWordLayout) { + uint32_t rot = 0xDEADBEEF; + bit::bit_array<> dynarr(5 * 6 * 7); + for (int i = 0; i < 5; i++) { + for (int j = 0; j < 6; j++) { + for (int k = 0; k < 7; k++) { + dynarr[i * 6 * 7 + j * 7 + k] = (rot & 1) ? bit::bit1 : bit::bit0; + rot = (rot >> 1) | ((rot & 1) << 31); + } + } + } + rot = 0xDEADBEEF; + using accessor_t = bit::bit_word_accessor<5, uintptr_t>; + using mdspan_t = + std::mdspan< + accessor_t::element_type, + std::dextents, + std::layout_right, + accessor_t>; + + mdspan_t myspan(&dynarr[0], 6, 7); + for (size_t i = 0; i < myspan.extent(0); i++) { + for (size_t j = 0; j < myspan.extent(1); j++) { + auto ref = myspan[i, j]; + for (size_t k = 0; k < 5; k++) { + bit::bit_value expected = ((rot & 1) ? bit::bit1 : bit::bit0); + EXPECT_EQ(ref[k], expected); + rot = (rot >> 1) | ((rot & 1) << 31); + } + } + } +} + +TEST(MdSpanTest, BitDynamicWordLayout) { + uint32_t rot = 0xDEADBEEF; + bit::bit_array<> dynarr(5 * 6 * 7); + for (int i = 0; i < 5; i++) { + for (int j = 0; j < 6; j++) { + for (int k = 0; k < 7; k++) { + dynarr[i * 6 * 7 + j * 7 + k] = (rot & 1) ? bit::bit1 : bit::bit0; + rot = (rot >> 1) | ((rot & 1) << 31); + } + } + } + rot = 0xDEADBEEF; + using accessor_t = bit::bit_word_accessor; + using extents_t = std::dextents; + using mdspan_t = + std::mdspan< + accessor_t::element_type, + std::dextents, + std::layout_right, + accessor_t>; + + accessor_t myaccessor(5); + extents_t dyn_ext{6, 7}; + mdspan_t myspan(&dynarr[0], dyn_ext, myaccessor); + for (size_t i = 0; i < myspan.extent(0); i++) { + for (size_t j = 0; j < myspan.extent(1); j++) { + auto ref = myspan[i, j]; + for (size_t k = 0; k < 5; k++) { + bit::bit_value expected = ((rot & 1) ? bit::bit1 : bit::bit0); + EXPECT_EQ(ref[k], expected); + rot = (rot >> 1) | ((rot & 1) << 31); + } + } + } +} From 3aa65434ec17025435b02c8c119436590bdd14dc Mon Sep 17 00:00:00 2001 From: Peter McLean Date: Sat, 5 Jul 2025 23:23:10 -0400 Subject: [PATCH 09/13] Warnings cleanup --- include/bitlib/bit-algorithms/accumulate.hpp | 2 -- .../bit_array_dynamic_extent.hpp | 20 ++++++++-------- .../bitlib/bit-containers/bit_array_ref.hpp | 24 +++++++++---------- 3 files changed, 22 insertions(+), 24 deletions(-) diff --git a/include/bitlib/bit-algorithms/accumulate.hpp b/include/bitlib/bit-algorithms/accumulate.hpp index 52887fda..62b77ada 100644 --- a/include/bitlib/bit-algorithms/accumulate.hpp +++ b/include/bitlib/bit-algorithms/accumulate.hpp @@ -36,9 +36,7 @@ constexpr auto accumulate( using size_type = typename bit_iterator::size_type; constexpr size_type digits = bitsof(); - size_type total_bits_to_op = distance(first, last); - bool keep_going = true;; if constexpr (initial_sub_word) { size_type sub_digits; if constexpr (forward) { diff --git a/include/bitlib/bit-containers/bit_array_dynamic_extent.hpp b/include/bitlib/bit-containers/bit_array_dynamic_extent.hpp index 206212aa..3c334dbc 100644 --- a/include/bitlib/bit-containers/bit_array_dynamic_extent.hpp +++ b/include/bitlib/bit-containers/bit_array_dynamic_extent.hpp @@ -154,23 +154,23 @@ class array */ array() = delete; - constexpr array(const size_type size, const Allocator& allocator = Allocator()) - : base(size), storage(Words(size), allocator) { + constexpr array(const size_type extent, const Allocator& allocator = Allocator()) + : base(extent), storage(Words(extent), allocator) { } template - constexpr array(const size_type size, const U& integral, const Allocator& allocator = Allocator()) - : base(size), storage(Words(size), allocator, detail::uninitialized) { + constexpr array(const size_type extent, const U& integral, const Allocator& allocator = Allocator()) + : base(extent), storage(Words(extent), allocator, detail::uninitialized) { this->from_integral(integral); } - constexpr array(const size_type size, const word_type val, const Allocator& allocator = Allocator()) - : base(size), storage(Words(size), val, allocator) { + constexpr array(const size_type extent, const word_type val, const Allocator& allocator = Allocator()) + : base(extent), storage(Words(extent), val, allocator) { } - constexpr array(const size_type size, const value_type bit_val, const Allocator& allocator = Allocator()) + constexpr array(const size_type extent, const value_type bit_val, const Allocator& allocator = Allocator()) requires(!std::is_same::value) - : base(size), storage(Words(size), allocator, detail::uninitialized) { + : base(extent), storage(Words(extent), allocator, detail::uninitialized) { this->fill(bit_val); } @@ -235,7 +235,7 @@ class array */ constexpr array& operator=(const array& other) { if (nullptr == data() || size() != other.size()) { - throw std::invalid_argument("Cannot reassign array size"); + throw std::invalid_argument("Cannot reassign array extent"); } if (this == &other) [[unlikely]] { return *this; @@ -254,7 +254,7 @@ class array constexpr array& operator=(array&& other) { if (nullptr == data() || size() != other.size()) { - throw std::invalid_argument("Cannot reassign array size"); + throw std::invalid_argument("Cannot reassign array extent"); } array temp(std::move(other)); swap(temp); diff --git a/include/bitlib/bit-containers/bit_array_ref.hpp b/include/bitlib/bit-containers/bit_array_ref.hpp index 8f90ad74..f2b51c61 100644 --- a/include/bitlib/bit-containers/bit_array_ref.hpp +++ b/include/bitlib/bit-containers/bit_array_ref.hpp @@ -77,11 +77,11 @@ class array_ref * @brief Constructs a non-owning reference to a bit array * * @param storage Pointer to the storage - * @param size Number of bits + * @param extent Number of bits */ - constexpr array_ref(word_type* storage, size_type size) + constexpr array_ref(word_type* storage, size_type extent) requires(N == std::dynamic_extent) - : base(size), m_storage(storage) { + : base(extent), m_storage(storage) { } constexpr array_ref(word_type* storage) requires(N != std::dynamic_extent) @@ -92,11 +92,11 @@ class array_ref * @brief Constructs a non-owning reference to a bit array using a bit_pointer * * @param storage bit_pointer to the storage - * @param size Number of bits + * @param extent Number of bits */ - constexpr array_ref(bit_pointer storage, size_type size) + constexpr array_ref(bit_pointer storage, size_type extent) requires(N == std::dynamic_extent) - : base(size), m_storage(storage) { + : base(extent), m_storage(storage) { } constexpr array_ref(bit_pointer storage) requires(N != std::dynamic_extent) @@ -108,10 +108,10 @@ class array_ref * * @param other bit_sized_range */ - constexpr array_ref(bit_range auto& other, size_type size) + constexpr array_ref(bit_range auto& other, size_type extent) requires(N == std::dynamic_extent) - : base(size), m_storage(&(*other.begin())) { - assert(size <= (other.end() - other.begin())); + : base(extent), m_storage(&(*other.begin())) { + assert(extent <= (other.end() - other.begin())); } constexpr array_ref(bit_range auto& other) requires(N != std::dynamic_extent) @@ -124,10 +124,10 @@ class array_ref * * @param other bit_sized_range */ - constexpr array_ref(const bit_range auto& other, size_type size) + constexpr array_ref(const bit_range auto& other, size_type extent) requires((N == std::dynamic_extent) && std::is_const_v) - : base(size), m_storage(&(*other.begin())) { - assert(size <= (other.end() - other.begin())); + : base(extent), m_storage(&(*other.begin())) { + assert(extent <= (other.end() - other.begin())); } constexpr array_ref(const bit_range auto& other) requires((N != std::dynamic_extent) && std::is_const_v) From 8b3941a33a53bc73ed6668e9d8faf1547b235bb0 Mon Sep 17 00:00:00 2001 From: Peter McLean Date: Sat, 5 Jul 2025 23:50:19 -0400 Subject: [PATCH 10/13] Fix exact integral type --- include/bitlib/bit-iterator/bit_details.hpp | 65 +++++++++++---------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/include/bitlib/bit-iterator/bit_details.hpp b/include/bitlib/bit-iterator/bit_details.hpp index 13908488..87612b2f 100644 --- a/include/bitlib/bit-iterator/bit_details.hpp +++ b/include/bitlib/bit-iterator/bit_details.hpp @@ -286,12 +286,12 @@ using _wider_type_t = typename _wider_type::type; #endif /* -exact_ceil_integral is used to determine the exact integral type that a proxy reference +exact_floor_integral is used to determine the exact integral type that a proxy reference can be implicitly converted to. -If the proxy reference supports multiple types, it will pick the largest, preferring unsigned. +If the proxy reference supports multiple types, it will pick the smallest, preferring unsigned. */ template -struct exact_ceil_integral { +struct exact_floor_integral { private: using U = std::remove_cvref_t; @@ -308,28 +308,29 @@ struct exact_ceil_integral { } public: - using type = std::conditional_t< - is_exactly_convertible(), uint64_t, + using type = std::conditional_t< - is_exactly_convertible(), int64_t, + is_exactly_convertible(), uint8_t, std::conditional_t< - is_exactly_convertible(), uint32_t, + is_exactly_convertible(), int8_t, std::conditional_t< - is_exactly_convertible(), int32_t, + is_exactly_convertible(), uint16_t, std::conditional_t< - is_exactly_convertible(), uint16_t, + is_exactly_convertible(), int16_t, std::conditional_t< - is_exactly_convertible(), int16_t, + is_exactly_convertible(), uint32_t, std::conditional_t< - is_exactly_convertible(), uint8_t, + is_exactly_convertible(), int32_t, std::conditional_t< - is_exactly_convertible(), int8_t, - void>>>>>>>>; + is_exactly_convertible(), uint64_t, + std::conditional_t< + is_exactly_convertible(), int64_t, + void>>>>>>>>; }; // Helper alias template -using exact_ceil_integral_t = typename exact_ceil_integral::type; +using exact_floor_integral_t = typename exact_floor_integral::type; /* ******************* IMPLEMENTATION DETAILS: UTILITIES ******************** */ // Assertions @@ -449,8 +450,10 @@ constexpr T lsr(const T val, const size_type shift) { } template -constexpr exact_ceil_integral_t lsr(const T val, const size_type shift) { - return static_cast>(static_cast>>(val) >> shift); +constexpr exact_floor_integral_t lsr(const T val, const size_type shift) { + static_assert(!std::is_same_v, void>, + "Type T must be convertible to an integral type"); + return static_cast>(static_cast>>(val) >> shift); } enum class _mask_len { @@ -804,32 +807,32 @@ constexpr T _bitswap() noexcept { // Replaces bits of src0 by the ones of src1 where the mask is true template -constexpr exact_ceil_integral_t _bitblend( +constexpr exact_floor_integral_t _bitblend( const T src0_, const U src1_, - const exact_ceil_integral_t msk) noexcept - requires(std::is_same_v, exact_ceil_integral_t>) + const exact_floor_integral_t msk) noexcept + requires(std::is_same_v, exact_floor_integral_t>) { - static_assert(binary_digits>::value, ""); - const exact_ceil_integral_t src0 = static_cast>(src0_); - const exact_ceil_integral_t src1 = static_cast>(src1_); + static_assert(binary_digits>::value, ""); + const exact_floor_integral_t src0 = static_cast>(src0_); + const exact_floor_integral_t src1 = static_cast>(src1_); return src0 ^ ((src0 ^ src1) & msk); } // Replaces len bits of src0 by the ones of src1 starting at start template -constexpr exact_ceil_integral_t _bitblend( +constexpr exact_floor_integral_t _bitblend( const T src0_, const U src1_, - const exact_ceil_integral_t start, - const exact_ceil_integral_t len) noexcept - requires(std::is_same_v, exact_ceil_integral_t>) + const exact_floor_integral_t start, + const exact_floor_integral_t len) noexcept + requires(std::is_same_v, exact_floor_integral_t>) { - static_assert(binary_digits>::value, ""); - constexpr exact_ceil_integral_t digits = bitsof>(); - const exact_ceil_integral_t src0 = static_cast>(src0_); - const exact_ceil_integral_t src1 = static_cast>(src1_); - const exact_ceil_integral_t msk = _mask, _mask_len::unknown>(len) << start; + static_assert(binary_digits>::value, ""); + constexpr exact_floor_integral_t digits = bitsof>(); + const exact_floor_integral_t src0 = static_cast>(src0_); + const exact_floor_integral_t src1 = static_cast>(src1_); + const exact_floor_integral_t msk = _mask, _mask_len::unknown>(len) << start; return src0 ^ ((src0 ^ src1) & msk * (start < digits)); } // -------------------------------------------------------------------------- // From 5c17e4d209c8279a62ae93c87b4f8264b5c244d5 Mon Sep 17 00:00:00 2001 From: Peter McLean Date: Sun, 6 Jul 2025 00:14:47 -0400 Subject: [PATCH 11/13] Squash more warnings --- include/bitlib/bit-containers/bit_array.hpp | 14 +- .../bitlib/bit-containers/bit_array_ref.hpp | 4 +- test/src/fixtures.hpp | 124 +++-- test/src/test-count.cpp | 29 +- test/src/test-move.cpp | 101 ++-- test/src/vector_test.cpp | 465 +++++++++--------- 6 files changed, 378 insertions(+), 359 deletions(-) diff --git a/include/bitlib/bit-containers/bit_array.hpp b/include/bitlib/bit-containers/bit_array.hpp index d49e8e7c..a6e87d67 100644 --- a/include/bitlib/bit-containers/bit_array.hpp +++ b/include/bitlib/bit-containers/bit_array.hpp @@ -110,12 +110,12 @@ class array : public array_base, T, N, W, false, Policy, } constexpr array(const array& other) noexcept - : storage(other.storage) {} + : base(), storage(other.storage) {} constexpr array(const array&& other) noexcept - : storage(other.storage) {} + : base(), storage(other.storage) {} - constexpr array(const bit_sized_range auto& other) { + constexpr array(const bit_sized_range auto& other) : base() { if (other.size() != this->size()) [[unlikely]] { throw std::invalid_argument("other bit_range contains an invalid number of bits for array."); } @@ -124,21 +124,21 @@ class array : public array_base, T, N, W, false, Policy, constexpr array(const std::initializer_list init) requires(!std::is_same_v) - { + : base() { if (init.size() != bitsof(*this)) [[unlikely]] { throw std::invalid_argument("initialize_list contains an invalid number of bits for array."); } std::copy(init.begin(), init.end(), this->begin()); } - constexpr array(const std::initializer_list init) { + constexpr array(const std::initializer_list init) : base() { if (init.size() != bitsof(*this)) [[unlikely]] { throw std::invalid_argument("initialize_list contains an invalid number of bits for array."); } std::copy(init.begin(), init.end(), this->begin()); } - constexpr array(const std::initializer_list init) : storage{} { + constexpr array(const std::initializer_list init) : base(), storage{} { // Make sure we handle the case where init.size() != Words auto it = init.begin(); for (size_type i = 0; i < std::min(Words(N), init.size()); ++i, ++it) { @@ -148,7 +148,7 @@ class array : public array_base, T, N, W, false, Policy, constexpr array(const std::string_view s) requires(std::is_same_v) - { + : base() { if (bitsof(*this) != static_cast(std::count(s.begin(), s.end(), '0') + std::count(s.begin(), s.end(), '1'))) [[unlikely]] { throw std::invalid_argument("String contains an invalid number of bits for array."); }; diff --git a/include/bitlib/bit-containers/bit_array_ref.hpp b/include/bitlib/bit-containers/bit_array_ref.hpp index f2b51c61..796858a4 100644 --- a/include/bitlib/bit-containers/bit_array_ref.hpp +++ b/include/bitlib/bit-containers/bit_array_ref.hpp @@ -111,12 +111,12 @@ class array_ref constexpr array_ref(bit_range auto& other, size_type extent) requires(N == std::dynamic_extent) : base(extent), m_storage(&(*other.begin())) { - assert(extent <= (other.end() - other.begin())); + assert(extent <= static_cast(other.end() - other.begin())); } constexpr array_ref(bit_range auto& other) requires(N != std::dynamic_extent) : base(), m_storage(&(*other.begin())) { - assert(N <= (other.end() - other.begin())); + assert(N <= static_cast(other.end() - other.begin())); } /** diff --git a/test/src/fixtures.hpp b/test/src/fixtures.hpp index 515dbeb0..6317786e 100644 --- a/test/src/fixtures.hpp +++ b/test/src/fixtures.hpp @@ -46,11 +46,10 @@ class VectorTest : public testing::Test { std::vector random_bitvecs; std::vector> random_boolvecs; std::vector random_vec; - const size_t word_size = 4; - const size_t digits = bit::binary_digits::value; - const size_t bit_size = word_size * digits; - void SetUp() override { + const size_t word_size = 4; + const size_t bit_size = word_size * bit::binary_digits::value; + const size_t digits = bit::binary_digits::value; empty_vec = vec_type(); random_vec = get_random_vec(word_size); for (size_t cont_size = 1; cont_size < bit_size; ++cont_size) { @@ -79,53 +78,53 @@ TYPED_TEST_SUITE(VectorTest, BaseTypes); template class SingleRangeTest : public testing::Test { - protected: + protected: + using base_type = WordType; - using base_type = WordType; + std::vector> random_bitvecs; + std::vector> random_boolvecs; + std::vector random_vec; - std::vector> random_bitvecs; - std::vector> random_boolvecs; - std::vector random_vec; + protected: + void SetUp() override { + const size_t digits = bit::binary_digits::value; size_t word_size = 4; - size_t digits = bit::binary_digits::value; - size_t bit_size = word_size*digits; - - void SetUp() override { - random_vec = get_random_vec(word_size); - for (size_t cont_size = 1; cont_size < bit_size; ++cont_size) { - auto bitvec = bit::bit_vector(bit_size); - std::copy(random_vec.begin(), random_vec.end(), bitvec.begin().base()); - bitvec.resize(cont_size); - - auto boolvec = boolvec_from_bitvec(bitvec); - random_bitvecs.push_back(bitvec); - random_boolvecs.push_back(boolvec); - } - word_size = 2*64*64; - random_vec = get_random_vec(word_size); - size_t bit_size = (word_size)*digits; - for (size_t cont_size = bit_size - digits - 4; cont_size < bit_size - digits + 4; ++cont_size) { - auto bitvec = bit::bit_vector(bit_size); - std::copy(random_vec.begin(), random_vec.end(), bitvec.begin().base()); - bitvec.resize(cont_size); + size_t bit_size = word_size * digits; + random_vec = get_random_vec(word_size); + for (size_t cont_size = 1; cont_size < bit_size; ++cont_size) { + auto bitvec = bit::bit_vector(bit_size); + std::copy(random_vec.begin(), random_vec.end(), bitvec.begin().base()); + bitvec.resize(cont_size); - auto boolvec = boolvec_from_bitvec(bitvec); - random_bitvecs.push_back(bitvec); - random_boolvecs.push_back(boolvec); - } + auto boolvec = boolvec_from_bitvec(bitvec); + random_bitvecs.push_back(bitvec); + random_boolvecs.push_back(boolvec); + } + word_size = 2 * 64 * 64; + bit_size = word_size * digits; + random_vec = get_random_vec(word_size); + for (size_t cont_size = bit_size - digits - 4; cont_size < bit_size - digits + 4; ++cont_size) { + auto bitvec = bit::bit_vector(bit_size); + std::copy(random_vec.begin(), random_vec.end(), bitvec.begin().base()); + bitvec.resize(cont_size); - auto zeros = bit::bit_vector(bit_size); - std::fill(zeros.begin(), zeros.end(), bit::bit0); - *(zeros.end() - 1024 - digits - 4) = bit::bit1; - random_bitvecs.push_back(zeros); - random_boolvecs.push_back(boolvec_from_bitvec(zeros)); - - auto ones = bit::bit_vector(bit_size); - std::fill(ones.begin(), ones.end(), bit::bit1); - *(ones.end() - 1024 - digits - 4) = bit::bit0; - random_bitvecs.push_back(ones); - random_boolvecs.push_back(boolvec_from_bitvec(ones)); + auto boolvec = boolvec_from_bitvec(bitvec); + random_bitvecs.push_back(bitvec); + random_boolvecs.push_back(boolvec); } + + auto zeros = bit::bit_vector(bit_size); + std::fill(zeros.begin(), zeros.end(), bit::bit0); + *(zeros.end() - 1024 - digits - 4) = bit::bit1; + random_bitvecs.push_back(zeros); + random_boolvecs.push_back(boolvec_from_bitvec(zeros)); + + auto ones = bit::bit_vector(bit_size); + std::fill(ones.begin(), ones.end(), bit::bit1); + *(ones.end() - 1024 - digits - 4) = bit::bit0; + random_bitvecs.push_back(ones); + random_boolvecs.push_back(boolvec_from_bitvec(ones)); + } }; TYPED_TEST_SUITE(SingleRangeTest, BaseTypes); @@ -141,24 +140,25 @@ class DoubleRangeTest : public testing::Test { std::vector> random_boolvecs2; std::vector random_vec; std::vector random_vec_big; - size_t digits = bit::binary_digits::value; - size_t word_size = 4; - size_t bit_size = word_size*bit::binary_digits::value; - size_t big_size = 64*64*2; void SetUp() override { - // TODO this is ugly, need to refactor - random_vec = get_random_vec(word_size); - random_vec_big = get_random_vec(big_size); - for (size_t cont_size = 1; cont_size < bit_size; ++cont_size) { - auto bitvec = bit::bit_vector(bit_size); - std::copy(random_vec.begin(), random_vec.end(), bitvec.begin().base()); - bitvec.resize(cont_size); - - auto boolvec = boolvec_from_bitvec(bitvec); - random_bitvecs1.push_back(bitvec); - random_boolvecs1.push_back(boolvec); - } + const size_t word_size = 4; + const size_t big_size = 64 * 64 * 2; + const size_t digits = bit::binary_digits::value; + const size_t bit_size = word_size * digits; + + // TODO this is ugly, need to refactor + random_vec = get_random_vec(word_size); + random_vec_big = get_random_vec(big_size); + for (size_t cont_size = 1; cont_size < bit_size; ++cont_size) { + auto bitvec = bit::bit_vector(bit_size); + std::copy(random_vec.begin(), random_vec.end(), bitvec.begin().base()); + bitvec.resize(cont_size); + + auto boolvec = boolvec_from_bitvec(bitvec); + random_bitvecs1.push_back(bitvec); + random_boolvecs1.push_back(boolvec); + } for (int i = -4; i < 4; ++i) { size_t cont_size = (big_size-1)*digits + i; auto bitvec = bit::bit_vector(big_size*digits); @@ -199,9 +199,7 @@ class MixedDoubleRangeTest : public testing::Test { using FromWordType = typename FromToPair::first_type; using ToWordType = typename FromToPair::second_type; - static constexpr size_t digits = bit::binary_digits::value; static constexpr size_t word_size = 4; - static constexpr size_t bit_size = word_size * digits; static constexpr size_t big_size = 64 * 64 * 2; // test data diff --git a/test/src/test-count.cpp b/test/src/test-count.cpp index bb0ad072..8dca0004 100644 --- a/test/src/test-count.cpp +++ b/test/src/test-count.cpp @@ -1,11 +1,10 @@ // ============================== COUNT TESTS =============================== // // Project: The Experimental Bit Algorithms Library -// Description: Tests for count algorithms +// Description: Tests for count algorithms // Contributor(s): Bryce Kille // License: BSD 3-Clause License // ========================================================================== // - // ============================== PREAMBLE ================================== // // C++ standard library #include @@ -20,20 +19,20 @@ // ========================================================================== // TYPED_TEST(SingleRangeTest, Count) { - for (size_t idx = 0; idx < this->bit_size - 1; ++idx) { - bit::bit_vector bitvec = this->random_bitvecs[idx]; - std::vector boolvec = this->random_boolvecs[idx]; - size_t start_count = 16; - while (start_count--) { - unsigned long long start = generate_random_number(0, std::min(bitvec.size() - 1, 16)); - auto bitret = bit::count(bitvec.begin() + start, bitvec.end(), bit::bit1); - auto boolret = std::count(boolvec.begin() + start, boolvec.end(), true); - EXPECT_EQ(bitret, boolret); - bitret = bit::count(bitvec.begin() + start, bitvec.end(), bit::bit0); - boolret = std::count(boolvec.begin() + start, boolvec.end(), false); - EXPECT_EQ(bitret, boolret); - } + for (size_t idx = 0; idx < this->random_bitvecs.size(); ++idx) { + bit::bit_vector bitvec = this->random_bitvecs[idx]; + std::vector boolvec = this->random_boolvecs[idx]; + size_t start_count = 16; + while (start_count--) { + unsigned long long start = generate_random_number(0, std::min(bitvec.size() - 1, 16)); + auto bitret = bit::count(bitvec.begin() + start, bitvec.end(), bit::bit1); + auto boolret = std::count(boolvec.begin() + start, boolvec.end(), true); + EXPECT_EQ(bitret, boolret); + bitret = bit::count(bitvec.begin() + start, bitvec.end(), bit::bit0); + boolret = std::count(boolvec.begin() + start, boolvec.end(), false); + EXPECT_EQ(bitret, boolret); } + } } diff --git a/test/src/test-move.cpp b/test/src/test-move.cpp index bede7a79..f1f9d807 100644 --- a/test/src/test-move.cpp +++ b/test/src/test-move.cpp @@ -1,11 +1,10 @@ // ============================= MOVE TESTS =============================== // // Project: The Experimental Bit Algorithms Library -// Description: Tests for move algorithms +// Description: Tests for move algorithms // Contributor(s): Bryce Kille // License: BSD 3-Clause License // ========================================================================== // - // ============================== PREAMBLE ================================== // // C++ standard library #include @@ -20,57 +19,55 @@ // ========================================================================== // TYPED_TEST(DoubleRangeTest, Move) { - for (size_t idx = 0; idx < this->random_bitvecs1.size(); ++idx) { - using WordType = typename TestFixture::base_type; - bit::bit_vector& bitvec1 = this->random_bitvecs1[idx]; - bit::bit_vector& bitvec2 = this->random_bitvecs2[idx]; - constexpr auto digits = bit::binary_digits::value; - std::vector& boolvec1 = this->random_boolvecs1[idx]; - std::vector& boolvec2 = this->random_boolvecs2[idx]; - long long start1 = generate_random_number( - 0, - std::min(bitvec1.size() - 1, digits + 1)); - long long start2 = generate_random_number( - 0, - std::min(bitvec2.size() - 1, digits + 1)); - const auto min_range = (start2 > start1) ? start2 - start1 : 0; - const auto max_range = std::max( - min_range, - std::min(digits, bitvec1.size() - start1)); - long long end1 = generate_random_number(min_range, max_range); + using WordType = typename TestFixture::base_type; + constexpr auto digits = bit::binary_digits::value; + for (size_t idx = 0; idx < this->random_bitvecs1.size(); ++idx) { + bit::bit_vector& bitvec1 = this->random_bitvecs1[idx]; + bit::bit_vector& bitvec2 = this->random_bitvecs2[idx]; + std::vector& boolvec1 = this->random_boolvecs1[idx]; + std::vector& boolvec2 = this->random_boolvecs2[idx]; + long long start1 = generate_random_number( + 0, + std::min(bitvec1.size() - 1, digits + 1)); + long long start2 = generate_random_number( + 0, + std::min(bitvec2.size() - 1, digits + 1)); + const auto min_range = (start2 > start1) ? start2 - start1 : 0; + const auto max_range = std::max( + min_range, + std::min(digits, bitvec1.size() - start1)); + long long end1 = generate_random_number(min_range, max_range); - auto bitret = bit::move( - bitvec1.begin() + start1, - bitvec1.end() - end1, - bitvec2.begin() + start2); - auto boolret = std::move( - boolvec1.begin() + start1, - boolvec1.end() - end1, - boolvec2.begin() + start2); - EXPECT_EQ( - bit::distance(bitvec2.begin(), bitret), - std::distance(boolvec2.begin(), boolret)); - EXPECT_TRUE(std::equal( - bitvec2.begin(), bitvec2.end(), - boolvec2.begin(), boolvec2.end(), comparator) - ); - start2 = generate_random_number(0, start1); - bitret = bit::move( - bitvec1.begin() + start1, - bitvec1.end() - end1, - bitvec1.begin() + start2); - boolret = std::move( - boolvec1.begin() + start1, - boolvec1.end() - end1, - boolvec1.begin() + start2); - EXPECT_EQ( - bit::distance(bitvec1.begin(), bitret), - std::distance(boolvec1.begin(), boolret)); - EXPECT_TRUE(std::equal( - bitvec1.begin(), bitvec1.end(), - boolvec1.begin(), boolvec1.end(), comparator) - ); - } + auto bitret = bit::move( + bitvec1.begin() + start1, + bitvec1.end() - end1, + bitvec2.begin() + start2); + auto boolret = std::move( + boolvec1.begin() + start1, + boolvec1.end() - end1, + boolvec2.begin() + start2); + EXPECT_EQ( + bit::distance(bitvec2.begin(), bitret), + std::distance(boolvec2.begin(), boolret)); + EXPECT_TRUE(std::equal( + bitvec2.begin(), bitvec2.end(), + boolvec2.begin(), boolvec2.end(), comparator)); + start2 = generate_random_number(0, start1); + bitret = bit::move( + bitvec1.begin() + start1, + bitvec1.end() - end1, + bitvec1.begin() + start2); + boolret = std::move( + boolvec1.begin() + start1, + boolvec1.end() - end1, + boolvec1.begin() + start2); + EXPECT_EQ( + bit::distance(bitvec1.begin(), bitret), + std::distance(boolvec1.begin(), boolret)); + EXPECT_TRUE(std::equal( + bitvec1.begin(), bitvec1.end(), + boolvec1.begin(), boolvec1.end(), comparator)); + } } diff --git a/test/src/vector_test.cpp b/test/src/vector_test.cpp index 5c896b48..149d14b0 100644 --- a/test/src/vector_test.cpp +++ b/test/src/vector_test.cpp @@ -33,8 +33,9 @@ TYPED_TEST(VectorTest, SizeInitializerConstructor) { EXPECT_FALSE(bv); } using WordType = typename TestFixture::base_type; + constexpr auto digits = bit::binary_digits::value; using vec_type = typename TestFixture::vec_type; - for (unsigned int veclen = 0; veclen < 4 * this->digits; veclen++) { + for (unsigned int veclen = 0; veclen < 4 * digits; veclen++) { this->empty_vec = vec_type(veclen); for (unsigned int i = 0; i < veclen; ++i) { EXPECT_FALSE(this->empty_vec[i]); @@ -52,23 +53,25 @@ TYPED_TEST(VectorTest, SizeInitializerConstructor) { TYPED_TEST(VectorTest, CountValueConstructor) { using vec_type = typename TestFixture::vec_type; - for (unsigned int veclen = 0; veclen < 4*this->digits; veclen++) { - this->empty_vec = vec_type(veclen, bit::bit1); - unsigned int i = 0; - // TODO misplaced test for range-based for loop - for (auto bv: this->empty_vec) { - EXPECT_TRUE(bv); - i++; - } - EXPECT_EQ(i, veclen); - this->empty_vec = vec_type(veclen, bit::bit0); - i = 0; - // TODO misplaced test for range-based for loop - for (auto bv: this->empty_vec) { - EXPECT_FALSE(bv); - i++; - } - EXPECT_EQ(i, veclen); + using WordType = typename TestFixture::base_type; + constexpr auto digits = bit::binary_digits::value; + for (unsigned int veclen = 0; veclen < 4 * digits; veclen++) { + this->empty_vec = vec_type(veclen, bit::bit1); + unsigned int i = 0; + // TODO misplaced test for range-based for loop + for (auto bv : this->empty_vec) { + EXPECT_TRUE(bv); + i++; + } + EXPECT_EQ(i, veclen); + this->empty_vec = vec_type(veclen, bit::bit0); + i = 0; + // TODO misplaced test for range-based for loop + for (auto bv : this->empty_vec) { + EXPECT_FALSE(bv); + i++; + } + EXPECT_EQ(i, veclen); } } @@ -77,14 +80,15 @@ TYPED_TEST(VectorTest, WordIterPairConstructor) { using WordType = typename TestFixture::base_type; using vec_type = typename TestFixture::vec_type; using iterator_type = typename std::vector::iterator; - for (unsigned int veclen = 0; veclen < 4*this->digits; veclen++) { - std::vector word_vec = get_random_vec(veclen); - vec_type test(word_vec.begin(), word_vec.end()); - EXPECT_TRUE(std::equal( - test.begin(), - test.end(), - bit::bit_iterator(word_vec.begin()), - bit::bit_iterator(word_vec.end()))); + constexpr auto digits = bit::binary_digits::value; + for (unsigned int veclen = 0; veclen < 4 * digits; veclen++) { + std::vector word_vec = get_random_vec(veclen); + vec_type test(word_vec.begin(), word_vec.end()); + EXPECT_TRUE(std::equal( + test.begin(), + test.end(), + bit::bit_iterator(word_vec.begin()), + bit::bit_iterator(word_vec.end()))); } } @@ -140,20 +144,21 @@ TYPED_TEST(VectorTest, StringConstructor) { EXPECT_EQ(false, static_cast(this->v3_[0])); EXPECT_EQ(true, static_cast(this->v3_[8])); using WordType = typename TestFixture::base_type; - for (unsigned int strlen = 0; strlen < 4*this->digits; strlen++) { - std::string rand_bs(strlen, 0); - this->empty_vec_bool.clear(); - for (auto& pos: rand_bs) { - pos = generate_random_number('0', '1'); - this->empty_vec_bool.push_back(pos == '1'); - } - this->empty_vec = bit::bit_vector(rand_bs); - EXPECT_TRUE(std::equal( - this->empty_vec.begin(), - this->empty_vec.end(), - this->empty_vec_bool.begin(), - this->empty_vec_bool.end(), - comparator)); + constexpr auto digits = bit::binary_digits::value; + for (unsigned int strlen = 0; strlen < 4 * digits; strlen++) { + std::string rand_bs(strlen, 0); + this->empty_vec_bool.clear(); + for (auto& pos : rand_bs) { + pos = generate_random_number('0', '1'); + this->empty_vec_bool.push_back(pos == '1'); + } + this->empty_vec = bit::bit_vector(rand_bs); + EXPECT_TRUE(std::equal( + this->empty_vec.begin(), + this->empty_vec.end(), + this->empty_vec_bool.begin(), + this->empty_vec_bool.end(), + comparator)); } } @@ -262,18 +267,20 @@ TYPED_TEST(VectorTest, BracketWrite) { // Test at TYPED_TEST(VectorTest, AtRead) { - EXPECT_EQ(this->v3_.at(0), bit::bit0); - EXPECT_EQ(this->v3_.at(8), bit::bit1); - for (unsigned int vec_idx = 0; vec_idx < this->random_bitvecs.size(); ++vec_idx) { - auto& bitvec = this->random_bitvecs[vec_idx]; - auto& boolvec = this->random_boolvecs[vec_idx]; - for (unsigned int i = 0; i < boolvec.size(); i++) { - EXPECT_TRUE(comparator(bitvec.at(i), boolvec.at(i))); - } - for (unsigned int i = boolvec.size(); i < boolvec.size() + 4*this->digits; i++) { - EXPECT_THROW(bitvec.at(i), std::out_of_range); - } + using WordType = typename TestFixture::base_type; + constexpr auto digits = bit::binary_digits::value; + EXPECT_EQ(this->v3_.at(0), bit::bit0); + EXPECT_EQ(this->v3_.at(8), bit::bit1); + for (unsigned int vec_idx = 0; vec_idx < this->random_bitvecs.size(); ++vec_idx) { + auto& bitvec = this->random_bitvecs[vec_idx]; + auto& boolvec = this->random_boolvecs[vec_idx]; + for (unsigned int i = 0; i < boolvec.size(); i++) { + EXPECT_TRUE(comparator(bitvec.at(i), boolvec.at(i))); + } + for (unsigned int i = boolvec.size(); i < boolvec.size() + 4 * digits; i++) { + EXPECT_THROW(bitvec.at(i), std::out_of_range); } + } } @@ -314,20 +321,22 @@ TYPED_TEST(VectorTest, ReserveAndCapacity) { // Test shrink_to_fit TYPED_TEST(VectorTest, ShrinkToFit) { - this->empty_vec.shrink_to_fit(); - EXPECT_EQ(this->empty_vec.capacity(), 0); - this->empty_vec.reserve(12345); - this->empty_vec.shrink_to_fit(); - EXPECT_EQ(this->empty_vec.capacity(), 0); - for (unsigned int vec_idx = 0; vec_idx < this->random_bitvecs.size(); ++vec_idx) { - auto& bitvec = this->random_bitvecs[vec_idx]; - for (unsigned int _ = 0; _ < this->digits; _++) { - bitvec.pop_back(); - } - auto old_cap = bitvec.capacity(); - bitvec.shrink_to_fit(); - EXPECT_LT(bitvec.capacity(), old_cap); - } + using WordType = typename TestFixture::base_type; + constexpr auto digits = bit::binary_digits::value; + this->empty_vec.shrink_to_fit(); + EXPECT_EQ(this->empty_vec.capacity(), 0); + this->empty_vec.reserve(12345); + this->empty_vec.shrink_to_fit(); + EXPECT_EQ(this->empty_vec.capacity(), 0); + for (unsigned int vec_idx = 0; vec_idx < this->random_bitvecs.size(); ++vec_idx) { + auto& bitvec = this->random_bitvecs[vec_idx]; + for (unsigned int _ = 0; _ < digits; _++) { + bitvec.pop_back(); + } + auto old_cap = bitvec.capacity(); + bitvec.shrink_to_fit(); + EXPECT_LT(bitvec.capacity(), old_cap); + } } /* @@ -356,145 +365,157 @@ TYPED_TEST(VectorTest, Clear) { // Test insert TYPED_TEST(VectorTest, InsertAtEnd1) { - // First signature - for (auto _ = 64*this->digits; _--;) { - bool to_insert_bool = generate_random_number(0, 1) > 0 ? true : false; - bit::bit_value to_insert_bit = to_insert_bool ? bit::bit1 : bit::bit0; - auto bitret = this->empty_vec.insert( - this->empty_vec.end(), - to_insert_bit); - auto boolret = this->empty_vec_bool.insert( - this->empty_vec_bool.end(), - to_insert_bool); - EXPECT_TRUE(std::equal( - this->empty_vec.begin(), - this->empty_vec.end(), - this->empty_vec_bool.begin(), - this->empty_vec_bool.end(), - comparator)); - EXPECT_EQ( - std::distance(this->empty_vec.begin(), bitret), - std::distance(this->empty_vec_bool.begin(), boolret)); - } + using WordType = typename TestFixture::base_type; + constexpr auto digits = bit::binary_digits::value; + // First signature + for (auto _ = 64 * digits; _--;) { + bool to_insert_bool = generate_random_number(0, 1) > 0 ? true : false; + bit::bit_value to_insert_bit = to_insert_bool ? bit::bit1 : bit::bit0; + auto bitret = this->empty_vec.insert( + this->empty_vec.end(), + to_insert_bit); + auto boolret = this->empty_vec_bool.insert( + this->empty_vec_bool.end(), + to_insert_bool); + EXPECT_TRUE(std::equal( + this->empty_vec.begin(), + this->empty_vec.end(), + this->empty_vec_bool.begin(), + this->empty_vec_bool.end(), + comparator)); + EXPECT_EQ( + std::distance(this->empty_vec.begin(), bitret), + std::distance(this->empty_vec_bool.begin(), boolret)); + } } TYPED_TEST(VectorTest, InsertAtBegin1) { - // First signature - for (auto _ = 64*this->digits; _--;) { - bool to_insert_bool = generate_random_number(0, 1) > 0 ? true : false; - bit::bit_value to_insert_bit = to_insert_bool ? bit::bit1 : bit::bit0; - auto bitret = this->empty_vec.insert( - this->empty_vec.begin(), - to_insert_bit); - auto boolret = this->empty_vec_bool.insert( - this->empty_vec_bool.begin(), - to_insert_bool); - EXPECT_TRUE(std::equal( - this->empty_vec.begin(), - this->empty_vec.end(), - this->empty_vec_bool.begin(), - this->empty_vec_bool.end(), - comparator)); - EXPECT_EQ( - std::distance(this->empty_vec.begin(), bitret), - std::distance(this->empty_vec_bool.begin(), boolret)); - } + using WordType = typename TestFixture::base_type; + constexpr auto digits = bit::binary_digits::value; + // First signature + for (auto _ = 64 * digits; _--;) { + bool to_insert_bool = generate_random_number(0, 1) > 0 ? true : false; + bit::bit_value to_insert_bit = to_insert_bool ? bit::bit1 : bit::bit0; + auto bitret = this->empty_vec.insert( + this->empty_vec.begin(), + to_insert_bit); + auto boolret = this->empty_vec_bool.insert( + this->empty_vec_bool.begin(), + to_insert_bool); + EXPECT_TRUE(std::equal( + this->empty_vec.begin(), + this->empty_vec.end(), + this->empty_vec_bool.begin(), + this->empty_vec_bool.end(), + comparator)); + EXPECT_EQ( + std::distance(this->empty_vec.begin(), bitret), + std::distance(this->empty_vec_bool.begin(), boolret)); + } } TYPED_TEST(VectorTest, InsertAtRand1) { - // First signature - for (auto _ = 64*this->digits; _--;) { - auto insert_location = generate_random_number(0, this->empty_vec.size()); - bool to_insert_bool = generate_random_number(0, 1) > 0 ? true : false; - bit::bit_value to_insert_bit = to_insert_bool ? bit::bit1 : bit::bit0; - auto bitret = this->empty_vec.insert( - this->empty_vec.begin() + insert_location, - to_insert_bit); - auto boolret = this->empty_vec_bool.insert( - this->empty_vec_bool.begin() + insert_location, - to_insert_bool); - EXPECT_TRUE(std::equal( - this->empty_vec.begin(), - this->empty_vec.end(), - this->empty_vec_bool.begin(), - this->empty_vec_bool.end(), - comparator)); - EXPECT_EQ( - std::distance(this->empty_vec.begin(), bitret), - std::distance(this->empty_vec_bool.begin(), boolret)); - } + using WordType = typename TestFixture::base_type; + constexpr auto digits = bit::binary_digits::value; + // First signature + for (auto _ = 64 * digits; _--;) { + auto insert_location = generate_random_number(0, this->empty_vec.size()); + bool to_insert_bool = generate_random_number(0, 1) > 0 ? true : false; + bit::bit_value to_insert_bit = to_insert_bool ? bit::bit1 : bit::bit0; + auto bitret = this->empty_vec.insert( + this->empty_vec.begin() + insert_location, + to_insert_bit); + auto boolret = this->empty_vec_bool.insert( + this->empty_vec_bool.begin() + insert_location, + to_insert_bool); + EXPECT_TRUE(std::equal( + this->empty_vec.begin(), + this->empty_vec.end(), + this->empty_vec_bool.begin(), + this->empty_vec_bool.end(), + comparator)); + EXPECT_EQ( + std::distance(this->empty_vec.begin(), bitret), + std::distance(this->empty_vec_bool.begin(), boolret)); + } } TYPED_TEST(VectorTest, InsertAtBegin2) { - // Second signature - for (auto _ = 16; _--;) { - auto to_insert = generate_random_number(0, 4*this->digits); - auto bitret = this->empty_vec.insert( - this->empty_vec.begin(), - to_insert, - bit::bit1); - auto boolret = this->empty_vec_bool.insert( - this->empty_vec_bool.begin(), - to_insert, - true); - EXPECT_TRUE(std::equal( - this->empty_vec.begin(), - this->empty_vec.end(), - this->empty_vec_bool.begin(), - this->empty_vec_bool.end(), - comparator)); - EXPECT_EQ( - std::distance(this->empty_vec.begin(), bitret), - std::distance(this->empty_vec_bool.begin(), boolret)); - } + using WordType = typename TestFixture::base_type; + constexpr auto digits = bit::binary_digits::value; + // Second signature + for (auto _ = 16; _--;) { + auto to_insert = generate_random_number(0, 4 * digits); + auto bitret = this->empty_vec.insert( + this->empty_vec.begin(), + to_insert, + bit::bit1); + auto boolret = this->empty_vec_bool.insert( + this->empty_vec_bool.begin(), + to_insert, + true); + EXPECT_TRUE(std::equal( + this->empty_vec.begin(), + this->empty_vec.end(), + this->empty_vec_bool.begin(), + this->empty_vec_bool.end(), + comparator)); + EXPECT_EQ( + std::distance(this->empty_vec.begin(), bitret), + std::distance(this->empty_vec_bool.begin(), boolret)); + } } TYPED_TEST(VectorTest, InsertAtEnd2) { - // Second signature - for (auto _ = 16; _--;) { - auto to_insert = generate_random_number(0, 444*this->digits); - auto bitret = this->empty_vec.insert( - this->empty_vec.end(), - to_insert, - bit::bit1); - auto boolret = this->empty_vec_bool.insert( - this->empty_vec_bool.end(), - to_insert, - true); - EXPECT_TRUE(std::equal( - this->empty_vec.begin(), - this->empty_vec.end(), - this->empty_vec_bool.begin(), - this->empty_vec_bool.end(), - comparator)); - EXPECT_EQ( - std::distance(this->empty_vec.begin(), bitret), - std::distance(this->empty_vec_bool.begin(), boolret)); - } + using WordType = typename TestFixture::base_type; + constexpr auto digits = bit::binary_digits::value; + // Second signature + for (auto _ = 16; _--;) { + auto to_insert = generate_random_number(0, 444 * digits); + auto bitret = this->empty_vec.insert( + this->empty_vec.end(), + to_insert, + bit::bit1); + auto boolret = this->empty_vec_bool.insert( + this->empty_vec_bool.end(), + to_insert, + true); + EXPECT_TRUE(std::equal( + this->empty_vec.begin(), + this->empty_vec.end(), + this->empty_vec_bool.begin(), + this->empty_vec_bool.end(), + comparator)); + EXPECT_EQ( + std::distance(this->empty_vec.begin(), bitret), + std::distance(this->empty_vec_bool.begin(), boolret)); + } } TYPED_TEST(VectorTest, InsertAtRand2) { - // Second signature - for (auto _ = 16; _--;) { - auto to_insert = generate_random_number(0, 4*this->digits); - auto insert_location = generate_random_number(0, this->empty_vec.size()); - auto bitret = this->empty_vec.insert( - this->empty_vec.begin() + insert_location, - to_insert, - bit::bit1); - auto boolret = this->empty_vec_bool.insert( - this->empty_vec_bool.begin() + insert_location, - to_insert, - true); - EXPECT_TRUE(std::equal( - this->empty_vec.begin(), - this->empty_vec.end(), - this->empty_vec_bool.begin(), - this->empty_vec_bool.end(), - comparator)); - EXPECT_EQ( - std::distance(this->empty_vec.begin(), bitret), - std::distance(this->empty_vec_bool.begin(), boolret)); - } + using WordType = typename TestFixture::base_type; + constexpr auto digits = bit::binary_digits::value; + // Second signature + for (auto _ = 16; _--;) { + auto to_insert = generate_random_number(0, 4 * digits); + auto insert_location = generate_random_number(0, this->empty_vec.size()); + auto bitret = this->empty_vec.insert( + this->empty_vec.begin() + insert_location, + to_insert, + bit::bit1); + auto boolret = this->empty_vec_bool.insert( + this->empty_vec_bool.begin() + insert_location, + to_insert, + true); + EXPECT_TRUE(std::equal( + this->empty_vec.begin(), + this->empty_vec.end(), + this->empty_vec_bool.begin(), + this->empty_vec_bool.end(), + comparator)); + EXPECT_EQ( + std::distance(this->empty_vec.begin(), bitret), + std::distance(this->empty_vec_bool.begin(), boolret)); + } } TYPED_TEST(VectorTest, InsertAtBegin3) { @@ -710,42 +731,46 @@ TYPED_TEST(VectorTest, EraseAtRand2) { // Test push_back TYPED_TEST(VectorTest, PushBack) { - // First signature - for (unsigned int vec_idx = 0; vec_idx < this->random_bitvecs.size(); ++vec_idx) { - for (auto _ = 4*this->digits; _ > 0; _--) { - auto& bitvec = this->random_bitvecs[vec_idx]; - auto& boolvec = this->random_boolvecs[vec_idx]; - bool to_insert_bool = generate_random_number(0, 1) > 0 ? true : false; - bit::bit_value to_insert_bit = to_insert_bool ? bit::bit1 : bit::bit0; - bitvec.push_back(to_insert_bit); - boolvec.push_back(to_insert_bool); - EXPECT_TRUE(std::equal( - bitvec.begin(), - bitvec.end(), - boolvec.begin(), - boolvec.end(), - comparator)); - } + using WordType = typename TestFixture::base_type; + constexpr auto digits = bit::binary_digits::value; + // First signature + for (unsigned int vec_idx = 0; vec_idx < this->random_bitvecs.size(); ++vec_idx) { + for (auto _ = 4 * digits; _ > 0; _--) { + auto& bitvec = this->random_bitvecs[vec_idx]; + auto& boolvec = this->random_boolvecs[vec_idx]; + bool to_insert_bool = generate_random_number(0, 1) > 0 ? true : false; + bit::bit_value to_insert_bit = to_insert_bool ? bit::bit1 : bit::bit0; + bitvec.push_back(to_insert_bit); + boolvec.push_back(to_insert_bool); + EXPECT_TRUE(std::equal( + bitvec.begin(), + bitvec.end(), + boolvec.begin(), + boolvec.end(), + comparator)); } + } } // Test pop_back TYPED_TEST(VectorTest, PopBack) { - // First signature - for (unsigned int vec_idx = 0; vec_idx < this->random_bitvecs.size(); ++vec_idx) { - auto& bitvec = this->random_bitvecs[vec_idx]; - auto& boolvec = this->random_boolvecs[vec_idx]; - for (auto _ = std::min(boolvec.size(), 4*this->digits); _>0; _--) { - bitvec.pop_back(); - boolvec.pop_back(); - EXPECT_TRUE(std::equal( - bitvec.begin(), - bitvec.end(), - boolvec.begin(), - boolvec.end(), - comparator)); - } + using WordType = typename TestFixture::base_type; + constexpr auto digits = bit::binary_digits::value; + // First signature + for (unsigned int vec_idx = 0; vec_idx < this->random_bitvecs.size(); ++vec_idx) { + auto& bitvec = this->random_bitvecs[vec_idx]; + auto& boolvec = this->random_boolvecs[vec_idx]; + for (auto _ = std::min(boolvec.size(), 4 * digits); _ > 0; _--) { + bitvec.pop_back(); + boolvec.pop_back(); + EXPECT_TRUE(std::equal( + bitvec.begin(), + bitvec.end(), + boolvec.begin(), + boolvec.end(), + comparator)); } + } } TEST(BitVectorTest, Slice) { From 1916263c3db90046d36370b0076450f50b1a56be Mon Sep 17 00:00:00 2001 From: Peter McLean Date: Sun, 6 Jul 2025 01:13:23 -0400 Subject: [PATCH 12/13] Prevent some aliasing in the test code which clutters warnings --- include/bitlib/bit-algorithms/shift.hpp | 3 - include/bitlib/bit-iterator/bit_details.hpp | 1 - test/src/fixtures.hpp | 4 +- test/src/test-copy.cpp | 8 +- test/src/test-equal.cpp | 8 +- test/src/test-iterator_adapter.cpp | 10 -- test/src/vector_test.cpp | 122 ++++++++++---------- 7 files changed, 69 insertions(+), 87 deletions(-) diff --git a/include/bitlib/bit-algorithms/shift.hpp b/include/bitlib/bit-algorithms/shift.hpp index 279877bc..e44c8f82 100644 --- a/include/bitlib/bit-algorithms/shift.hpp +++ b/include/bitlib/bit-algorithms/shift.hpp @@ -98,9 +98,6 @@ bit_iterator shift_left( write_word(new_word, first, d - n); return first + d - n; } - // Multiple word case - word_type first_value = *first.base(); - word_type last_value = !is_last_aligned ? *last.base() : 0; // Align first if (!is_first_aligned) { diff --git a/include/bitlib/bit-iterator/bit_details.hpp b/include/bitlib/bit-iterator/bit_details.hpp index 87612b2f..cac7b81f 100644 --- a/include/bitlib/bit-iterator/bit_details.hpp +++ b/include/bitlib/bit-iterator/bit_details.hpp @@ -869,7 +869,6 @@ template constexpr void _bitexch(T& src0, T& src1, S start0, S start1, S len) noexcept { static_assert(binary_digits::value, ""); - constexpr auto digits = binary_digits::value; const T msk = _mask(len); if (start0 >= start1) { src0 = src0 ^ ( diff --git a/test/src/fixtures.hpp b/test/src/fixtures.hpp index 6317786e..b2d6c36b 100644 --- a/test/src/fixtures.hpp +++ b/test/src/fixtures.hpp @@ -47,9 +47,9 @@ class VectorTest : public testing::Test { std::vector> random_boolvecs; std::vector random_vec; void SetUp() override { - const size_t word_size = 4; - const size_t bit_size = word_size * bit::binary_digits::value; const size_t digits = bit::binary_digits::value; + const size_t word_size = 4; + const size_t bit_size = word_size * digits; empty_vec = vec_type(); random_vec = get_random_vec(word_size); for (size_t cont_size = 1; cont_size < bit_size; ++cont_size) { diff --git a/test/src/test-copy.cpp b/test/src/test-copy.cpp index f1b3187b..045fe743 100644 --- a/test/src/test-copy.cpp +++ b/test/src/test-copy.cpp @@ -74,11 +74,9 @@ TYPED_TEST(DoubleRangeTest, Copy) { TYPED_TEST(MixedDoubleRangeTest, Copy) { for (size_t idx = 0; idx < this->random_bitvecs1.size(); ++idx) { - using FromWordType = typename TestFixture::FromWordType; - using ToWordType = typename TestFixture::ToWordType; - bit::bit_vector& bitvec1 = this->random_bitvecs1[idx]; - bit::bit_vector& bitvec2 = this->random_bitvecs2[idx]; - constexpr auto min_digits = std::min(bit::bitsof(), bit::bitsof()); + bit::bit_vector& bitvec1 = this->random_bitvecs1[idx]; + bit::bit_vector& bitvec2 = this->random_bitvecs2[idx]; + constexpr auto min_digits = std::min(bit::bitsof(), bit::bitsof()); std::vector& boolvec1 = this->random_boolvecs1[idx]; std::vector& boolvec2 = this->random_boolvecs2[idx]; long long start1 = generate_random_number( diff --git a/test/src/test-equal.cpp b/test/src/test-equal.cpp index 2a842aa5..01355f3a 100644 --- a/test/src/test-equal.cpp +++ b/test/src/test-equal.cpp @@ -77,11 +77,9 @@ TYPED_TEST(DoubleRangeTest, Equal) { TYPED_TEST(MixedDoubleRangeTest, Equal) { for (size_t idx = 0; idx < this->random_bitvecs1.size(); ++idx) { - using FromWordType = typename TestFixture::FromWordType; - using ToWordType = typename TestFixture::ToWordType; - bit::bit_vector& bitvec1 = this->random_bitvecs1[idx]; - bit::bit_vector& bitvec2 = this->random_bitvecs2[idx]; - constexpr auto min_digits = std::min(bit::bitsof(), bit::bitsof()); + bit::bit_vector& bitvec1 = this->random_bitvecs1[idx]; + bit::bit_vector& bitvec2 = this->random_bitvecs2[idx]; + constexpr auto min_digits = std::min(bit::bitsof(), bit::bitsof()); std::vector& boolvec1 = this->random_boolvecs1[idx]; std::vector& boolvec2 = this->random_boolvecs2[idx]; long long start1 = generate_random_number( diff --git a/test/src/test-iterator_adapter.cpp b/test/src/test-iterator_adapter.cpp index 7607d420..81b94f7f 100644 --- a/test/src/test-iterator_adapter.cpp +++ b/test/src/test-iterator_adapter.cpp @@ -45,16 +45,6 @@ TEST(IteratorAdapter, Basic) { EXPECT_EQ(*adapter, 0x56); } -// ----------------------------------------------------------------------------- -// Helper: Convert a 32‐bit word into its 4 individual bytes (little‐endian) -// ----------------------------------------------------------------------------- -static void split_u32_le(uint32_t value, uint8_t out_bytes[4]) { - out_bytes[0] = static_cast(value & 0xFFu); - out_bytes[1] = static_cast((value >> 8) & 0xFFu); - out_bytes[2] = static_cast((value >> 16) & 0xFFu); - out_bytes[3] = static_cast((value >> 24) & 0xFFu); -} - // ----------------------------------------------------------------------------- // TEST SUITE: Big-to-Small Mode (BaseIterator.value_type > Iterator.value_type) // ----------------------------------------------------------------------------- diff --git a/test/src/vector_test.cpp b/test/src/vector_test.cpp index 149d14b0..78c5e241 100644 --- a/test/src/vector_test.cpp +++ b/test/src/vector_test.cpp @@ -34,9 +34,9 @@ TYPED_TEST(VectorTest, SizeInitializerConstructor) { } using WordType = typename TestFixture::base_type; constexpr auto digits = bit::binary_digits::value; - using vec_type = typename TestFixture::vec_type; + using VecType = typename TestFixture::vec_type; for (unsigned int veclen = 0; veclen < 4 * digits; veclen++) { - this->empty_vec = vec_type(veclen); + this->empty_vec = VecType(veclen); for (unsigned int i = 0; i < veclen; ++i) { EXPECT_FALSE(this->empty_vec[i]); } @@ -52,38 +52,38 @@ TYPED_TEST(VectorTest, SizeInitializerConstructor) { } TYPED_TEST(VectorTest, CountValueConstructor) { - using vec_type = typename TestFixture::vec_type; - using WordType = typename TestFixture::base_type; - constexpr auto digits = bit::binary_digits::value; - for (unsigned int veclen = 0; veclen < 4 * digits; veclen++) { - this->empty_vec = vec_type(veclen, bit::bit1); - unsigned int i = 0; - // TODO misplaced test for range-based for loop - for (auto bv : this->empty_vec) { - EXPECT_TRUE(bv); - i++; - } - EXPECT_EQ(i, veclen); - this->empty_vec = vec_type(veclen, bit::bit0); - i = 0; - // TODO misplaced test for range-based for loop - for (auto bv : this->empty_vec) { - EXPECT_FALSE(bv); - i++; - } - EXPECT_EQ(i, veclen); + using VecType = typename TestFixture::vec_type; + using WordType = typename TestFixture::base_type; + constexpr auto digits = bit::binary_digits::value; + for (unsigned int veclen = 0; veclen < 4 * digits; veclen++) { + this->empty_vec = VecType(veclen, bit::bit1); + unsigned int i = 0; + // TODO misplaced test for range-based for loop + for (auto bv : this->empty_vec) { + EXPECT_TRUE(bv); + i++; + } + EXPECT_EQ(i, veclen); + this->empty_vec = VecType(veclen, bit::bit0); + i = 0; + // TODO misplaced test for range-based for loop + for (auto bv : this->empty_vec) { + EXPECT_FALSE(bv); + i++; } + EXPECT_EQ(i, veclen); + } } // Test when first, last are WordType iterators TYPED_TEST(VectorTest, WordIterPairConstructor) { using WordType = typename TestFixture::base_type; - using vec_type = typename TestFixture::vec_type; + using VecType = typename TestFixture::vec_type; using iterator_type = typename std::vector::iterator; constexpr auto digits = bit::binary_digits::value; for (unsigned int veclen = 0; veclen < 4 * digits; veclen++) { std::vector word_vec = get_random_vec(veclen); - vec_type test(word_vec.begin(), word_vec.end()); + VecType test(word_vec.begin(), word_vec.end()); EXPECT_TRUE(std::equal( test.begin(), test.end(), @@ -94,48 +94,48 @@ TYPED_TEST(VectorTest, WordIterPairConstructor) { // Test when first, last are bool iterators TYPED_TEST(VectorTest, BoolIterPairConstructor) { - using vec_type = typename TestFixture::vec_type; - for (unsigned int vec_idx = 0; vec_idx < this->random_bitvecs.size(); ++vec_idx) { - auto& boolvec = this->random_boolvecs[vec_idx]; - vec_type test = vec_type(boolvec.begin(), boolvec.end()); - EXPECT_TRUE(std::equal( - test.begin(), - test.end(), - boolvec.begin(), - boolvec.end(), - comparator)); - } + using VecType = typename TestFixture::vec_type; + for (unsigned int vec_idx = 0; vec_idx < this->random_bitvecs.size(); ++vec_idx) { + auto& boolvec = this->random_boolvecs[vec_idx]; + VecType test = VecType(boolvec.begin(), boolvec.end()); + EXPECT_TRUE(std::equal( + test.begin(), + test.end(), + boolvec.begin(), + boolvec.end(), + comparator)); + } } // Test copy ctor TYPED_TEST(VectorTest, CopyConstructor) { - using vec_type = typename TestFixture::vec_type; - for (unsigned int vec_idx = 0; vec_idx < this->random_bitvecs.size(); ++vec_idx) { - auto& bitvec = this->random_bitvecs[vec_idx]; - auto& boolvec = this->random_boolvecs[vec_idx]; - vec_type test = vec_type(bitvec); - EXPECT_TRUE(std::equal( - test.begin(), - test.end(), - boolvec.begin(), - boolvec.end(), - comparator)); - } + using VecType = typename TestFixture::vec_type; + for (unsigned int vec_idx = 0; vec_idx < this->random_bitvecs.size(); ++vec_idx) { + auto& bitvec = this->random_bitvecs[vec_idx]; + auto& boolvec = this->random_boolvecs[vec_idx]; + VecType test = VecType(bitvec); + EXPECT_TRUE(std::equal( + test.begin(), + test.end(), + boolvec.begin(), + boolvec.end(), + comparator)); + } } TYPED_TEST(VectorTest, MoveConstructor) { - using vec_type = typename TestFixture::vec_type; - for (unsigned int vec_idx = 0; vec_idx < this->random_bitvecs.size(); ++vec_idx) { - auto& bitvec = this->random_bitvecs[vec_idx]; - auto& boolvec = this->random_boolvecs[vec_idx]; - vec_type test = vec_type(std::move(bitvec)); - EXPECT_TRUE(std::equal( - test.begin(), - test.end(), - boolvec.begin(), - boolvec.end(), - comparator)); - } + using VecType = typename TestFixture::vec_type; + for (unsigned int vec_idx = 0; vec_idx < this->random_bitvecs.size(); ++vec_idx) { + auto& bitvec = this->random_bitvecs[vec_idx]; + auto& boolvec = this->random_boolvecs[vec_idx]; + VecType test = VecType(std::move(bitvec)); + EXPECT_TRUE(std::equal( + test.begin(), + test.end(), + boolvec.begin(), + boolvec.end(), + comparator)); + } } // Tests the string c'tor. @@ -218,9 +218,9 @@ TYPED_TEST(VectorTest, MoveAssignment) { // Test the initializer list c'tor TYPED_TEST(VectorTest, InitializerListConstructor) { bit::bit_vector v2_copy = this->v2_; - using vec_type = typename TestFixture::vec_type; + using VecType = typename TestFixture::vec_type; std::vector boolvec {true, false, true, true, true, false, false, true, false, true, true, false}; - vec_type test {true, false, true, true, true, false, false, true, false, true, true, false}; + VecType test{true, false, true, true, true, false, false, true, false, true, true, false}; EXPECT_TRUE(std::equal( test.begin(), test.end(), From 9e82be8c8f588d4b31f266349d6e23f6e2459342 Mon Sep 17 00:00:00 2001 From: Peter McLean Date: Sun, 6 Jul 2025 01:19:12 -0400 Subject: [PATCH 13/13] Avoid unused variable --- include/bitlib/bit-algorithms/shift.hpp | 26 ++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/include/bitlib/bit-algorithms/shift.hpp b/include/bitlib/bit-algorithms/shift.hpp index e44c8f82..c93da4ea 100644 --- a/include/bitlib/bit-algorithms/shift.hpp +++ b/include/bitlib/bit-algorithms/shift.hpp @@ -283,19 +283,19 @@ bit_iterator shift_right( // Shift bit sequence to the msb if (offset == 0) { - auto new_first = bit::bit_iterator( - STD_SHIFT_RIGHT( - first.base(), - last.base(), - word_shifts), - first.position() - ); - // https://en.cppreference.com/w/cpp/algorithm/shift - // "Elements that are in the original range but not the new range - // are left in a valid but unspecified state." - // - //bit::fill(first, new_first, bit::bit0); - return first + n; + /*auto new_first = */ + static_cast(bit::bit_iterator( + STD_SHIFT_RIGHT( + first.base(), + last.base(), + word_shifts), + first.position())); + // https://en.cppreference.com/w/cpp/algorithm/shift + // "Elements that are in the original range but not the new range + // are left in a valid but unspecified state." + // + //bit::fill(first, new_first, bit::bit0); + return first + n; } if (bit::distance(first, middle) >= digits)