From d526a57c61f6c2b8d4cc5d42ca4c023e24f910d9 Mon Sep 17 00:00:00 2001 From: ckormanyos Date: Wed, 3 Jun 2026 21:02:06 +0200 Subject: [PATCH 1/4] Update wide integer and dyn array again --- .../functions/math_functions_hypergeometric.h | 6 +- ref_app/src/math/wide_integer/uintwide_t.h | 321 ++++++++++-------- ref_app/src/util/utility/util_dynamic_array.h | 274 ++++++++------- 3 files changed, 332 insertions(+), 269 deletions(-) diff --git a/ref_app/src/math/functions/math_functions_hypergeometric.h b/ref_app/src/math/functions/math_functions_hypergeometric.h index f5a057515..95ceaa850 100644 --- a/ref_app/src/math/functions/math_functions_hypergeometric.h +++ b/ref_app/src/math/functions/math_functions_hypergeometric.h @@ -160,11 +160,13 @@ T x_pow_n_div_n_fact(x); + constexpr std::size_t local_buffer_size { std::size_t { UINT8_C(64) } }; + // Define an allocator type for use in the containers below. - using allocator_type = util::ring_allocator; + using allocator_type = util::ring_allocator; // Define a container type for the upcoming calculation. - using container_type = util::dynamic_array; + using container_type = util::fixed_dynamic_array; // The pochhammer symbols for the multiplications in the series expansion // will be stored in non-constant STL vectors. diff --git a/ref_app/src/math/wide_integer/uintwide_t.h b/ref_app/src/math/wide_integer/uintwide_t.h index 0469fd22a..9aa3af7aa 100644 --- a/ref_app/src/math/wide_integer/uintwide_t.h +++ b/ref_app/src/math/wide_integer/uintwide_t.h @@ -504,7 +504,7 @@ namespace array_detail { - template + template class array { public: @@ -605,26 +605,25 @@ friend constexpr auto operator> (const array& left, const array& right) -> bool { return (right < left); } friend constexpr auto operator>=(const array& left, const array& right) -> bool { return (!(left < right)); } friend constexpr auto operator<=(const array& left, const array& right) -> bool { return (!(right < left)); } - }; - template - constexpr auto swap(array& x, array& y) noexcept -> void - { - swap_ranges_unsafe(x.begin(), x.end(), y.begin()); - } + friend constexpr auto swap(array& x, array& y) noexcept -> void + { + swap_ranges_unsafe(x.begin(), x.end(), y.begin()); + } + }; template class tuple_size; - template + template class tuple_size> : public std::integral_constant { }; template class tuple_element; template + typename T, + const ::std::size_t N> class tuple_element > { static_assert(I < N, "Sorry, tuple_element index is out of bounds."); @@ -662,7 +661,7 @@ typename DiffType> class dynamic_array { - public: + protected: // Type definitions. using allocator_type = typename std::allocator_traits::template rebind_alloc; using value_type = typename allocator_type::value_type; @@ -675,18 +674,98 @@ using size_type = SizeType; using difference_type = DiffType; #if defined(WIDE_INTEGER_NAMESPACE) - using reverse_iterator = WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::iterator_detail::reverse_iterator< value_type*>; - using const_reverse_iterator = WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::iterator_detail::reverse_iterator; + using reverse_iterator = WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::iterator_detail::reverse_iterator; + using const_reverse_iterator = WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::iterator_detail::reverse_iterator; #else - using reverse_iterator = ::math::wide_integer::detail::iterator_detail::reverse_iterator< value_type*>; - using const_reverse_iterator = ::math::wide_integer::detail::iterator_detail::reverse_iterator; + using reverse_iterator = ::math::wide_integer::detail::iterator_detail::reverse_iterator; + using const_reverse_iterator = ::math::wide_integer::detail::iterator_detail::reverse_iterator; #endif + public: static_assert(std::is_integral::value, "Error: the value_type of dynamic_array must be a built-in integral"); - // Constructors. + // Deleted default constructor. constexpr dynamic_array() = delete; + // Destructor. + virtual ~dynamic_array() + { + if(!empty()) + { + using local_allocator_traits_type = std::allocator_traits; + + // Deallocate the range of *this. + local_allocator_traits_type::deallocate(my_alloc, elems, elem_count); + + elem_count = static_cast(UINT8_C(0)); + elems = nullptr; + } + } + + // Iterator members: + WIDE_INTEGER_NODISCARD constexpr auto begin () -> iterator { return elems; } + WIDE_INTEGER_NODISCARD constexpr auto end () -> iterator { return elems + elem_count; } + WIDE_INTEGER_NODISCARD constexpr auto begin () const -> const_iterator { return elems; } + WIDE_INTEGER_NODISCARD constexpr auto end () const -> const_iterator { return elems + elem_count; } + WIDE_INTEGER_NODISCARD constexpr auto cbegin () const -> const_iterator { return elems; } + WIDE_INTEGER_NODISCARD constexpr auto cend () const -> const_iterator { return elems + elem_count; } + WIDE_INTEGER_NODISCARD constexpr auto rbegin () -> reverse_iterator { return reverse_iterator(elems + elem_count); } + WIDE_INTEGER_NODISCARD constexpr auto rend () -> reverse_iterator { return reverse_iterator(elems); } + WIDE_INTEGER_NODISCARD constexpr auto rbegin () const -> const_reverse_iterator { return const_reverse_iterator(elems + elem_count); } + WIDE_INTEGER_NODISCARD constexpr auto rend () const -> const_reverse_iterator { return const_reverse_iterator(elems); } + WIDE_INTEGER_NODISCARD constexpr auto crbegin() const -> const_reverse_iterator { return const_reverse_iterator(elems + elem_count); } + WIDE_INTEGER_NODISCARD constexpr auto crend () const -> const_reverse_iterator { return const_reverse_iterator(elems); } + + // Raw pointer access. + WIDE_INTEGER_NODISCARD constexpr auto data() -> pointer { return elems; } + WIDE_INTEGER_NODISCARD constexpr auto data() const -> const_pointer { return elems; } + + // Size and capacity. + WIDE_INTEGER_NODISCARD constexpr auto size () const noexcept -> size_type { return elem_count; } + WIDE_INTEGER_NODISCARD constexpr auto max_size() const noexcept -> size_type { return elem_count; } + WIDE_INTEGER_NODISCARD constexpr auto empty () const noexcept -> bool { return (elem_count == static_cast(UINT8_C(0))); } + + // Element access members. + WIDE_INTEGER_NODISCARD constexpr auto operator[](const size_type i) -> reference { return elems[i]; } + WIDE_INTEGER_NODISCARD constexpr auto operator[](const size_type i) const -> const_reference { return elems[i]; } + + WIDE_INTEGER_NODISCARD constexpr auto front() -> reference { return elems[static_cast(UINT8_C(0))]; } + WIDE_INTEGER_NODISCARD constexpr auto front() const -> const_reference { return elems[static_cast(UINT8_C(0))]; } + + WIDE_INTEGER_NODISCARD constexpr auto back() -> reference { return ((elem_count > static_cast(UINT8_C(0))) ? elems[static_cast(elem_count - static_cast(UINT8_C(1)))] : elems[static_cast(UINT8_C(0))]); } + WIDE_INTEGER_NODISCARD constexpr auto back() const -> const_reference { return ((elem_count > static_cast(UINT8_C(0))) ? elems[static_cast(elem_count - static_cast(UINT8_C(1)))] : elems[static_cast(UINT8_C(0))]); } + + WIDE_INTEGER_NODISCARD constexpr auto at(const size_type i) -> reference { return ((i < elem_count) ? elems[i] : elems[static_cast(UINT8_C(0))]); } + WIDE_INTEGER_NODISCARD constexpr auto at(const size_type i) const -> const_reference { return ((i < elem_count) ? elems[i] : elems[static_cast(UINT8_C(0))]); } + + // Element manipulation members. + constexpr auto fill(const value_type& value_in) -> void + { + #if defined(WIDE_INTEGER_NAMESPACE) + WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::fill_unsafe(begin(), begin() + elem_count, value_in); + #else + ::math::wide_integer::detail::fill_unsafe(begin(), begin() + elem_count, value_in); + #endif + } + + constexpr auto swap(dynamic_array& other) noexcept -> void + { + if(this != &other) + { + #if defined(WIDE_INTEGER_NAMESPACE) + WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::swap_unsafe(elems, other.elems); + WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::swap_unsafe(elem_count, other.elem_count); + WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::swap_unsafe(my_alloc, other.my_alloc); + #else + ::math::wide_integer::detail::swap_unsafe(elems, other.elems); + ::math::wide_integer::detail::swap_unsafe(elem_count, other.elem_count); + ::math::wide_integer::detail::swap_unsafe(my_alloc, other.my_alloc); + #endif + } + } + + protected: + // Constructors. explicit constexpr dynamic_array(size_type count_in, const_reference value_in = value_type(), const allocator_type& alloc_in = allocator_type()) @@ -761,27 +840,12 @@ // Move constructor. constexpr dynamic_array(dynamic_array&& other) noexcept : elem_count(other.elem_count), elems (other.elems), - my_alloc (std::move(other.my_alloc)) + my_alloc (std::move(static_cast(other.my_alloc))) { other.elem_count = static_cast(UINT8_C(0)); other.elems = nullptr; } - // Destructor. - virtual ~dynamic_array() - { - if(!empty()) - { - using local_allocator_traits_type = std::allocator_traits; - - // Deallocate the range of *this. - local_allocator_traits_type::deallocate(my_alloc, elems, elem_count); - - elem_count = static_cast(UINT8_C(0)); - elems = nullptr; - } - } - // Assignment operator. constexpr auto operator=(const dynamic_array& other) -> dynamic_array& { @@ -832,115 +896,47 @@ return *this; } - // Iterator members: - WIDE_INTEGER_NODISCARD constexpr auto begin () -> iterator { return elems; } - WIDE_INTEGER_NODISCARD constexpr auto end () -> iterator { return elems + elem_count; } - WIDE_INTEGER_NODISCARD constexpr auto begin () const -> const_iterator { return elems; } - WIDE_INTEGER_NODISCARD constexpr auto end () const -> const_iterator { return elems + elem_count; } - WIDE_INTEGER_NODISCARD constexpr auto cbegin () const -> const_iterator { return elems; } - WIDE_INTEGER_NODISCARD constexpr auto cend () const -> const_iterator { return elems + elem_count; } - WIDE_INTEGER_NODISCARD constexpr auto rbegin () -> reverse_iterator { return reverse_iterator(elems + elem_count); } - WIDE_INTEGER_NODISCARD constexpr auto rend () -> reverse_iterator { return reverse_iterator(elems); } - WIDE_INTEGER_NODISCARD constexpr auto rbegin () const -> const_reverse_iterator { return const_reverse_iterator(elems + elem_count); } - WIDE_INTEGER_NODISCARD constexpr auto rend () const -> const_reverse_iterator { return const_reverse_iterator(elems); } - WIDE_INTEGER_NODISCARD constexpr auto crbegin() const -> const_reverse_iterator { return const_reverse_iterator(elems + elem_count); } - WIDE_INTEGER_NODISCARD constexpr auto crend () const -> const_reverse_iterator { return const_reverse_iterator(elems); } - - // Raw pointer access. - WIDE_INTEGER_NODISCARD constexpr auto data() -> pointer { return elems; } - WIDE_INTEGER_NODISCARD constexpr auto data() const -> const_pointer { return elems; } - - // Size and capacity. - WIDE_INTEGER_NODISCARD constexpr auto size () const noexcept -> size_type { return elem_count; } - WIDE_INTEGER_NODISCARD constexpr auto max_size() const noexcept -> size_type { return elem_count; } - WIDE_INTEGER_NODISCARD constexpr auto empty () const noexcept -> bool { return (elem_count == static_cast(UINT8_C(0))); } - - // Element access members. - WIDE_INTEGER_NODISCARD constexpr auto operator[](const size_type i) -> reference { return elems[i]; } - WIDE_INTEGER_NODISCARD constexpr auto operator[](const size_type i) const -> const_reference { return elems[i]; } - - WIDE_INTEGER_NODISCARD constexpr auto front() -> reference { return elems[static_cast(UINT8_C(0))]; } - WIDE_INTEGER_NODISCARD constexpr auto front() const -> const_reference { return elems[static_cast(UINT8_C(0))]; } - - WIDE_INTEGER_NODISCARD constexpr auto back() -> reference { return ((elem_count > static_cast(UINT8_C(0))) ? elems[static_cast(elem_count - static_cast(UINT8_C(1)))] : elems[static_cast(UINT8_C(0))]); } - WIDE_INTEGER_NODISCARD constexpr auto back() const -> const_reference { return ((elem_count > static_cast(UINT8_C(0))) ? elems[static_cast(elem_count - static_cast(UINT8_C(1)))] : elems[static_cast(UINT8_C(0))]); } - - WIDE_INTEGER_NODISCARD constexpr auto at(const size_type i) -> reference { return ((i < elem_count) ? elems[i] : elems[static_cast(UINT8_C(0))]); } - WIDE_INTEGER_NODISCARD constexpr auto at(const size_type i) const -> const_reference { return ((i < elem_count) ? elems[i] : elems[static_cast(UINT8_C(0))]); } + private: + size_type elem_count { static_cast(UINT8_C(0)) }; // NOLINT(readability-identifier-naming) + pointer elems { nullptr }; // NOLINT(readability-identifier-naming,altera-id-dependent-backward-branch) + allocator_type my_alloc; // NOLINT(readability-identifier-naming) - // Element manipulation members. - constexpr auto fill(const value_type& value_in) -> void + friend constexpr auto operator==(const dynamic_array& lhs, const dynamic_array& rhs) -> bool { - #if defined(WIDE_INTEGER_NAMESPACE) - WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::fill_unsafe(begin(), begin() + elem_count, value_in); - #else - ::math::wide_integer::detail::fill_unsafe(begin(), begin() + elem_count, value_in); - #endif - } + bool left_and_right_are_equal { }; - constexpr auto swap(dynamic_array& other) noexcept -> void - { - if(this != &other) + if(lhs.size() == rhs.size()) { #if defined(WIDE_INTEGER_NAMESPACE) - WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::swap_unsafe(elems, other.elems); - WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::swap_unsafe(elem_count, other.elem_count); - WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::swap_unsafe(my_alloc, other.my_alloc); + left_and_right_are_equal = WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::equal_unsafe(lhs.cbegin(), lhs.cend(), rhs.cbegin()); #else - ::math::wide_integer::detail::swap_unsafe(elems, other.elems); - ::math::wide_integer::detail::swap_unsafe(elem_count, other.elem_count); - ::math::wide_integer::detail::swap_unsafe(my_alloc, other.my_alloc); + left_and_right_are_equal = ::math::wide_integer::detail::equal_unsafe(lhs.cbegin(), lhs.cend(), rhs.cbegin()); #endif } - } - - private: - size_type elem_count { static_cast(UINT8_C(0)) }; // NOLINT(readability-identifier-naming) - pointer elems { nullptr }; // NOLINT(readability-identifier-naming,altera-id-dependent-backward-branch) - allocator_type my_alloc; // NOLINT(readability-identifier-naming) - friend constexpr auto operator==(const dynamic_array& lhs, const dynamic_array& rhs) -> bool - { - return - ( - (lhs.size() == rhs.size()) - && ( - lhs.empty() - #if defined(WIDE_INTEGER_NAMESPACE) - || WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::equal_unsafe(lhs.cbegin(), lhs.cend(), rhs.cbegin()) - #else - || ::math::wide_integer::detail::equal_unsafe(lhs.cbegin(), lhs.cend(), rhs.cbegin()) - #endif - ) - ); + return left_and_right_are_equal; } friend constexpr auto operator<(const dynamic_array& lhs, const dynamic_array& rhs) -> bool { - bool b_result { }; - - if(lhs.empty()) - { - b_result = (!rhs.empty()); - } - else - { - // Note: Use lexicographical_compare here. If the dynamic arrays - // have unequal sizes, then simply ignore the size differences. + #if defined(WIDE_INTEGER_NAMESPACE) + const typename dynamic_array::size_type count { WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::min_unsafe(lhs.size(), rhs.size()) }; + #else + const typename dynamic_array::size_type count { ::math::wide_integer::detail::min_unsafe(lhs.size(), rhs.size()) }; + #endif - b_result = - #if defined(WIDE_INTEGER_NAMESPACE) - WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::lexicographical_compare_unsafe - #else - ::math::wide_integer::detail::lexicographical_compare_unsafe - #endif - ( - lhs.cbegin(), - lhs.cend(), - rhs.cbegin(), - rhs.cend() - ); - } + const bool b_result = + #if defined(WIDE_INTEGER_NAMESPACE) + WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::lexicographical_compare_unsafe + #else + ::math::wide_integer::detail::lexicographical_compare_unsafe + #endif + ( + lhs.cbegin(), + lhs.cbegin() + count, + rhs.cbegin(), + rhs.cbegin() + count + ); return b_result; } @@ -949,14 +945,9 @@ friend constexpr auto operator> (const dynamic_array& lhs, const dynamic_array& rhs) -> bool { return (rhs < lhs); } friend constexpr auto operator>=(const dynamic_array& lhs, const dynamic_array& rhs) -> bool { return (!(lhs < rhs)); } friend constexpr auto operator<=(const dynamic_array& lhs, const dynamic_array& rhs) -> bool { return (!(rhs < lhs)); } - }; - template - constexpr auto swap(dynamic_array& x, - dynamic_array& y) noexcept -> void - { - x.swap(y); - } + friend constexpr auto swap(dynamic_array& x, dynamic_array& y) noexcept -> void { x.swap(y); } + }; } // namespace util @@ -1588,21 +1579,40 @@ namespace math { namespace wide_integer { namespace detail { // NOLINT(modernize-concat-nested-namespaces) #endif - template> + class fixed_dynamic_array; + + template - class fixed_dynamic_array final : public detail::dynamic_array // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) + typename AllocatorType> + class fixed_dynamic_array final : public detail::dynamic_array // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) { private: - using base_class_type = detail::dynamic_array; + using base_class_type = detail::dynamic_array; public: - static constexpr auto static_size() -> typename base_class_type::size_type { return MySize; } + // Type definitions. + using typename base_class_type::allocator_type; + using typename base_class_type::value_type; + using typename base_class_type::reference; + using typename base_class_type::const_reference; + using typename base_class_type::iterator; + using typename base_class_type::const_iterator; + using typename base_class_type::pointer; + using typename base_class_type::const_pointer; + using typename base_class_type::size_type; + using typename base_class_type::difference_type; + using typename base_class_type::reverse_iterator; + using typename base_class_type::const_reverse_iterator; + + static constexpr auto static_size() -> size_type { return MySize; } - explicit constexpr fixed_dynamic_array(const typename base_class_type::size_type size_in = MySize, - const typename base_class_type::value_type& value_in = typename base_class_type::value_type(), - const typename base_class_type::allocator_type& alloc_in = typename base_class_type::allocator_type()) - : base_class_type(MySize, value_in, alloc_in) + explicit constexpr fixed_dynamic_array(const size_type size_in = static_size(), + const value_type& value_in = value_type(), + const allocator_type& alloc_in = allocator_type()) + : base_class_type(static_size(), value_in, alloc_in) { static_cast(size_in); } @@ -1611,11 +1621,11 @@ constexpr fixed_dynamic_array(fixed_dynamic_array&&) noexcept = default; - constexpr fixed_dynamic_array(std::initializer_list lst) + constexpr fixed_dynamic_array(std::initializer_list lst, const allocator_type& alloc_in = allocator_type()) : base_class_type(lst.begin(), - lst.begin() + (detail::min_unsafe)(static_cast(lst.size()), MySize)) { } + lst.begin() + (detail::min_unsafe)(static_cast(lst.size()), static_size()), + alloc_in) { } - //constexpt ~fixed_dynamic_array() override = default; constexpr auto operator=(const fixed_dynamic_array&) -> fixed_dynamic_array& = default; @@ -1623,12 +1633,20 @@ constexpr auto operator=(fixed_dynamic_array&&) noexcept -> fixed_dynamic_array& = default; }; - template + class tuple_size; + + template + class tuple_size> : public ::std::integral_constant { }; + + template - class fixed_static_array final : public detail::array_detail::array(MySize)> + class fixed_static_array final : public detail::array_detail::array(MySize)> { private: - using base_class_type = detail::array_detail::array(MySize)>; + using base_class_type = detail::array_detail::array(MySize)>; struct allocator_dummy_unsafe { @@ -1690,7 +1708,6 @@ } } - //constexpr ~fixed_static_array() = default; constexpr auto operator=(const fixed_static_array& other_array) -> fixed_static_array& = default; @@ -1700,6 +1717,10 @@ constexpr auto operator[](const size_type i) const -> typename base_class_type::const_reference { return base_class_type::operator[](static_cast(i)); } }; + template + class tuple_size> : public ::std::integral_constant { }; + template struct verify_power_of_two_times_granularity_one_sixty_fourth // NOLINT(altera-struct-pack-align) { // List of numbers used to identify the form 2^n times 1...63. diff --git a/ref_app/src/util/utility/util_dynamic_array.h b/ref_app/src/util/utility/util_dynamic_array.h index 624461ebd..f5381f2ed 100644 --- a/ref_app/src/util/utility/util_dynamic_array.h +++ b/ref_app/src/util/utility/util_dynamic_array.h @@ -19,9 +19,9 @@ namespace util { template, - typename SizeType = std::size_t, - typename DiffType = std::ptrdiff_t> + typename AllocatorType = ::std::allocator, + typename SizeType = ::std::size_t, + typename DiffType = ::std::ptrdiff_t> class dynamic_array; template class dynamic_array { - public: + protected: // Type definitions. using allocator_type = typename std::allocator_traits::template rebind_alloc; using value_type = typename allocator_type::value_type; @@ -45,9 +45,78 @@ using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; - // Constructors. + public: + // Deleted default constructor. constexpr dynamic_array() = delete; + // Destructor. + virtual ~dynamic_array() + { + if(!empty()) + { + using local_allocator_traits_type = std::allocator_traits; + + // Deallocate the range of *this. + local_allocator_traits_type::deallocate(my_alloc, elems, elem_count); + + elem_count = static_cast(UINT8_C(0)); + elems = nullptr; + } + } + + // Iterator members: + [[nodiscard]] constexpr auto begin () noexcept -> iterator { return elems; } + [[nodiscard]] constexpr auto end () noexcept -> iterator { return elems + elem_count; } + [[nodiscard]] constexpr auto begin () const noexcept -> const_iterator { return elems; } + [[nodiscard]] constexpr auto end () const noexcept -> const_iterator { return elems + elem_count; } + [[nodiscard]] constexpr auto cbegin () const noexcept -> const_iterator { return elems; } + [[nodiscard]] constexpr auto cend () const noexcept -> const_iterator { return elems + elem_count; } + [[nodiscard]] constexpr auto rbegin () noexcept -> reverse_iterator { return reverse_iterator(elems + elem_count); } + [[nodiscard]] constexpr auto rend () noexcept -> reverse_iterator { return reverse_iterator(elems); } + [[nodiscard]] constexpr auto rbegin () const noexcept -> const_reverse_iterator { return const_reverse_iterator(elems + elem_count); } + [[nodiscard]] constexpr auto rend () const noexcept -> const_reverse_iterator { return const_reverse_iterator(elems); } + [[nodiscard]] constexpr auto crbegin() const noexcept -> const_reverse_iterator { return const_reverse_iterator(elems + elem_count); } + [[nodiscard]] constexpr auto crend () const noexcept -> const_reverse_iterator { return const_reverse_iterator(elems); } + + // Raw pointer access. + [[nodiscard]] constexpr auto data() noexcept -> pointer { return elems; } + [[nodiscard]] constexpr auto data() const noexcept -> const_pointer { return elems; } + + // Size and capacity. + [[nodiscard]] constexpr auto size () const noexcept -> size_type { return elem_count; } + [[nodiscard]] constexpr auto max_size() const noexcept -> size_type { return elem_count; } + [[nodiscard]] constexpr auto empty () const noexcept -> bool { return (elem_count == static_cast(UINT8_C(0))); } + + // Element access members. + [[nodiscard]] constexpr auto operator[](const size_type i) noexcept -> reference { return elems[i]; } + [[nodiscard]] constexpr auto operator[](const size_type i) const noexcept -> const_reference { return elems[i]; } + + [[nodiscard]] constexpr auto front() noexcept -> reference { return elems[static_cast(UINT8_C(0))]; } + [[nodiscard]] constexpr auto front() const noexcept -> const_reference { return elems[static_cast(UINT8_C(0))]; } + + [[nodiscard]] constexpr auto back() noexcept -> reference { return ((elem_count > static_cast(UINT8_C(0))) ? elems[static_cast(elem_count - static_cast(UINT8_C(1)))] : elems[static_cast(UINT8_C(0))]); } + [[nodiscard]] constexpr auto back() const noexcept -> const_reference { return ((elem_count > static_cast(UINT8_C(0))) ? elems[static_cast(elem_count - static_cast(UINT8_C(1)))] : elems[static_cast(UINT8_C(0))]); } + + [[nodiscard]] constexpr auto at(const size_type i) noexcept -> reference { return ((i < elem_count) ? elems[i] : elems[static_cast(UINT8_C(0))]); } + [[nodiscard]] constexpr auto at(const size_type i) const noexcept -> const_reference { return ((i < elem_count) ? elems[i] : elems[static_cast(UINT8_C(0))]); } + + // Element manipulation members. + constexpr auto fill(const value_type& value_in) -> void + { + std::fill(begin(), begin() + elem_count, value_in); + } + + constexpr auto swap(dynamic_array& other) noexcept -> void + { + if(this != &other) + { + std::swap(elems, other.elems); + std::swap(elem_count, other.elem_count); + } + } + + protected: + // Constructors. explicit constexpr dynamic_array(size_type count_in, const_reference value_in = value_type(), const allocator_type& alloc_in = allocator_type()) @@ -79,9 +148,9 @@ } } - template - constexpr dynamic_array(input_iterator first, - input_iterator last, + template + constexpr dynamic_array(InputIterator first, + InputIterator last, const allocator_type& alloc_in = allocator_type()) : elem_count(static_cast(std::distance(first, last))), my_alloc(alloc_in) @@ -110,27 +179,12 @@ // Move constructor. constexpr dynamic_array(dynamic_array&& other) noexcept : elem_count(other.elem_count), elems (other.elems), - my_alloc (std::move(other.my_alloc)) + my_alloc (std::move(static_cast(other.my_alloc))) { other.elem_count = static_cast(UINT8_C(0)); other.elems = nullptr; } - // Destructor. - virtual ~dynamic_array() // LCOV_EXCL_LINE - { - if(!empty()) - { - using local_allocator_traits_type = std::allocator_traits; - - // Deallocate the range of *this. - local_allocator_traits_type::deallocate(my_alloc, elems, elem_count); - - elem_count = static_cast(UINT8_C(0)); - elems = nullptr; - } - } - // Assignment operator. constexpr auto operator=(const dynamic_array& other) -> dynamic_array& { @@ -153,57 +207,6 @@ return *this; } - // Iterator members: - constexpr auto begin () noexcept -> iterator { return elems; } - constexpr auto end () noexcept -> iterator { return elems + elem_count; } - constexpr auto begin () const noexcept -> const_iterator { return elems; } - constexpr auto end () const noexcept -> const_iterator { return elems + elem_count; } - constexpr auto cbegin () const noexcept -> const_iterator { return elems; } - constexpr auto cend () const noexcept -> const_iterator { return elems + elem_count; } - constexpr auto rbegin () noexcept -> reverse_iterator { return reverse_iterator(elems + elem_count); } - constexpr auto rend () noexcept -> reverse_iterator { return reverse_iterator(elems); } - constexpr auto rbegin () const noexcept -> const_reverse_iterator { return const_reverse_iterator(elems + elem_count); } - constexpr auto rend () const noexcept -> const_reverse_iterator { return const_reverse_iterator(elems); } - constexpr auto crbegin() const noexcept -> const_reverse_iterator { return const_reverse_iterator(elems + elem_count); } - constexpr auto crend () const noexcept -> const_reverse_iterator { return const_reverse_iterator(elems); } - - // Raw pointer access. - constexpr auto data() noexcept -> pointer { return elems; } - constexpr auto data() const noexcept -> const_pointer { return elems; } - - // Size and capacity. - constexpr auto size () const noexcept -> size_type { return elem_count; } - constexpr auto max_size() const noexcept -> size_type { return elem_count; } - constexpr auto empty () const noexcept -> bool { return (elem_count == static_cast(UINT8_C(0))); } - - // Element access members. - constexpr auto operator[](const size_type i) noexcept -> reference { return elems[i]; } - constexpr auto operator[](const size_type i) const noexcept -> const_reference { return elems[i]; } - - constexpr auto front() noexcept -> reference { return elems[static_cast(UINT8_C(0))]; } - constexpr auto front() const noexcept -> const_reference { return elems[static_cast(UINT8_C(0))]; } - - constexpr auto back() noexcept -> reference { return ((elem_count > static_cast(UINT8_C(0))) ? elems[static_cast(elem_count - static_cast(UINT8_C(1)))] : elems[static_cast(UINT8_C(0))]); } - constexpr auto back() const noexcept -> const_reference { return ((elem_count > static_cast(UINT8_C(0))) ? elems[static_cast(elem_count - static_cast(UINT8_C(1)))] : elems[static_cast(UINT8_C(0))]); } - - constexpr auto at(const size_type i) noexcept -> reference { return ((i < elem_count) ? elems[i] : elems[static_cast(UINT8_C(0))]); } - constexpr auto at(const size_type i) const noexcept -> const_reference { return ((i < elem_count) ? elems[i] : elems[static_cast(UINT8_C(0))]); } - - // Element manipulation members. - constexpr auto fill(const value_type& v) -> void - { - std::fill(begin(), begin() + elem_count, v); - } - - constexpr auto swap(dynamic_array& other) noexcept -> void - { - if(this != &other) - { - std::swap(elems, other.elems); - std::swap(elem_count, other.elem_count); - } - } - private: size_type elem_count { static_cast(UINT8_C(0)) }; // NOLINT(readability-identifier-naming) pointer elems { nullptr }; // NOLINT(readability-identifier-naming,altera-id-dependent-backward-branch) @@ -211,53 +214,27 @@ friend constexpr auto operator==(const dynamic_array& lhs, const dynamic_array& rhs) -> bool { - bool left_and_right_are_equal = false; + bool left_and_right_are_equal { }; if(lhs.size() == rhs.size()) { - using size_type = typename dynamic_array::size_type; - - const auto size_of_left_is_zero = (lhs.size() == static_cast(UINT8_C(0))); - - left_and_right_are_equal = - (size_of_left_is_zero || std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin())); - - return left_and_right_are_equal; + left_and_right_are_equal = std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin()); } + + return left_and_right_are_equal; } friend constexpr auto operator<(const dynamic_array& lhs, const dynamic_array& rhs) -> bool { - using size_type = typename dynamic_array::size_type; - - const auto size_of_left_is_zero = (lhs.size() == static_cast(UINT8_C(0))); - - bool b_result { }; - - if(size_of_left_is_zero) - { - const auto size_of_right_is_zero = (rhs.size() == static_cast(UINT8_C(0))); + using size_type = typename dynamic_array::size_type; - b_result = (!size_of_right_is_zero); - } - else - { - if(size_of_left_is_zero) - { - const auto size_of_right_is_zero = (rhs.size() == static_cast(UINT8_C(0))); - - b_result = (!size_of_right_is_zero); - } - else - { - const size_type count = (std::min)(lhs.size(), rhs.size()); + const size_type count { (std::min)(lhs.size(), rhs.size()) }; - b_result= std::lexicographical_compare(lhs.cbegin(), - lhs.cbegin() + count, - rhs.cbegin(), - rhs.cbegin() + count); - } - } + const bool b_result = + std::lexicographical_compare(lhs.cbegin(), + lhs.cbegin() + count, + rhs.cbegin(), + rhs.cbegin() + count); return b_result; } @@ -266,14 +243,77 @@ friend constexpr auto operator> (const dynamic_array& lhs, const dynamic_array& rhs) -> bool { return (rhs < lhs); } friend constexpr auto operator>=(const dynamic_array& lhs, const dynamic_array& rhs) -> bool { return (!(lhs < rhs)); } friend constexpr auto operator<=(const dynamic_array& lhs, const dynamic_array& rhs) -> bool { return (!(rhs < lhs)); } + + friend constexpr auto swap(dynamic_array& x, dynamic_array& y) noexcept -> void { x.swap(y); } }; - template - constexpr auto swap(dynamic_array& x, - dynamic_array& y) noexcept -> void + template> + class fixed_dynamic_array; + + template + class fixed_dynamic_array final : public dynamic_array // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) { - x.swap(y); - } + private: + using base_class_type = dynamic_array; + + public: + // Type definitions. + using typename base_class_type::allocator_type; + using typename base_class_type::value_type; + using typename base_class_type::reference; + using typename base_class_type::const_reference; + using typename base_class_type::iterator; + using typename base_class_type::const_iterator; + using typename base_class_type::pointer; + using typename base_class_type::const_pointer; + using typename base_class_type::size_type; + using typename base_class_type::difference_type; + using typename base_class_type::reverse_iterator; + using typename base_class_type::const_reverse_iterator; + + static constexpr auto static_size() -> size_type { return MySize; } + + explicit constexpr fixed_dynamic_array(const size_type size_in = static_size(), + const value_type& value_in = value_type(), + const allocator_type& alloc_in = allocator_type()) + : base_class_type(static_size(), value_in, alloc_in) + { + static_cast(size_in); + } + + constexpr fixed_dynamic_array(const fixed_dynamic_array&) = default; + + constexpr fixed_dynamic_array(fixed_dynamic_array&&) noexcept = default; + + template + constexpr fixed_dynamic_array(InputIterator first, + InputIterator last, + const allocator_type& alloc_in = allocator_type()) + : base_class_type(first, last, alloc_in) { } + + constexpr fixed_dynamic_array(std::initializer_list lst, const allocator_type& alloc_in = allocator_type()) + : base_class_type(lst.begin(), + lst.begin() + (std::min)(static_cast(lst.size()), static_size()), + alloc_in) { } + + ~fixed_dynamic_array() override = default; + + constexpr auto operator=(const fixed_dynamic_array&) -> fixed_dynamic_array& = default; + + constexpr auto operator=(fixed_dynamic_array&&) noexcept -> fixed_dynamic_array& = default; + }; + + template + class tuple_size; + + template + class tuple_size> : public ::std::integral_constant { }; } // namespace util From e7bb39551062d46b0133685a14b11c7f6f4ac6c7 Mon Sep 17 00:00:00 2001 From: ckormanyos Date: Wed, 3 Jun 2026 21:52:52 +0200 Subject: [PATCH 2/4] dyn array base needs public interface --- ref_app/src/util/utility/util_dynamic_array.h | 136 +++++++++--------- 1 file changed, 67 insertions(+), 69 deletions(-) diff --git a/ref_app/src/util/utility/util_dynamic_array.h b/ref_app/src/util/utility/util_dynamic_array.h index f5381f2ed..0a0699704 100644 --- a/ref_app/src/util/utility/util_dynamic_array.h +++ b/ref_app/src/util/utility/util_dynamic_array.h @@ -30,7 +30,7 @@ typename DiffType> class dynamic_array { - protected: + public: // Type definitions. using allocator_type = typename std::allocator_traits::template rebind_alloc; using value_type = typename allocator_type::value_type; @@ -45,77 +45,9 @@ using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; - public: // Deleted default constructor. constexpr dynamic_array() = delete; - // Destructor. - virtual ~dynamic_array() - { - if(!empty()) - { - using local_allocator_traits_type = std::allocator_traits; - - // Deallocate the range of *this. - local_allocator_traits_type::deallocate(my_alloc, elems, elem_count); - - elem_count = static_cast(UINT8_C(0)); - elems = nullptr; - } - } - - // Iterator members: - [[nodiscard]] constexpr auto begin () noexcept -> iterator { return elems; } - [[nodiscard]] constexpr auto end () noexcept -> iterator { return elems + elem_count; } - [[nodiscard]] constexpr auto begin () const noexcept -> const_iterator { return elems; } - [[nodiscard]] constexpr auto end () const noexcept -> const_iterator { return elems + elem_count; } - [[nodiscard]] constexpr auto cbegin () const noexcept -> const_iterator { return elems; } - [[nodiscard]] constexpr auto cend () const noexcept -> const_iterator { return elems + elem_count; } - [[nodiscard]] constexpr auto rbegin () noexcept -> reverse_iterator { return reverse_iterator(elems + elem_count); } - [[nodiscard]] constexpr auto rend () noexcept -> reverse_iterator { return reverse_iterator(elems); } - [[nodiscard]] constexpr auto rbegin () const noexcept -> const_reverse_iterator { return const_reverse_iterator(elems + elem_count); } - [[nodiscard]] constexpr auto rend () const noexcept -> const_reverse_iterator { return const_reverse_iterator(elems); } - [[nodiscard]] constexpr auto crbegin() const noexcept -> const_reverse_iterator { return const_reverse_iterator(elems + elem_count); } - [[nodiscard]] constexpr auto crend () const noexcept -> const_reverse_iterator { return const_reverse_iterator(elems); } - - // Raw pointer access. - [[nodiscard]] constexpr auto data() noexcept -> pointer { return elems; } - [[nodiscard]] constexpr auto data() const noexcept -> const_pointer { return elems; } - - // Size and capacity. - [[nodiscard]] constexpr auto size () const noexcept -> size_type { return elem_count; } - [[nodiscard]] constexpr auto max_size() const noexcept -> size_type { return elem_count; } - [[nodiscard]] constexpr auto empty () const noexcept -> bool { return (elem_count == static_cast(UINT8_C(0))); } - - // Element access members. - [[nodiscard]] constexpr auto operator[](const size_type i) noexcept -> reference { return elems[i]; } - [[nodiscard]] constexpr auto operator[](const size_type i) const noexcept -> const_reference { return elems[i]; } - - [[nodiscard]] constexpr auto front() noexcept -> reference { return elems[static_cast(UINT8_C(0))]; } - [[nodiscard]] constexpr auto front() const noexcept -> const_reference { return elems[static_cast(UINT8_C(0))]; } - - [[nodiscard]] constexpr auto back() noexcept -> reference { return ((elem_count > static_cast(UINT8_C(0))) ? elems[static_cast(elem_count - static_cast(UINT8_C(1)))] : elems[static_cast(UINT8_C(0))]); } - [[nodiscard]] constexpr auto back() const noexcept -> const_reference { return ((elem_count > static_cast(UINT8_C(0))) ? elems[static_cast(elem_count - static_cast(UINT8_C(1)))] : elems[static_cast(UINT8_C(0))]); } - - [[nodiscard]] constexpr auto at(const size_type i) noexcept -> reference { return ((i < elem_count) ? elems[i] : elems[static_cast(UINT8_C(0))]); } - [[nodiscard]] constexpr auto at(const size_type i) const noexcept -> const_reference { return ((i < elem_count) ? elems[i] : elems[static_cast(UINT8_C(0))]); } - - // Element manipulation members. - constexpr auto fill(const value_type& value_in) -> void - { - std::fill(begin(), begin() + elem_count, value_in); - } - - constexpr auto swap(dynamic_array& other) noexcept -> void - { - if(this != &other) - { - std::swap(elems, other.elems); - std::swap(elem_count, other.elem_count); - } - } - - protected: // Constructors. explicit constexpr dynamic_array(size_type count_in, const_reference value_in = value_type(), @@ -185,6 +117,21 @@ other.elems = nullptr; } + // Destructor. + virtual ~dynamic_array() + { + if(!empty()) + { + using local_allocator_traits_type = std::allocator_traits; + + // Deallocate the range of *this. + local_allocator_traits_type::deallocate(my_alloc, elems, elem_count); + + elem_count = static_cast(UINT8_C(0)); + elems = nullptr; + } + } + // Assignment operator. constexpr auto operator=(const dynamic_array& other) -> dynamic_array& { @@ -207,6 +154,57 @@ return *this; } + // Iterator members: + [[nodiscard]] constexpr auto begin () noexcept -> iterator { return elems; } + [[nodiscard]] constexpr auto end () noexcept -> iterator { return elems + elem_count; } + [[nodiscard]] constexpr auto begin () const noexcept -> const_iterator { return elems; } + [[nodiscard]] constexpr auto end () const noexcept -> const_iterator { return elems + elem_count; } + [[nodiscard]] constexpr auto cbegin () const noexcept -> const_iterator { return elems; } + [[nodiscard]] constexpr auto cend () const noexcept -> const_iterator { return elems + elem_count; } + [[nodiscard]] constexpr auto rbegin () noexcept -> reverse_iterator { return reverse_iterator(elems + elem_count); } + [[nodiscard]] constexpr auto rend () noexcept -> reverse_iterator { return reverse_iterator(elems); } + [[nodiscard]] constexpr auto rbegin () const noexcept -> const_reverse_iterator { return const_reverse_iterator(elems + elem_count); } + [[nodiscard]] constexpr auto rend () const noexcept -> const_reverse_iterator { return const_reverse_iterator(elems); } + [[nodiscard]] constexpr auto crbegin() const noexcept -> const_reverse_iterator { return const_reverse_iterator(elems + elem_count); } + [[nodiscard]] constexpr auto crend () const noexcept -> const_reverse_iterator { return const_reverse_iterator(elems); } + + // Raw pointer access. + [[nodiscard]] constexpr auto data() noexcept -> pointer { return elems; } + [[nodiscard]] constexpr auto data() const noexcept -> const_pointer { return elems; } + + // Size and capacity. + [[nodiscard]] constexpr auto size () const noexcept -> size_type { return elem_count; } + [[nodiscard]] constexpr auto max_size() const noexcept -> size_type { return elem_count; } + [[nodiscard]] constexpr auto empty () const noexcept -> bool { return (elem_count == static_cast(UINT8_C(0))); } + + // Element access members. + [[nodiscard]] constexpr auto operator[](const size_type i) noexcept -> reference { return elems[i]; } + [[nodiscard]] constexpr auto operator[](const size_type i) const noexcept -> const_reference { return elems[i]; } + + [[nodiscard]] constexpr auto front() noexcept -> reference { return elems[static_cast(UINT8_C(0))]; } + [[nodiscard]] constexpr auto front() const noexcept -> const_reference { return elems[static_cast(UINT8_C(0))]; } + + [[nodiscard]] constexpr auto back() noexcept -> reference { return ((elem_count > static_cast(UINT8_C(0))) ? elems[static_cast(elem_count - static_cast(UINT8_C(1)))] : elems[static_cast(UINT8_C(0))]); } + [[nodiscard]] constexpr auto back() const noexcept -> const_reference { return ((elem_count > static_cast(UINT8_C(0))) ? elems[static_cast(elem_count - static_cast(UINT8_C(1)))] : elems[static_cast(UINT8_C(0))]); } + + [[nodiscard]] constexpr auto at(const size_type i) noexcept -> reference { return ((i < elem_count) ? elems[i] : elems[static_cast(UINT8_C(0))]); } + [[nodiscard]] constexpr auto at(const size_type i) const noexcept -> const_reference { return ((i < elem_count) ? elems[i] : elems[static_cast(UINT8_C(0))]); } + + // Element manipulation members. + constexpr auto fill(const value_type& value_in) -> void + { + std::fill(begin(), begin() + elem_count, value_in); + } + + constexpr auto swap(dynamic_array& other) noexcept -> void + { + if(this != &other) + { + std::swap(elems, other.elems); + std::swap(elem_count, other.elem_count); + } + } + private: size_type elem_count { static_cast(UINT8_C(0)) }; // NOLINT(readability-identifier-naming) pointer elems { nullptr }; // NOLINT(readability-identifier-naming,altera-id-dependent-backward-branch) From 0bb00c3f29a764d657dc1a8ce7832b5a8925c44a Mon Sep 17 00:00:00 2001 From: ckormanyos Date: Thu, 4 Jun 2026 16:58:34 +0200 Subject: [PATCH 3/4] Update wide integer and dynamic array --- ref_app/src/math/wide_integer/uintwide_t.h | 314 ++++++++++-------- ref_app/src/util/utility/util_dynamic_array.h | 100 ++++-- 2 files changed, 241 insertions(+), 173 deletions(-) diff --git a/ref_app/src/math/wide_integer/uintwide_t.h b/ref_app/src/math/wide_integer/uintwide_t.h index 9aa3af7aa..40f7466ed 100644 --- a/ref_app/src/math/wide_integer/uintwide_t.h +++ b/ref_app/src/math/wide_integer/uintwide_t.h @@ -114,6 +114,14 @@ namespace math { namespace wide_integer { namespace detail { // NOLINT(modernize-concat-nested-namespaces) #endif + using size_t = std::uint32_t; + using ptrdiff_t = std::int32_t; + #if defined(WIDE_INTEGER_HAS_LIMB_TYPE_UINT64) + using uint_defaultlimb_t = std::uint64_t; + #else + using uint_defaultlimb_t = std::uint32_t; + #endif + namespace iterator_detail { class input_iterator_tag { }; @@ -374,7 +382,7 @@ template constexpr auto lexicographical_compare_unsafe(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2) -> bool { - for( ; (first1 != last1) && (first2 != last2); static_cast(++first1), static_cast(++first2)) + for( ; (first1 != last1) && (first2 != last2); ++first1, static_cast(++first2)) { if(*first1 < *first2) { @@ -504,13 +512,25 @@ namespace array_detail { - template + + template class array { public: // Standard container-local type definitions. - using size_type = ::std::size_t; - using difference_type = ::std::ptrdiff_t; + #if defined(WIDE_INTEGER_NAMESPACE) + using size_type = WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::size_t; + using difference_type = WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::ptrdiff_t; + #else + using size_type = ::math::wide_integer::detail::size_t; + using difference_type = ::math::wide_integer::detail::ptrdiff_t; + #endif using value_type = T; using pointer = T*; using const_pointer = const T*; @@ -615,15 +635,15 @@ template class tuple_size; - template - class tuple_size> : public std::integral_constant { }; + template + class tuple_size> : public std::integral_constant { }; - template + template class tuple_element; - template + const size_t N> class tuple_element > { static_assert(I < N, "Sorry, tuple_element index is out of bounds."); @@ -661,7 +681,7 @@ typename DiffType> class dynamic_array { - protected: + public: // Type definitions. using allocator_type = typename std::allocator_traits::template rebind_alloc; using value_type = typename allocator_type::value_type; @@ -681,92 +701,10 @@ using const_reverse_iterator = ::math::wide_integer::detail::iterator_detail::reverse_iterator; #endif - public: static_assert(std::is_integral::value, "Error: the value_type of dynamic_array must be a built-in integral"); - // Deleted default constructor. - constexpr dynamic_array() = delete; - - // Destructor. - virtual ~dynamic_array() - { - if(!empty()) - { - using local_allocator_traits_type = std::allocator_traits; - - // Deallocate the range of *this. - local_allocator_traits_type::deallocate(my_alloc, elems, elem_count); - - elem_count = static_cast(UINT8_C(0)); - elems = nullptr; - } - } - - // Iterator members: - WIDE_INTEGER_NODISCARD constexpr auto begin () -> iterator { return elems; } - WIDE_INTEGER_NODISCARD constexpr auto end () -> iterator { return elems + elem_count; } - WIDE_INTEGER_NODISCARD constexpr auto begin () const -> const_iterator { return elems; } - WIDE_INTEGER_NODISCARD constexpr auto end () const -> const_iterator { return elems + elem_count; } - WIDE_INTEGER_NODISCARD constexpr auto cbegin () const -> const_iterator { return elems; } - WIDE_INTEGER_NODISCARD constexpr auto cend () const -> const_iterator { return elems + elem_count; } - WIDE_INTEGER_NODISCARD constexpr auto rbegin () -> reverse_iterator { return reverse_iterator(elems + elem_count); } - WIDE_INTEGER_NODISCARD constexpr auto rend () -> reverse_iterator { return reverse_iterator(elems); } - WIDE_INTEGER_NODISCARD constexpr auto rbegin () const -> const_reverse_iterator { return const_reverse_iterator(elems + elem_count); } - WIDE_INTEGER_NODISCARD constexpr auto rend () const -> const_reverse_iterator { return const_reverse_iterator(elems); } - WIDE_INTEGER_NODISCARD constexpr auto crbegin() const -> const_reverse_iterator { return const_reverse_iterator(elems + elem_count); } - WIDE_INTEGER_NODISCARD constexpr auto crend () const -> const_reverse_iterator { return const_reverse_iterator(elems); } - - // Raw pointer access. - WIDE_INTEGER_NODISCARD constexpr auto data() -> pointer { return elems; } - WIDE_INTEGER_NODISCARD constexpr auto data() const -> const_pointer { return elems; } - - // Size and capacity. - WIDE_INTEGER_NODISCARD constexpr auto size () const noexcept -> size_type { return elem_count; } - WIDE_INTEGER_NODISCARD constexpr auto max_size() const noexcept -> size_type { return elem_count; } - WIDE_INTEGER_NODISCARD constexpr auto empty () const noexcept -> bool { return (elem_count == static_cast(UINT8_C(0))); } - - // Element access members. - WIDE_INTEGER_NODISCARD constexpr auto operator[](const size_type i) -> reference { return elems[i]; } - WIDE_INTEGER_NODISCARD constexpr auto operator[](const size_type i) const -> const_reference { return elems[i]; } - - WIDE_INTEGER_NODISCARD constexpr auto front() -> reference { return elems[static_cast(UINT8_C(0))]; } - WIDE_INTEGER_NODISCARD constexpr auto front() const -> const_reference { return elems[static_cast(UINT8_C(0))]; } - - WIDE_INTEGER_NODISCARD constexpr auto back() -> reference { return ((elem_count > static_cast(UINT8_C(0))) ? elems[static_cast(elem_count - static_cast(UINT8_C(1)))] : elems[static_cast(UINT8_C(0))]); } - WIDE_INTEGER_NODISCARD constexpr auto back() const -> const_reference { return ((elem_count > static_cast(UINT8_C(0))) ? elems[static_cast(elem_count - static_cast(UINT8_C(1)))] : elems[static_cast(UINT8_C(0))]); } - - WIDE_INTEGER_NODISCARD constexpr auto at(const size_type i) -> reference { return ((i < elem_count) ? elems[i] : elems[static_cast(UINT8_C(0))]); } - WIDE_INTEGER_NODISCARD constexpr auto at(const size_type i) const -> const_reference { return ((i < elem_count) ? elems[i] : elems[static_cast(UINT8_C(0))]); } - - // Element manipulation members. - constexpr auto fill(const value_type& value_in) -> void - { - #if defined(WIDE_INTEGER_NAMESPACE) - WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::fill_unsafe(begin(), begin() + elem_count, value_in); - #else - ::math::wide_integer::detail::fill_unsafe(begin(), begin() + elem_count, value_in); - #endif - } - - constexpr auto swap(dynamic_array& other) noexcept -> void - { - if(this != &other) - { - #if defined(WIDE_INTEGER_NAMESPACE) - WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::swap_unsafe(elems, other.elems); - WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::swap_unsafe(elem_count, other.elem_count); - WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::swap_unsafe(my_alloc, other.my_alloc); - #else - ::math::wide_integer::detail::swap_unsafe(elems, other.elems); - ::math::wide_integer::detail::swap_unsafe(elem_count, other.elem_count); - ::math::wide_integer::detail::swap_unsafe(my_alloc, other.my_alloc); - #endif - } - } - - protected: // Constructors. - explicit constexpr dynamic_array(size_type count_in, + explicit constexpr dynamic_array(size_type count_in = size_type(), const_reference value_in = value_type(), const allocator_type& alloc_in = allocator_type()) : elem_count(count_in), @@ -801,9 +739,9 @@ } } - template - constexpr dynamic_array(input_iterator first, - input_iterator last, + template + constexpr dynamic_array(InputIterator first, + InputIterator last, const allocator_type& alloc_in = allocator_type()) : elem_count(static_cast(last - first)), my_alloc(alloc_in) @@ -846,6 +784,28 @@ other.elems = nullptr; } + // Destructor. + virtual ~dynamic_array() + { + if(!empty()) + { + // The destructors of the elements are called (in unspecified order) + // and the dynamically allocated storage (if any) is deallocated. + + for(auto* itr { begin() }; itr != end(); ++itr) // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) + { + itr->~value_type(); + } + + using local_allocator_traits_type = std::allocator_traits; + + local_allocator_traits_type::deallocate(my_alloc, elems, elem_count); + + elem_count = static_cast(UINT8_C(0)); + elems = nullptr; + } + } + // Assignment operator. constexpr auto operator=(const dynamic_array& other) -> dynamic_array& { @@ -863,9 +823,9 @@ #else other.elems + ::math::wide_integer::detail::min_unsafe #endif - ( - elem_count, other.elem_count - ), + ( + elem_count, other.elem_count + ), elems ); } @@ -896,6 +856,68 @@ return *this; } + // Iterator members: + WIDE_INTEGER_NODISCARD constexpr auto begin () -> iterator { return elems; } + WIDE_INTEGER_NODISCARD constexpr auto end () -> iterator { return elems + elem_count; } + WIDE_INTEGER_NODISCARD constexpr auto begin () const -> const_iterator { return elems; } + WIDE_INTEGER_NODISCARD constexpr auto end () const -> const_iterator { return elems + elem_count; } + WIDE_INTEGER_NODISCARD constexpr auto cbegin () const -> const_iterator { return elems; } + WIDE_INTEGER_NODISCARD constexpr auto cend () const -> const_iterator { return elems + elem_count; } + WIDE_INTEGER_NODISCARD constexpr auto rbegin () -> reverse_iterator { return reverse_iterator(elems + elem_count); } + WIDE_INTEGER_NODISCARD constexpr auto rend () -> reverse_iterator { return reverse_iterator(elems); } + WIDE_INTEGER_NODISCARD constexpr auto rbegin () const -> const_reverse_iterator { return const_reverse_iterator(elems + elem_count); } + WIDE_INTEGER_NODISCARD constexpr auto rend () const -> const_reverse_iterator { return const_reverse_iterator(elems); } + WIDE_INTEGER_NODISCARD constexpr auto crbegin() const -> const_reverse_iterator { return const_reverse_iterator(elems + elem_count); } + WIDE_INTEGER_NODISCARD constexpr auto crend () const -> const_reverse_iterator { return const_reverse_iterator(elems); } + + // Raw pointer access. + WIDE_INTEGER_NODISCARD constexpr auto data() -> pointer { return elems; } + WIDE_INTEGER_NODISCARD constexpr auto data() const -> const_pointer { return elems; } + + // Size and capacity. + WIDE_INTEGER_NODISCARD constexpr auto size () const noexcept -> size_type { return elem_count; } + WIDE_INTEGER_NODISCARD constexpr auto max_size() const noexcept -> size_type { return elem_count; } + WIDE_INTEGER_NODISCARD constexpr auto empty () const noexcept -> bool { return (elem_count == static_cast(UINT8_C(0))); } + + // Element access members. + WIDE_INTEGER_NODISCARD constexpr auto operator[](const size_type i) -> reference { return elems[i]; } + WIDE_INTEGER_NODISCARD constexpr auto operator[](const size_type i) const -> const_reference { return elems[i]; } + + WIDE_INTEGER_NODISCARD constexpr auto front() -> reference { return elems[static_cast(UINT8_C(0))]; } + WIDE_INTEGER_NODISCARD constexpr auto front() const -> const_reference { return elems[static_cast(UINT8_C(0))]; } + + WIDE_INTEGER_NODISCARD constexpr auto back() -> reference { return ((elem_count > static_cast(UINT8_C(0))) ? elems[static_cast(elem_count - static_cast(UINT8_C(1)))] : elems[static_cast(UINT8_C(0))]); } + WIDE_INTEGER_NODISCARD constexpr auto back() const -> const_reference { return ((elem_count > static_cast(UINT8_C(0))) ? elems[static_cast(elem_count - static_cast(UINT8_C(1)))] : elems[static_cast(UINT8_C(0))]); } + + WIDE_INTEGER_NODISCARD constexpr auto at(const size_type i) -> reference { return ((i < elem_count) ? elems[i] : elems[static_cast(UINT8_C(0))]); } + WIDE_INTEGER_NODISCARD constexpr auto at(const size_type i) const -> const_reference { return ((i < elem_count) ? elems[i] : elems[static_cast(UINT8_C(0))]); } + + // Element manipulation members. + constexpr auto fill(const value_type& value_in) -> void + { + #if defined(WIDE_INTEGER_NAMESPACE) + WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::fill_unsafe(begin(), begin() + elem_count, value_in); + #else + ::math::wide_integer::detail::fill_unsafe(begin(), begin() + elem_count, value_in); + #endif + } + + constexpr auto swap(dynamic_array& other) noexcept -> void + { + if(this != &other) + { + #if defined(WIDE_INTEGER_NAMESPACE) + WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::swap_unsafe(elems, other.elems); + WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::swap_unsafe(elem_count, other.elem_count); + WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::swap_unsafe(my_alloc, other.my_alloc); + #else + ::math::wide_integer::detail::swap_unsafe(elems, other.elems); + ::math::wide_integer::detail::swap_unsafe(elem_count, other.elem_count); + ::math::wide_integer::detail::swap_unsafe(my_alloc, other.my_alloc); + #endif + } + } + private: size_type elem_count { static_cast(UINT8_C(0)) }; // NOLINT(readability-identifier-naming) pointer elems { nullptr }; // NOLINT(readability-identifier-naming,altera-id-dependent-backward-branch) @@ -903,42 +925,36 @@ friend constexpr auto operator==(const dynamic_array& lhs, const dynamic_array& rhs) -> bool { - bool left_and_right_are_equal { }; + bool b_result { }; - if(lhs.size() == rhs.size()) + if(lhs.empty()) + { + b_result = rhs.empty(); + } + else if(lhs.size() == rhs.size()) { #if defined(WIDE_INTEGER_NAMESPACE) - left_and_right_are_equal = WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::equal_unsafe(lhs.cbegin(), lhs.cend(), rhs.cbegin()); + b_result = WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::equal_unsafe(lhs.cbegin(), lhs.cend(), rhs.cbegin()); #else - left_and_right_are_equal = ::math::wide_integer::detail::equal_unsafe(lhs.cbegin(), lhs.cend(), rhs.cbegin()); + b_result = ::math::wide_integer::detail::equal_unsafe(lhs.cbegin(), lhs.cend(), rhs.cbegin()); #endif } + // else b_result remains false - return left_and_right_are_equal; + return b_result; } friend constexpr auto operator<(const dynamic_array& lhs, const dynamic_array& rhs) -> bool { - #if defined(WIDE_INTEGER_NAMESPACE) - const typename dynamic_array::size_type count { WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::min_unsafe(lhs.size(), rhs.size()) }; - #else - const typename dynamic_array::size_type count { ::math::wide_integer::detail::min_unsafe(lhs.size(), rhs.size()) }; - #endif - - const bool b_result = + return #if defined(WIDE_INTEGER_NAMESPACE) WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::lexicographical_compare_unsafe #else ::math::wide_integer::detail::lexicographical_compare_unsafe #endif ( - lhs.cbegin(), - lhs.cbegin() + count, - rhs.cbegin(), - rhs.cbegin() + count + lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend() ); - - return b_result; } friend constexpr auto operator!=(const dynamic_array& lhs, const dynamic_array& rhs) -> bool { return (!(lhs == rhs)); } @@ -1009,14 +1025,6 @@ namespace detail { - using size_t = std::uint32_t; - using ptrdiff_t = std::int32_t; - #if defined(WIDE_INTEGER_HAS_LIMB_TYPE_UINT64) - using uint_defaultlimb_t = std::uint64_t; - #else - using uint_defaultlimb_t = std::uint32_t; - #endif - static_assert(( (std::numeric_limits::digits >= std::numeric_limits::digits) && (std::numeric_limits::digits + 1 >= std::numeric_limits::digits)), "Error: size type and pointer difference type must be at least 16 bits in width (or wider)"); @@ -1614,6 +1622,7 @@ const allocator_type& alloc_in = allocator_type()) : base_class_type(static_size(), value_in, alloc_in) { + // This parameter is explicitly and purposely ignored. static_cast(size_in); } @@ -1622,15 +1631,30 @@ constexpr fixed_dynamic_array(fixed_dynamic_array&&) noexcept = default; constexpr fixed_dynamic_array(std::initializer_list lst, const allocator_type& alloc_in = allocator_type()) - : base_class_type(lst.begin(), - lst.begin() + (detail::min_unsafe)(static_cast(lst.size()), static_size()), - alloc_in) { } + : base_class_type(static_size(), size_type(), alloc_in) + { + #if defined(WIDE_INTEGER_NAMESPACE) + WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::copy_unsafe + #else + ::math::wide_integer::detail::copy_unsafe + #endif + ( + lst.begin(), + lst.begin() + (detail::min_unsafe)(static_cast(lst.size()), static_size()), + base_class_type::data() + ); + } ~fixed_dynamic_array() override = default; constexpr auto operator=(const fixed_dynamic_array&) -> fixed_dynamic_array& = default; - constexpr auto operator=(fixed_dynamic_array&&) noexcept -> fixed_dynamic_array& = default; + constexpr auto operator=(fixed_dynamic_array&& other) noexcept -> fixed_dynamic_array& + { + base_class_type::operator=(static_cast(other)); + + return *this; + } }; template @@ -1643,10 +1667,10 @@ template - class fixed_static_array final : public detail::array_detail::array(MySize)> + class fixed_static_array final : public detail::array_detail::array { private: - using base_class_type = detail::array_detail::array(MySize)>; + using base_class_type = detail::array_detail::array; struct allocator_dummy_unsafe { @@ -1654,15 +1678,26 @@ }; public: - using size_type = size_t; - using value_type = typename base_class_type::value_type; + // Standard container-local type definitions. using allocator_type = allocator_dummy_unsafe; - static constexpr auto static_size() -> size_type { return MySize; } + using typename base_class_type::size_type; + using typename base_class_type::difference_type; + using typename base_class_type::value_type; + using typename base_class_type::pointer; + using typename base_class_type::const_pointer; + using typename base_class_type::reference; + using typename base_class_type::const_reference; + using typename base_class_type::iterator; + using typename base_class_type::const_iterator; + using typename base_class_type::reverse_iterator; + using typename base_class_type::const_reverse_iterator; - constexpr fixed_static_array() = default; + static_assert(::std::is_integral::value, "Error the template value_type must be a built-in integral type."); - explicit constexpr fixed_static_array(const size_type size_in, + static constexpr auto static_size() -> size_type { return MySize; } + + explicit constexpr fixed_static_array(const size_type size_in = size_type(), const value_type& value_in = value_type(), allocator_type alloc_in = allocator_type()) { @@ -1670,8 +1705,8 @@ if(size_in < static_size()) { - detail::fill_unsafe(base_class_type::begin(), base_class_type::begin() + size_in, value_in); - detail::fill_unsafe(base_class_type::begin() + size_in, base_class_type::end(), value_type()); + detail::fill_unsafe(base_class_type::begin(), base_class_type::begin() + size_in, value_in); + detail::fill_unsafe(base_class_type::begin() + size_in, base_class_type::end(), value_type()); } else { @@ -1712,9 +1747,6 @@ constexpr auto operator=(const fixed_static_array& other_array) -> fixed_static_array& = default; constexpr auto operator=(fixed_static_array&& other_array) noexcept -> fixed_static_array& = default; - - constexpr auto operator[](const size_type i) -> typename base_class_type::reference { return base_class_type::operator[](static_cast(i)); } - constexpr auto operator[](const size_type i) const -> typename base_class_type::const_reference { return base_class_type::operator[](static_cast(i)); } }; template; using const_reverse_iterator = std::reverse_iterator; - // Deleted default constructor. - constexpr dynamic_array() = delete; - // Constructors. - explicit constexpr dynamic_array(size_type count_in, + explicit constexpr dynamic_array(size_type count_in = size_type(), const_reference value_in = value_type(), const allocator_type& alloc_in = allocator_type()) : elem_count(count_in), @@ -122,9 +119,16 @@ { if(!empty()) { + // The destructors of the elements are called (in unspecified order) + // and the dynamically allocated storage (if any) is deallocated. + + for(auto* itr { begin() }; itr != end(); ++itr) // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) + { + itr->~value_type(); + } + using local_allocator_traits_type = std::allocator_traits; - // Deallocate the range of *this. local_allocator_traits_type::deallocate(my_alloc, elems, elem_count); elem_count = static_cast(UINT8_C(0)); @@ -137,9 +141,15 @@ { if(this != &other) { - std::copy(other.elems, - other.elems + (std::min)(elem_count, other.elem_count), - elems); + std::copy + ( + other.elems, + other.elems + (std::min) + ( + elem_count, other.elem_count + ), + elems + ); } return *this; @@ -148,8 +158,22 @@ // Move assignment operator. constexpr auto operator=(dynamic_array&& other) noexcept -> dynamic_array& { - std::swap(elem_count, other.elem_count); - std::swap(elems, other.elems); + if(this != &other) + { + if(!empty()) + { + using local_allocator_traits_type = std::allocator_traits; + + // Deallocate the range of *this. + local_allocator_traits_type::deallocate(my_alloc, elems, elem_count); + } + + elem_count = other.elem_count; + elems = other.elems; + + other.elem_count = static_cast(UINT8_C(0)); + other.elems = nullptr; + } return *this; } @@ -200,8 +224,9 @@ { if(this != &other) { - std::swap(elems, other.elems); + std::swap(elems, other.elems); std::swap(elem_count, other.elem_count); + std::swap(my_alloc, other.my_alloc); } } @@ -212,29 +237,28 @@ friend constexpr auto operator==(const dynamic_array& lhs, const dynamic_array& rhs) -> bool { - bool left_and_right_are_equal { }; + bool b_result { }; - if(lhs.size() == rhs.size()) + if(lhs.empty()) + { + b_result = rhs.empty(); + } + else if(lhs.size() == rhs.size()) { - left_and_right_are_equal = std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin()); + b_result = std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin()); } + // else b_result remains false - return left_and_right_are_equal; + return b_result; } friend constexpr auto operator<(const dynamic_array& lhs, const dynamic_array& rhs) -> bool { - using size_type = typename dynamic_array::size_type; - - const size_type count { (std::min)(lhs.size(), rhs.size()) }; - - const bool b_result = - std::lexicographical_compare(lhs.cbegin(), - lhs.cbegin() + count, - rhs.cbegin(), - rhs.cbegin() + count); - - return b_result; + return + std::lexicographical_compare + ( + lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend() + ); } friend constexpr auto operator!=(const dynamic_array& lhs, const dynamic_array& rhs) -> bool { return (!(lhs == rhs)); } @@ -280,6 +304,7 @@ const allocator_type& alloc_in = allocator_type()) : base_class_type(static_size(), value_in, alloc_in) { + // This parameter is explicitly and purposely ignored. static_cast(size_in); } @@ -287,22 +312,33 @@ constexpr fixed_dynamic_array(fixed_dynamic_array&&) noexcept = default; + constexpr fixed_dynamic_array(std::initializer_list lst, const allocator_type& alloc_in = allocator_type()) + : base_class_type(static_size(), size_type(), alloc_in) + { + std::copy + ( + lst.begin(), + lst.begin() + (std::min)(static_cast(lst.size()), static_size()), + base_class_type::data() + ); + } + template constexpr fixed_dynamic_array(InputIterator first, InputIterator last, const allocator_type& alloc_in = allocator_type()) : base_class_type(first, last, alloc_in) { } - constexpr fixed_dynamic_array(std::initializer_list lst, const allocator_type& alloc_in = allocator_type()) - : base_class_type(lst.begin(), - lst.begin() + (std::min)(static_cast(lst.size()), static_size()), - alloc_in) { } - ~fixed_dynamic_array() override = default; constexpr auto operator=(const fixed_dynamic_array&) -> fixed_dynamic_array& = default; - constexpr auto operator=(fixed_dynamic_array&&) noexcept -> fixed_dynamic_array& = default; + constexpr auto operator=(fixed_dynamic_array&& other) noexcept -> fixed_dynamic_array& + { + base_class_type::operator=(static_cast(other)); + + return *this; + } }; template From bc02c4ffa6c92a861cb0bfd74449ff9c74cd52e6 Mon Sep 17 00:00:00 2001 From: ckormanyos Date: Thu, 4 Jun 2026 17:37:50 +0200 Subject: [PATCH 4/4] Handle bogus GCC warn new std-big-int bench --- ref_app/src/util/memory/util_ring_allocator.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/ref_app/src/util/memory/util_ring_allocator.h b/ref_app/src/util/memory/util_ring_allocator.h index b44dab8ea..77985d4da 100644 --- a/ref_app/src/util/memory/util_ring_allocator.h +++ b/ref_app/src/util/memory/util_ring_allocator.h @@ -88,10 +88,23 @@ { // The buffer has overflowed. + #if (defined(__GNUC__) && !defined(__clang__)) + #if(__GNUC__ >= 12) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Warray-bounds" + #endif + #endif + // Reset the allocated pointer to the bottom of the buffer // and increment the next get-pointer. p = &buffer.data[std::size_t { UINT8_C(0) }]; get_ptr = &buffer.data[chunk_size]; + + #if (defined(__GNUC__) && !defined(__clang__)) + #if(__GNUC__ >= 12) + #pragma GCC diagnostic pop + #endif + #endif } return static_cast(p);