diff --git a/include/bitlib/bit-algorithms/accumulate.hpp b/include/bitlib/bit-algorithms/accumulate.hpp index f01c0833..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) { @@ -90,7 +88,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-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/shift.hpp b/include/bitlib/bit-algorithms/shift.hpp index 279877bc..c93da4ea 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) { @@ -286,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) diff --git a/include/bitlib/bit-algorithms/to_from_string.hpp b/include/bitlib/bit-algorithms/to_from_string.hpp index faf98b0e..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/array_dynamic_extent.hpp" -#include "bitlib/bit-containers/bit_vector.hpp" #include "bitlib/bit_concepts.hpp" namespace bit { @@ -109,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, @@ -145,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; @@ -158,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 diff --git a/include/bitlib/bit-containers/bit_array.hpp b/include/bitlib/bit-containers/bit_array.hpp index 23263fc0..a6e87d67 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 { @@ -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; @@ -108,13 +109,13 @@ class array : public array_base, T, N, W, Policy, detail::array_i this->from_integral(integral); } - constexpr array(const array& other) noexcept - : storage(other.storage) {} + constexpr array(const array& other) noexcept + : base(), storage(other.storage) {} - constexpr array(const array&& other) noexcept - : storage(other.storage) {} + constexpr array(const array&& other) noexcept + : 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."); } @@ -123,21 +124,21 @@ class array : public array_base, T, N, W, Policy, detail::array_i 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) { @@ -147,7 +148,7 @@ class array : public array_base, T, N, W, Policy, detail::array_i 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."); }; @@ -209,7 +210,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_base.hpp b/include/bitlib/bit-containers/bit_array_base.hpp index af75d2bc..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 @@ -193,7 +198,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 +207,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_array_dynamic_extent.hpp b/include/bitlib/bit-containers/bit_array_dynamic_extent.hpp index 57907fbd..3c334dbc 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; @@ -58,11 +59,12 @@ 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; - struct Storage { union { word_type_ptr pointer; @@ -152,72 +154,72 @@ class array */ array() = delete; - constexpr array(const size_type size, const Allocator& allocator = Allocator()) - : m_size(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()) - : m_size(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()) - : m_size(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) - : m_size(size), storage(Words(size), allocator, detail::uninitialized) { + : base(extent), storage(Words(extent), 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()) - : array(other.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)) { + constexpr array(array&& other) + : 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) { + constexpr array(array&& other, const Allocator& 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()); } #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()) { + 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') { @@ -231,9 +233,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 extent"); } if (this == &other) [[unlikely]] { return *this; @@ -242,7 +244,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 +252,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 extent"); } - array temp(std::move(other)); + array temp(std::move(other)); swap(temp); return *this; } @@ -297,17 +299,10 @@ class array } } - /* - * Capacity - */ - constexpr size_type size() const noexcept { - return m_size; - } - /* * 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); @@ -319,8 +314,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!"); diff --git a/include/bitlib/bit-containers/bit_array_ref.hpp b/include/bitlib/bit-containers/bit_array_ref.hpp index 5706b6e0..796858a4 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 @@ -77,22 +77,30 @@ 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) - : m_storage(storage), - m_size(size) { + constexpr array_ref(word_type* storage, size_type extent) + requires(N == std::dynamic_extent) + : base(extent), m_storage(storage) { + } + constexpr array_ref(word_type* storage) + requires(N != std::dynamic_extent) + : base(), m_storage(storage) { } /** * @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) - : m_storage(storage), - m_size(size) { + constexpr array_ref(bit_pointer storage, size_type extent) + requires(N == std::dynamic_extent) + : base(extent), m_storage(storage) { + } + constexpr array_ref(bit_pointer storage) + requires(N != std::dynamic_extent) + : base(), m_storage(storage) { } /** @@ -100,10 +108,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) { - assert(size <= (other.end() - other.begin())); + constexpr array_ref(bit_range auto& other, size_type extent) + requires(N == std::dynamic_extent) + : base(extent), m_storage(&(*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 <= static_cast(other.end() - other.begin())); } /** @@ -111,11 +124,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) { - assert(size <= (other.end() - other.begin())); + constexpr array_ref(const bit_range auto& other, size_type extent) + requires((N == std::dynamic_extent) && std::is_const_v) + : 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) + : base(), m_storage(&(*other.begin())) { + assert(N <= (other.end() - other.begin())); } /** @@ -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 a948a117..9b8cd82b 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]; @@ -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_policy.hpp b/include/bitlib/bit-containers/bit_policy.hpp index 03943f0e..844ecd93 100644 --- a/include/bitlib/bit-containers/bit_policy.hpp +++ b/include/bitlib/bit-containers/bit_policy.hpp @@ -65,11 +65,15 @@ struct sign_extend { 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 { + ::bit::fill(integral_begin + value.size(), integral_begin + bitsof(), bit0); } } else { if constexpr (std::is_signed_v) { - ::bit::fill(integral_begin + N, integral_begin + bitsof(), value.begin()[N - 1]); + ::bit::fill(integral_begin + value.size(), integral_begin + bitsof(), value.begin()[N - 1]); + } else { + ::bit::fill(integral_begin + value.size(), integral_begin + bitsof(), bit0); } } } @@ -92,13 +96,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); } } }; diff --git a/include/bitlib/bit-containers/bit_span.hpp b/include/bitlib/bit-containers/bit_span.hpp index d7afe202..7eaf466b 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; + 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,43 +296,43 @@ 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 -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 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-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_details.hpp b/include/bitlib/bit-iterator/bit_details.hpp index bd602267..cac7b81f 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)); } // -------------------------------------------------------------------------- // @@ -866,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 ^ ( @@ -1112,6 +1114,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/include/bitlib/bit-iterator/bit_reference.hpp b/include/bitlib/bit-iterator/bit_reference.hpp index 55fc4bf7..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); @@ -80,6 +75,7 @@ class bit_reference { // Access public: constexpr bit_pointer operator&() const noexcept; + constexpr bit_pointer operator&() noexcept; // Swap members public: @@ -227,6 +223,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)); +} // -------------------------------------------------------------------------- // 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..b2d6c36b 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 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) { @@ -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 @@ -231,7 +229,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-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-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-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 f8be23d5..81b94f7f 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 @@ -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/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); + } + } + } +} 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..78c5e241 100644 --- a/test/src/vector_test.cpp +++ b/test/src/vector_test.cpp @@ -33,9 +33,10 @@ TYPED_TEST(VectorTest, SizeInitializerConstructor) { EXPECT_FALSE(bv); } using WordType = typename TestFixture::base_type; - using vec_type = typename TestFixture::vec_type; - for (unsigned int veclen = 0; veclen < 4 * this->digits; veclen++) { - this->empty_vec = vec_type(veclen); + constexpr auto digits = bit::binary_digits::value; + using VecType = typename TestFixture::vec_type; + for (unsigned int veclen = 0; veclen < 4 * digits; veclen++) { + this->empty_vec = VecType(veclen); for (unsigned int i = 0; i < veclen; ++i) { EXPECT_FALSE(this->empty_vec[i]); } @@ -51,87 +52,90 @@ 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 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; - 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); + VecType 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()))); } } // 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. @@ -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)); } } @@ -213,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(), @@ -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) {