From 054aa5015f76fc15ef6238712a3487dc799ad780 Mon Sep 17 00:00:00 2001 From: John McFarlane Date: Sat, 1 May 2021 17:17:20 +0100 Subject: [PATCH 1/8] Make many APIs constant expressions Means that many tests can use constexpr variables using C++20 --- math/wide_integer/uintwide_t.h | 577 ++++++++++++++++----------------- 1 file changed, 286 insertions(+), 291 deletions(-) diff --git a/math/wide_integer/uintwide_t.h b/math/wide_integer/uintwide_t.h index 6d91dd3d..a953391c 100644 --- a/math/wide_integer/uintwide_t.h +++ b/math/wide_integer/uintwide_t.h @@ -43,195 +43,195 @@ class uintwide_t; // Forward declarations of non-member binary add, sub, mul, div, mod of (uintwide_t op uintwide_t). - template uintwide_t operator+(const uintwide_t& u, const uintwide_t& v); - template uintwide_t operator-(const uintwide_t& u, const uintwide_t& v); - template uintwide_t operator*(const uintwide_t& u, const uintwide_t& v); - template uintwide_t operator/(const uintwide_t& u, const uintwide_t& v); - template uintwide_t operator%(const uintwide_t& u, const uintwide_t& v); + template constexpr uintwide_t operator+(const uintwide_t& u, const uintwide_t& v); + template constexpr uintwide_t operator-(const uintwide_t& u, const uintwide_t& v); + template constexpr uintwide_t operator*(const uintwide_t& u, const uintwide_t& v); + template constexpr uintwide_t operator/(const uintwide_t& u, const uintwide_t& v); + template constexpr uintwide_t operator%(const uintwide_t& u, const uintwide_t& v); // Forward declarations of non-member binary add, sub, mul, div, mod of (uintwide_t op IntegralType). template typename std::enable_if<( (std::is_fundamental::value == true) && (std::is_integral ::value == true)), uintwide_t>::type - operator+(const uintwide_t& u, const IntegralType& v); + constexpr operator+(const uintwide_t& u, const IntegralType& v); template typename std::enable_if<( (std::is_fundamental::value == true) && (std::is_integral ::value == true)), uintwide_t>::type - operator-(const uintwide_t& u, const IntegralType& v); + constexpr operator-(const uintwide_t& u, const IntegralType& v); template typename std::enable_if<( (std::is_fundamental::value == true) && (std::is_integral ::value == true)), uintwide_t>::type - operator*(const uintwide_t& u, const IntegralType& v); + constexpr operator*(const uintwide_t& u, const IntegralType& v); template typename std::enable_if<( (std::is_fundamental::value == true) && (std::is_integral ::value == true)), uintwide_t>::type - operator/(const uintwide_t& u, const IntegralType& v); + constexpr operator/(const uintwide_t& u, const IntegralType& v); template typename std::enable_if<( (std::is_fundamental::value == true) && (std::is_integral ::value == true) && (std::is_unsigned ::value == false)), uintwide_t>::type - operator%(const uintwide_t& u, const IntegralType& v); + constexpr operator%(const uintwide_t& u, const IntegralType& v); template typename std::enable_if<( (std::is_fundamental::value == true) && (std::is_integral ::value == true) && (std::is_unsigned ::value == true) && (std::numeric_limits::digits <= std::numeric_limits::digits)), typename uintwide_t::limb_type>::type - operator%(const uintwide_t& u, const IntegralType& v); + constexpr operator%(const uintwide_t& u, const IntegralType& v); template typename std::enable_if<( (std::is_fundamental::value == true) && (std::is_integral ::value == true) && (std::is_unsigned ::value == true) && (std::numeric_limits::digits > std::numeric_limits::digits)), uintwide_t>::type - operator%(const uintwide_t& u, const IntegralType& v); + constexpr operator%(const uintwide_t& u, const IntegralType& v); // Forward declarations of non-member binary add, sub, mul, div, mod of (IntegralType op uintwide_t). template typename std::enable_if<( (std::is_fundamental::value == true) && (std::is_integral ::value == true)), uintwide_t>::type - operator+(const IntegralType& u, const uintwide_t& v); + constexpr operator+(const IntegralType& u, const uintwide_t& v); template typename std::enable_if<( (std::is_fundamental::value == true) && (std::is_integral ::value == true)), uintwide_t>::type - operator-(const IntegralType& u, const uintwide_t& v); + constexpr operator-(const IntegralType& u, const uintwide_t& v); template typename std::enable_if<( (std::is_fundamental::value == true) && (std::is_integral ::value == true)), uintwide_t>::type - operator*(const IntegralType& u, const uintwide_t& v); + constexpr operator*(const IntegralType& u, const uintwide_t& v); template typename std::enable_if<( (std::is_fundamental::value == true) && (std::is_integral ::value == true)), uintwide_t>::type - operator/(const IntegralType& u, const uintwide_t& v); + constexpr operator/(const IntegralType& u, const uintwide_t& v); template typename std::enable_if<( (std::is_fundamental::value == true) && (std::is_integral ::value == true)), uintwide_t>::type - operator%(const IntegralType& u, const uintwide_t& v); + constexpr operator%(const IntegralType& u, const uintwide_t& v); // Forward declarations of non-member binary logic operations of (uintwide_t op uintwide_t). - template uintwide_t operator|(const uintwide_t& u, const uintwide_t& v); - template uintwide_t operator^(const uintwide_t& u, const uintwide_t& v); - template uintwide_t operator&(const uintwide_t& u, const uintwide_t& v); + template constexpr uintwide_t operator|(const uintwide_t& u, const uintwide_t& v); + template constexpr uintwide_t operator^(const uintwide_t& u, const uintwide_t& v); + template constexpr uintwide_t operator&(const uintwide_t& u, const uintwide_t& v); // Forward declarations of non-member binary logic operations of (uintwide_t op IntegralType). template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), uintwide_t>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), uintwide_t>::type operator|(const uintwide_t& u, const IntegralType& v); template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), uintwide_t>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), uintwide_t>::type operator^(const uintwide_t& u, const IntegralType& v); template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), uintwide_t>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), uintwide_t>::type operator&(const uintwide_t& u, const IntegralType& v); // Forward declarations of non-member binary binary logic operations of (IntegralType op uintwide_t). template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), uintwide_t>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), uintwide_t>::type operator|(const IntegralType& u, const uintwide_t& v); template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), uintwide_t>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), uintwide_t>::type operator^(const IntegralType& u, const uintwide_t& v); template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), uintwide_t>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), uintwide_t>::type operator&(const IntegralType& u, const uintwide_t& v); // Forward declarations of non-member shift functions of (uintwide_t shift IntegralType). template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), uintwide_t>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), uintwide_t>::type operator<<(const uintwide_t& u, const IntegralType n); template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), uintwide_t>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), uintwide_t>::type operator>>(const uintwide_t& u, const IntegralType n); // Forward declarations of non-member comparison functions of (uintwide_t cmp uintwide_t). - template bool operator==(const uintwide_t& u, const uintwide_t& v); - template bool operator!=(const uintwide_t& u, const uintwide_t& v); - template bool operator> (const uintwide_t& u, const uintwide_t& v); - template bool operator< (const uintwide_t& u, const uintwide_t& v); - template bool operator>=(const uintwide_t& u, const uintwide_t& v); - template bool operator<=(const uintwide_t& u, const uintwide_t& v); + template constexpr bool operator==(const uintwide_t& u, const uintwide_t& v); + template constexpr bool operator!=(const uintwide_t& u, const uintwide_t& v); + template constexpr bool operator> (const uintwide_t& u, const uintwide_t& v); + template constexpr bool operator< (const uintwide_t& u, const uintwide_t& v); + template constexpr bool operator>=(const uintwide_t& u, const uintwide_t& v); + template constexpr bool operator<=(const uintwide_t& u, const uintwide_t& v); // Forward declarations of non-member comparison functions of (uintwide_t cmp IntegralType). template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), bool>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), bool>::type operator==(const uintwide_t& u, const IntegralType& v); template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), bool>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), bool>::type operator!=(const uintwide_t& u, const IntegralType& v); template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), bool>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), bool>::type operator> (const uintwide_t& u, const IntegralType& v); template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), bool>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), bool>::type operator< (const uintwide_t& u, const IntegralType& v); template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), bool>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), bool>::type operator>=(const uintwide_t& u, const IntegralType& v); template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), bool>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), bool>::type operator<=(const uintwide_t& u, const IntegralType& v); // Forward declarations of non-member comparison functions of (IntegralType cmp uintwide_t). template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), bool>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), bool>::type operator==(const IntegralType& u, const uintwide_t& v); template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), bool>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), bool>::type operator!=(const IntegralType& u, const uintwide_t& v); template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), bool>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), bool>::type operator> (const IntegralType& u, const uintwide_t& v); template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), bool>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), bool>::type operator< (const IntegralType& u, const uintwide_t& v); template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), bool>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), bool>::type operator>=(const IntegralType& u, const uintwide_t& v); template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), bool>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), bool>::type operator<=(const IntegralType& u, const uintwide_t& v); #if defined(WIDE_INTEGER_DISABLE_IOSTREAM) @@ -260,61 +260,61 @@ template - void swap(uintwide_t& x, - uintwide_t& y); + constexpr void swap(uintwide_t& x, + uintwide_t& y); template - std::uint_fast32_t lsb(const uintwide_t& x); + constexpr std::uint_fast32_t lsb(const uintwide_t& x); template - std::uint_fast32_t msb(const uintwide_t& x); + constexpr std::uint_fast32_t msb(const uintwide_t& x); template - uintwide_t sqrt(const uintwide_t& m); + constexpr uintwide_t sqrt(const uintwide_t& m); template - uintwide_t cbrt(const uintwide_t& m); + constexpr uintwide_t cbrt(const uintwide_t& m); template - uintwide_t rootk(const uintwide_t& m, + constexpr uintwide_t rootk(const uintwide_t& m, const std::uint_fast8_t k); template - uintwide_t pow(const uintwide_t& b, - const OtherUnsignedIntegralTypeP& p); + constexpr uintwide_t pow(const uintwide_t& b, + const OtherUnsignedIntegralTypeP& p); template - uintwide_t powm(const uintwide_t& b, - const OtherUnsignedIntegralTypeP& p, - const OtherUnsignedIntegralTypeM& m); + constexpr uintwide_t powm(const uintwide_t& b, + const OtherUnsignedIntegralTypeP& p, + const OtherUnsignedIntegralTypeM& m); template - uintwide_t gcd(const uintwide_t& a, - const uintwide_t& b); + constexpr uintwide_t gcd(const uintwide_t& a, + const uintwide_t& b); template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true) - && (std::is_unsigned ::value == true)), UshortType>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true) + && (std::is_unsigned ::value == true)), UshortType>::type gcd(const UshortType& u, const UshortType& v); template - bool operator==(const uniform_int_distribution& lhs, + constexpr bool operator==(const uniform_int_distribution& lhs, const uniform_int_distribution& rhs); template - bool operator!=(const uniform_int_distribution& lhs, + constexpr bool operator!=(const uniform_int_distribution& lhs, const uniform_int_distribution& rhs); template; public: - fixed_static_array() { } + constexpr fixed_static_array() = default; - fixed_static_array(const typename base_class_type::size_type s, + constexpr fixed_static_array(const typename base_class_type::size_type s, const typename base_class_type::value_type& v = typename base_class_type::value_type()) { std::fill(base_class_type::begin(), @@ -443,7 +443,7 @@ : base_class_type(static_cast(other_array)) { } template - fixed_static_array(const fixed_static_array& other_array) + constexpr fixed_static_array(const fixed_static_array& other_array) { std::copy(other_array.cbegin(), other_array.cbegin() + (std::min)(OtherSize, MySize), @@ -454,7 +454,7 @@ typename base_class_type::value_type()); } - explicit fixed_static_array(std::initializer_list lst) + explicit constexpr fixed_static_array(std::initializer_list lst) { std::copy(lst.begin(), lst.begin() + (std::min)((std::uint_fast32_t) lst.size(), MySize), @@ -468,22 +468,20 @@ constexpr fixed_static_array(fixed_static_array&& other_array) : base_class_type(static_cast(other_array)) { } - fixed_static_array& operator=(const fixed_static_array& other_array) + constexpr fixed_static_array& operator=(const fixed_static_array& other_array) { base_class_type::operator=((const base_class_type&) other_array); return *this; } - fixed_static_array& operator=(fixed_static_array&& other_array) + constexpr fixed_static_array& operator=(fixed_static_array&& other_array) { base_class_type::operator=((base_class_type&&) other_array); return *this; } - ~fixed_static_array() { } - static constexpr typename base_class_type::size_type static_size() { return MySize; @@ -560,9 +558,9 @@ } // Use a local implementation of string length. - inline std::uint_fast32_t strlen_unsafe(const char* p_str) + inline constexpr std::uint_fast32_t strlen_unsafe(const char* p_str) { - const char* p_str_copy; + const char* p_str_copy{}; for(p_str_copy = p_str; (*p_str_copy != char('\0')); ++p_str_copy) { ; } @@ -571,7 +569,7 @@ template::digits * 2)>::exact_unsigned_type> - UshortType make_lo(const UlargeType& u) + constexpr UshortType make_lo(const UlargeType& u) { // From an unsigned integral input parameter of type UlargeType, // extract the low part of it. The type of the extracted @@ -598,7 +596,7 @@ template::digits * 2)>::exact_unsigned_type> - UshortType make_hi(const UlargeType& u) + constexpr UshortType make_hi(const UlargeType& u) { // From an unsigned integral input parameter of type UlargeType, // extract the high part of it. The type of the extracted @@ -625,7 +623,7 @@ template::digits * 2)>::exact_unsigned_type> - UlargeType make_large(const UshortType& lo, const UshortType& hi) + constexpr UlargeType make_large(const UshortType& lo, const UshortType& hi) { // Create a composite unsigned integral value having type UlargeType. // Two constituents are used having type UshortType, whereby the @@ -735,7 +733,7 @@ // are wider than limb_type, and do not have exactly the // same width as limb_type. template - uintwide_t(const UnsignedIntegralType v, + constexpr uintwide_t(const UnsignedIntegralType v, typename std::enable_if<( (std::is_fundamental::value == true) && (std::is_integral ::value == true) && (std::is_unsigned ::value == true) @@ -756,7 +754,7 @@ // Constructors from built-in signed integral types. template - uintwide_t(const SignedIntegralType v, + constexpr uintwide_t(const SignedIntegralType v, typename std::enable_if<( (std::is_fundamental::value == true) && (std::is_integral ::value == true) && (std::is_signed ::value == true))>::type* = nullptr) @@ -805,7 +803,7 @@ // Constructor from the another type having a different width but the same limb type. // This constructor is explicit because it is a non-trivial conversion. template - uintwide_t(const uintwide_t& v) + constexpr uintwide_t(const uintwide_t& v) { const std::uint_fast32_t sz = (std::min)(std::uint_fast32_t(v.crepresentation().size()), @@ -819,7 +817,7 @@ } // Constructor from a constant character string. - uintwide_t(const char* str_input) + constexpr uintwide_t(const char* str_input) { if(rd_string(str_input) == false) { @@ -830,11 +828,8 @@ // Move constructor. constexpr uintwide_t(uintwide_t&& other) : values(static_cast(other.values)) { } - // Default destructor. - ~uintwide_t() { } - // Assignment operator. - uintwide_t& operator=(const uintwide_t& other) + constexpr uintwide_t& operator=(const uintwide_t& other) { if(this != &other) { @@ -845,7 +840,7 @@ } // Trivial move assignment operator. - uintwide_t& operator=(uintwide_t&& other) + constexpr uintwide_t& operator=(uintwide_t&& other) { values = static_cast(other.values); @@ -858,7 +853,7 @@ typename = typename std::enable_if< ( (std::is_fundamental::value == true) && (std::is_integral ::value == true))>::type> - explicit operator UnknownBuiltInIntegralType() const + explicit constexpr operator UnknownBuiltInIntegralType() const { using local_unknown_integral_type = UnknownBuiltInIntegralType; @@ -868,7 +863,7 @@ ? std::numeric_limits::digits + 1 : std::numeric_limits::digits + 0>::exact_unsigned_type; - local_unsigned_integral_type cast_result; + local_unsigned_integral_type cast_result{}; const std::uint_fast8_t digits_ratio = std::uint_fast8_t( std::numeric_limits::digits @@ -904,7 +899,7 @@ // Implement the cast operator that casts to the double-width type. template::value == true)>::type> - operator double_width_type() const + constexpr operator double_width_type() const { double_width_type local_double_width_instance; @@ -920,15 +915,15 @@ } // Provide a user interface to the internal data representation. - representation_type& representation() { return values; } - const representation_type& representation() const { return values; } - const representation_type& crepresentation() const { return values; } + constexpr representation_type& representation() { return values; } + constexpr const representation_type& representation() const { return values; } + constexpr const representation_type& crepresentation() const { return values; } // Unary operators: not, plus and minus. - const uintwide_t& operator+() const { return *this; } - uintwide_t operator-() const { uintwide_t tmp(*this); tmp.negate(); return tmp; } + constexpr const uintwide_t& operator+() const { return *this; } + constexpr uintwide_t operator-() const { uintwide_t tmp(*this); tmp.negate(); return tmp; } - uintwide_t& operator+=(const uintwide_t& other) + constexpr uintwide_t& operator+=(const uintwide_t& other) { if(this == &other) { @@ -949,7 +944,7 @@ return *this; } - uintwide_t& operator-=(const uintwide_t& other) + constexpr uintwide_t& operator-=(const uintwide_t& other) { if(this == &other) { @@ -970,7 +965,7 @@ return *this; } - uintwide_t& operator*=(const uintwide_t& other) + constexpr uintwide_t& operator*=(const uintwide_t& other) { if(this == &other) { @@ -984,7 +979,7 @@ return *this; } - uintwide_t& mul_by_limb(const limb_type v) + constexpr uintwide_t& mul_by_limb(const limb_type v) { if(v == 0U) { @@ -1001,7 +996,7 @@ return *this; } - uintwide_t& operator/=(const uintwide_t& other) + constexpr uintwide_t& operator/=(const uintwide_t& other) { if(this == &other) { @@ -1022,7 +1017,7 @@ return *this; } - uintwide_t& operator%=(const uintwide_t& other) + constexpr uintwide_t& operator%=(const uintwide_t& other) { if(this == &other) { @@ -1104,7 +1099,7 @@ } template - typename std::enable_if<( (std::is_fundamental::value == true) + constexpr typename std::enable_if<( (std::is_fundamental::value == true) && (std::is_integral ::value == true) && (std::is_signed ::value == true)), uintwide_t>::type& operator<<=(const SignedIntegralType n) @@ -1134,7 +1129,7 @@ } template - typename std::enable_if<( (std::is_fundamental::value == true) + constexpr typename std::enable_if<( (std::is_fundamental::value == true) && (std::is_integral ::value == true) && (std::is_signed ::value == false)), uintwide_t>::type& operator<<=(const UnsignedIntegralType n) @@ -1160,7 +1155,7 @@ } template - typename std::enable_if<( (std::is_fundamental::value == true) + constexpr typename std::enable_if<( (std::is_fundamental::value == true) && (std::is_integral ::value == true) && (std::is_signed ::value == true)), uintwide_t>::type& operator>>=(const SignedIntegralType n) @@ -1190,7 +1185,7 @@ } template - typename std::enable_if<( (std::is_fundamental::value == true) + constexpr typename std::enable_if<( (std::is_fundamental::value == true) && (std::is_integral ::value == true) && (std::is_signed ::value == false)), uintwide_t>::type& operator>>=(const UnsignedIntegralType n) @@ -1216,12 +1211,12 @@ } // Implement comparison operators. - bool operator==(const uintwide_t& other) const { return (compare(other) == std::int_fast8_t( 0)); } - bool operator< (const uintwide_t& other) const { return (compare(other) == std::int_fast8_t(-1)); } - bool operator> (const uintwide_t& other) const { return (compare(other) == std::int_fast8_t( 1)); } - bool operator!=(const uintwide_t& other) const { return (compare(other) != std::int_fast8_t( 0)); } - bool operator<=(const uintwide_t& other) const { return (compare(other) <= std::int_fast8_t( 0)); } - bool operator>=(const uintwide_t& other) const { return (compare(other) >= std::int_fast8_t( 0)); } + constexpr bool operator==(const uintwide_t& other) const { return (compare(other) == std::int_fast8_t( 0)); } + constexpr bool operator< (const uintwide_t& other) const { return (compare(other) == std::int_fast8_t(-1)); } + constexpr bool operator> (const uintwide_t& other) const { return (compare(other) == std::int_fast8_t( 1)); } + constexpr bool operator!=(const uintwide_t& other) const { return (compare(other) != std::int_fast8_t( 0)); } + constexpr bool operator<=(const uintwide_t& other) const { return (compare(other) <= std::int_fast8_t( 0)); } + constexpr bool operator>=(const uintwide_t& other) const { return (compare(other) >= std::int_fast8_t( 0)); } // Helper functions for supporting std::numeric_limits<>. static constexpr uintwide_t limits_helper_max() @@ -1435,7 +1430,7 @@ return wr_string_is_ok; } - std::int_fast8_t compare(const uintwide_t& other) const + constexpr std::int_fast8_t compare(const uintwide_t& other) const { const std::int_fast8_t cmp_result = compare_ranges(values.data(), other.values.data(), number_of_limbs); @@ -1449,9 +1444,9 @@ preincrement(); } - void eval_divide_by_single_limb(const limb_type short_denominator, - const std::uint_fast32_t u_offset, - uintwide_t* remainder) + constexpr void eval_divide_by_single_limb(const limb_type short_denominator, + const std::uint_fast32_t u_offset, + uintwide_t* remainder) { // The denominator has one single limb. // Use a one-dimensional division algorithm. @@ -1481,11 +1476,11 @@ } private: - representation_type values; + representation_type values{}; - static std::int_fast8_t compare_ranges(const limb_type* a, - const limb_type* b, - const std::uint_fast32_t count) + static constexpr std::int_fast8_t compare_ranges(const limb_type* a, + const limb_type* b, + const std::uint_fast32_t count) { using local_const_reverse_iterator_type = std::reverse_iterator; @@ -1515,9 +1510,9 @@ } template - static void eval_mul_unary( uintwide_t& u, - const uintwide_t& v, - typename std::enable_if<((OtherDigits2 / std::numeric_limits::digits) < number_of_limbs_karatsuba_threshold)>::type* = nullptr) + static constexpr void eval_mul_unary( uintwide_t& u, + const uintwide_t& v, + typename std::enable_if<((OtherDigits2 / std::numeric_limits::digits) < number_of_limbs_karatsuba_threshold)>::type* = nullptr) { // Unary multiplication function using schoolbook multiplication, // but we only need to retain the low half of the n*n algorithm. @@ -1538,9 +1533,9 @@ } template - static void eval_mul_unary( uintwide_t& u, - const uintwide_t& v, - typename std::enable_if<((OtherDigits2 / std::numeric_limits::digits) >= number_of_limbs_karatsuba_threshold)>::type* = nullptr) + static constexpr void eval_mul_unary( uintwide_t& u, + const uintwide_t& v, + typename std::enable_if<((OtherDigits2 / std::numeric_limits::digits) >= number_of_limbs_karatsuba_threshold)>::type* = nullptr) { // Unary multiplication function using Karatsuba multiplication. @@ -1568,11 +1563,11 @@ u.values.begin()); } - static limb_type eval_add_n( limb_type* r, - const limb_type* u, - const limb_type* v, - const std::uint_fast32_t count, - const limb_type carry_in = 0U) + static constexpr limb_type eval_add_n( limb_type* r, + const limb_type* u, + const limb_type* v, + const std::uint_fast32_t count, + const limb_type carry_in = 0U) { std::uint_fast8_t carry_out = static_cast(carry_in); @@ -1588,11 +1583,11 @@ return static_cast(carry_out); } - static bool eval_subtract_n( limb_type* r, - const limb_type* u, - const limb_type* v, - const std::uint_fast32_t count, - const bool has_borrow_in = false) + static constexpr bool eval_subtract_n( limb_type* r, + const limb_type* u, + const limb_type* v, + const std::uint_fast32_t count, + const bool has_borrow_in = false) { std::uint_fast8_t has_borrow_out = (has_borrow_in ? 1U : 0U); @@ -1610,10 +1605,10 @@ template::limb_type) * 8U) * 4U == RePhraseDigits2)>::type const* = nullptr> - static void eval_multiply_n_by_n_to_lo_part( LimbType* r, - const LimbType* a, - const LimbType* b, - const std::uint_fast32_t count) + static constexpr void eval_multiply_n_by_n_to_lo_part( LimbType* r, + const LimbType* a, + const LimbType* b, + const std::uint_fast32_t count) { static_cast(count); @@ -1697,10 +1692,10 @@ template::limb_type) * 8U) * 8U == RePhraseDigits2)>::type const* = nullptr> - static void eval_multiply_n_by_n_to_lo_part( LimbType* r, - const LimbType* a, - const LimbType* b, - const std::uint_fast32_t count) + static constexpr void eval_multiply_n_by_n_to_lo_part( LimbType* r, + const LimbType* a, + const LimbType* b, + const std::uint_fast32_t count) { using local_limb_type = typename uintwide_t::limb_type; using local_double_limb_type = typename uintwide_t::double_limb_type; @@ -1736,7 +1731,7 @@ using local_limb_type = typename uintwide_t::limb_type; using local_double_limb_type = typename uintwide_t::double_limb_type; - std::memset(r, 0, count * sizeof(local_limb_type)); + std::fill_n(r, count, 0); for(std::uint_fast32_t i = 0U; i < count; ++i) { @@ -1785,10 +1780,10 @@ } } - static limb_type eval_multiply_1d( limb_type* r, - const limb_type* a, - const limb_type b, - const std::uint_fast32_t count) + static constexpr limb_type eval_multiply_1d( limb_type* r, + const limb_type* a, + const limb_type b, + const std::uint_fast32_t count) { double_limb_type carry = 0U; @@ -2029,7 +2024,7 @@ } #endif - void eval_divide_knuth(const uintwide_t& other, uintwide_t* remainder) + constexpr void eval_divide_knuth(const uintwide_t& other, uintwide_t* remainder) { // Use Knuth's long division algorithm. // The loop-ordering of indexes in Knuth's original @@ -2245,7 +2240,7 @@ } } - void shl(const std::uint_fast32_t offset, const std::uint_fast32_t left_shift_amount) + constexpr void shl(const std::uint_fast32_t offset, const std::uint_fast32_t left_shift_amount) { if(offset > 0U) { @@ -2273,7 +2268,7 @@ } } - void shr(const std::uint_fast32_t offset, const std::uint_fast32_t right_shift_amount) + constexpr void shr(const std::uint_fast32_t offset, const std::uint_fast32_t right_shift_amount) { if(offset > 0U) { @@ -2302,7 +2297,7 @@ } // Read string function. - bool rd_string(const char* str_input) + constexpr bool rd_string(const char* str_input) { std::fill(values.begin(), values.end(), limb_type(0U)); @@ -2401,7 +2396,7 @@ return char_is_valid; } - void bitwise_not() + constexpr void bitwise_not() { for(std::uint_fast32_t i = 0U; i < number_of_limbs; ++i) { @@ -2409,7 +2404,7 @@ } } - void preincrement() + constexpr void preincrement() { // Implement pre-increment. std::uint_fast32_t i = 0U; @@ -2425,7 +2420,7 @@ } } - void predecrement() + constexpr void predecrement() { // Implement pre-decrement. std::uint_fast32_t i = 0U; @@ -2441,7 +2436,7 @@ } } - bool is_zero() const + constexpr bool is_zero() const { return std::all_of(values.cbegin(), values.cend(), @@ -2504,31 +2499,31 @@ namespace math { namespace wide_integer { // Non-member binary add, sub, mul, div, mod of (uintwide_t op uintwide_t). - template uintwide_t operator+ (const uintwide_t& left, const uintwide_t& right) { return uintwide_t(left).operator+=(right); } - template uintwide_t operator- (const uintwide_t& left, const uintwide_t& right) { return uintwide_t(left).operator-=(right); } - template uintwide_t operator* (const uintwide_t& left, const uintwide_t& right) { return uintwide_t(left).operator*=(right); } - template uintwide_t operator/ (const uintwide_t& left, const uintwide_t& right) { return uintwide_t(left).operator/=(right); } - template uintwide_t operator% (const uintwide_t& left, const uintwide_t& right) { return uintwide_t(left).operator%=(right); } + template constexpr uintwide_t operator+ (const uintwide_t& left, const uintwide_t& right) { return uintwide_t(left).operator+=(right); } + template constexpr uintwide_t operator- (const uintwide_t& left, const uintwide_t& right) { return uintwide_t(left).operator-=(right); } + template constexpr uintwide_t operator* (const uintwide_t& left, const uintwide_t& right) { return uintwide_t(left).operator*=(right); } + template constexpr uintwide_t operator/ (const uintwide_t& left, const uintwide_t& right) { return uintwide_t(left).operator/=(right); } + template constexpr uintwide_t operator% (const uintwide_t& left, const uintwide_t& right) { return uintwide_t(left).operator%=(right); } // Non-member binary logic operations of (uintwide_t op uintwide_t). - template uintwide_t operator| (const uintwide_t& left, const uintwide_t& right) { return uintwide_t(left).operator|=(right); } - template uintwide_t operator^ (const uintwide_t& left, const uintwide_t& right) { return uintwide_t(left).operator^=(right); } - template uintwide_t operator& (const uintwide_t& left, const uintwide_t& right) { return uintwide_t(left).operator&=(right); } + template constexpr uintwide_t operator| (const uintwide_t& left, const uintwide_t& right) { return uintwide_t(left).operator|=(right); } + template constexpr uintwide_t operator^ (const uintwide_t& left, const uintwide_t& right) { return uintwide_t(left).operator^=(right); } + template constexpr uintwide_t operator& (const uintwide_t& left, const uintwide_t& right) { return uintwide_t(left).operator&=(right); } // Non-member binary add, sub, mul, div, mod of (uintwide_t op IntegralType). template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), uintwide_t>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), uintwide_t>::type operator+(const uintwide_t& u, const IntegralType& v) { return uintwide_t(u).operator+=(uintwide_t(v)); } template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), uintwide_t>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), uintwide_t>::type operator-(const uintwide_t& u, const IntegralType& v) { return uintwide_t(u).operator-=(uintwide_t(v)); } template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), uintwide_t>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), uintwide_t>::type operator*(const uintwide_t& u, const IntegralType& v) { // TBD: Make separate functions for signed/unsigned IntegralType. @@ -2537,21 +2532,21 @@ } template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), uintwide_t>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), uintwide_t>::type operator/(const uintwide_t& u, const IntegralType& v) { return uintwide_t(u).operator/=(uintwide_t(v)); } template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true) - && (std::is_unsigned ::value == false)), uintwide_t>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true) + && (std::is_unsigned ::value == false)), uintwide_t>::type operator%(const uintwide_t& u, const IntegralType& v) { return uintwide_t(u).operator%=(uintwide_t(v)); } template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true) - && (std::is_unsigned ::value == true) - && (std::numeric_limits::digits <= std::numeric_limits::digits)), typename uintwide_t::limb_type>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true) + && (std::is_unsigned ::value == true) + && (std::numeric_limits::digits <= std::numeric_limits::digits)), typename uintwide_t::limb_type>::type operator%(const uintwide_t& u, const IntegralType& v) { uintwide_t remainder; @@ -2564,26 +2559,26 @@ } template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true) - && (std::is_unsigned ::value == true) - && (std::numeric_limits::digits > std::numeric_limits::digits)), uintwide_t>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true) + && (std::is_unsigned ::value == true) + && (std::numeric_limits::digits > std::numeric_limits::digits)), uintwide_t>::type operator%(const uintwide_t& u, const IntegralType& v) { return uintwide_t(u).operator%=(uintwide_t(v)); } // Non-member binary add, sub, mul, div, mod of (IntegralType op uintwide_t). template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), uintwide_t>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), uintwide_t>::type operator+(const IntegralType& u, const uintwide_t& v) { return uintwide_t(u).operator+=(v); } template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), uintwide_t>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), uintwide_t>::type operator-(const IntegralType& u, const uintwide_t& v) { return uintwide_t(u).operator-=(v); } template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), uintwide_t>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), uintwide_t>::type operator*(const IntegralType& u, const uintwide_t& v) { // TBD: Make separate functions for signed/unsigned IntegralType. @@ -2592,126 +2587,126 @@ } template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), uintwide_t>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), uintwide_t>::type operator/(const IntegralType& u, const uintwide_t& v) { return uintwide_t(u).operator/=(v); } template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), uintwide_t>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), uintwide_t>::type operator%(const IntegralType& u, const uintwide_t& v) { return uintwide_t(u).operator%=(v); } // Non-member binary logic operations of (uintwide_t op IntegralType). template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), uintwide_t>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), uintwide_t>::type operator|(const uintwide_t& u, const IntegralType& v) { return uintwide_t(u).operator|=(uintwide_t(v)); } template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), uintwide_t>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), uintwide_t>::type operator^(const uintwide_t& u, const IntegralType& v) { return uintwide_t(u).operator^=(uintwide_t(v)); } template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), uintwide_t>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), uintwide_t>::type operator&(const uintwide_t& u, const IntegralType& v) { return uintwide_t(u).operator&=(uintwide_t(v)); } // Non-member binary binary logic operations of (IntegralType op uintwide_t). template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), uintwide_t>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), uintwide_t>::type operator|(const IntegralType& u, const uintwide_t& v) { return uintwide_t(u).operator|=(v); } template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), uintwide_t>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), uintwide_t>::type operator^(const IntegralType& u, const uintwide_t& v) { return uintwide_t(u).operator^=(v); } template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), uintwide_t>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), uintwide_t>::type operator&(const IntegralType& u, const uintwide_t& v) { return uintwide_t(u).operator&=(v); } // Non-member shift functions of (uintwide_t shift IntegralType). template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), uintwide_t>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), uintwide_t>::type operator<<(const uintwide_t& u, const IntegralType n) { return uintwide_t(u).operator<<=(n); } template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), uintwide_t>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), uintwide_t>::type operator>>(const uintwide_t& u, const IntegralType n) { return uintwide_t(u).operator>>=(n); } // Non-member comparison functions of (uintwide_t cmp uintwide_t). - template bool operator==(const uintwide_t& u, const uintwide_t& v) { return u.operator==(v); } - template bool operator!=(const uintwide_t& u, const uintwide_t& v) { return u.operator!=(v); } - template bool operator> (const uintwide_t& u, const uintwide_t& v) { return u.operator> (v); } - template bool operator< (const uintwide_t& u, const uintwide_t& v) { return u.operator< (v); } - template bool operator>=(const uintwide_t& u, const uintwide_t& v) { return u.operator>=(v); } - template bool operator<=(const uintwide_t& u, const uintwide_t& v) { return u.operator<=(v); } + template constexpr bool operator==(const uintwide_t& u, const uintwide_t& v) { return u.operator==(v); } + template constexpr bool operator!=(const uintwide_t& u, const uintwide_t& v) { return u.operator!=(v); } + template constexpr bool operator> (const uintwide_t& u, const uintwide_t& v) { return u.operator> (v); } + template constexpr bool operator< (const uintwide_t& u, const uintwide_t& v) { return u.operator< (v); } + template constexpr bool operator>=(const uintwide_t& u, const uintwide_t& v) { return u.operator>=(v); } + template constexpr bool operator<=(const uintwide_t& u, const uintwide_t& v) { return u.operator<=(v); } // Non-member comparison functions of (uintwide_t cmp IntegralType). template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), bool>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), bool>::type operator==(const uintwide_t& u, const IntegralType& v) { return u.operator==(uintwide_t(v)); } template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), bool>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), bool>::type operator!=(const uintwide_t& u, const IntegralType& v) { return u.operator!=(uintwide_t(v)); } template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), bool>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), bool>::type operator> (const uintwide_t& u, const IntegralType& v) { return u.operator> (uintwide_t(v)); } template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), bool>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), bool>::type operator< (const uintwide_t& u, const IntegralType& v) { return u.operator< (uintwide_t(v)); } template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), bool>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), bool>::type operator>=(const uintwide_t& u, const IntegralType& v) { return u.operator>=(uintwide_t(v)); } template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), bool>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), bool>::type operator<=(const uintwide_t& u, const IntegralType& v) { return u.operator<=(uintwide_t(v)); } // Non-member comparison functions of (IntegralType cmp uintwide_t). template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), bool>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), bool>::type operator==(const IntegralType& u, const uintwide_t& v) { return uintwide_t(u).operator==(v); } template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), bool>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), bool>::type operator!=(const IntegralType& u, const uintwide_t& v) { return uintwide_t(u).operator!=(v); } template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), bool>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), bool>::type operator> (const IntegralType& u, const uintwide_t& v) { return uintwide_t(u).operator> (v); } template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), bool>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), bool>::type operator< (const IntegralType& u, const uintwide_t& v) { return uintwide_t(u).operator< (v); } template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), bool>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), bool>::type operator>=(const IntegralType& u, const uintwide_t& v) { return uintwide_t(u).operator>=(v); } template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true)), bool>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true)), bool>::type operator<=(const IntegralType& u, const uintwide_t& v) { return uintwide_t(u).operator<=(v); } #if defined(WIDE_INTEGER_DISABLE_IOSTREAM) @@ -2805,7 +2800,7 @@ namespace detail { template - inline std::uint_fast32_t lsb_helper(const UnsignedIntegralType& x) + inline constexpr std::uint_fast32_t lsb_helper(const UnsignedIntegralType& x) { // Compile-time checks. static_assert(( (std::is_fundamental::value == true) @@ -2834,7 +2829,7 @@ } template - inline std::uint_fast32_t msb_helper(const UnsignedIntegralType& u) + constexpr std::uint_fast32_t msb_helper(const UnsignedIntegralType& u) { // Compile-time checks. static_assert(( (std::is_fundamental::value == true) @@ -2861,7 +2856,7 @@ } template<> - inline std::uint_fast32_t msb_helper(const std::uint32_t& u) + constexpr std::uint_fast32_t msb_helper(const std::uint32_t& u) { std::uint_fast32_t r(0); @@ -2878,7 +2873,7 @@ } template<> - inline std::uint_fast32_t msb_helper(const std::uint16_t& u) + constexpr std::uint_fast32_t msb_helper(const std::uint16_t& u) { std::uint_fast32_t r(0); @@ -2894,7 +2889,7 @@ } template<> - inline std::uint_fast32_t msb_helper(const std::uint8_t& u) + constexpr std::uint_fast32_t msb_helper(const std::uint8_t& u) { std::uint_fast32_t r(0); @@ -2913,8 +2908,8 @@ template - void swap(uintwide_t& x, - uintwide_t& y) + constexpr void swap(uintwide_t& x, + uintwide_t& y) { if(&x != &y) { @@ -2930,7 +2925,7 @@ template - std::uint_fast32_t lsb(const uintwide_t& x) + constexpr std::uint_fast32_t lsb(const uintwide_t& x) { // Calculate the position of the least-significant bit. // Use a linear search starting from the least significant limbs. @@ -2960,7 +2955,7 @@ template - std::uint_fast32_t msb(const uintwide_t& x) + constexpr std::uint_fast32_t msb(const uintwide_t& x) { // Calculate the position of the most-significant bit. // Use a linear search starting from the most significant limbs. @@ -2990,7 +2985,7 @@ template - uintwide_t sqrt(const uintwide_t& m) + constexpr uintwide_t sqrt(const uintwide_t& m) { // Calculate the square root. @@ -3048,7 +3043,7 @@ template - uintwide_t cbrt(const uintwide_t& m) + constexpr uintwide_t cbrt(const uintwide_t& m) { // Calculate the cube root. @@ -3120,7 +3115,7 @@ template - uintwide_t rootk(const uintwide_t& m, + constexpr uintwide_t rootk(const uintwide_t& m, const std::uint_fast8_t k) { // Calculate the k'th root. @@ -3205,8 +3200,8 @@ const std::uint_fast32_t Digits2, typename LimbType, typename AllocatorType> - uintwide_t pow(const uintwide_t& b, - const OtherUnsignedIntegralTypeP& p) + constexpr uintwide_t pow(const uintwide_t& b, + const OtherUnsignedIntegralTypeP& p) { // Calculate (b ^ p). @@ -3257,9 +3252,9 @@ const std::uint_fast32_t Digits2, typename LimbType, typename AllocatorType> - uintwide_t powm(const uintwide_t& b, - const OtherUnsignedIntegralTypeP& p, - const OtherUnsignedIntegralTypeM& m) + constexpr uintwide_t powm(const uintwide_t& b, + const OtherUnsignedIntegralTypeP& p, + const OtherUnsignedIntegralTypeM& m) { // Calculate (b ^ p) % m. @@ -3315,7 +3310,7 @@ namespace detail { template - UshortType integer_gcd_reduce_short(UshortType u, UshortType v) + constexpr UshortType integer_gcd_reduce_short(UshortType u, UshortType v) { // This implementation of GCD reduction is based on an // adaptation of existing code from Boost.Multiprecision. @@ -3340,7 +3335,7 @@ } template - UlargeType integer_gcd_reduce_large(UlargeType u, UlargeType v) + constexpr UlargeType integer_gcd_reduce_large(UlargeType u, UlargeType v) { // This implementation of GCD reduction is based on an // adaptation of existing code from Boost.Multiprecision. @@ -3384,8 +3379,8 @@ template - uintwide_t gcd(const uintwide_t& a, - const uintwide_t& b) + constexpr uintwide_t gcd(const uintwide_t& a, + const uintwide_t& b) { // This implementation of GCD is an adaptation // of existing code from Boost.Multiprecision. @@ -3482,9 +3477,9 @@ } template - typename std::enable_if<( (std::is_fundamental::value == true) - && (std::is_integral ::value == true) - && (std::is_unsigned ::value == true)), UshortType>::type + constexpr typename std::enable_if<( (std::is_fundamental::value == true) + && (std::is_integral ::value == true) + && (std::is_unsigned ::value == true)), UshortType>::type gcd(const UshortType& u, const UshortType& v) { UshortType result; @@ -3548,8 +3543,8 @@ return *this; } - const result_type& get_a() const { return param_a; } - const result_type& get_b() const { return param_b; } + constexpr const result_type& get_a() const { return param_a; } + constexpr const result_type& get_b() const { return param_b; } void set_a(const result_type& a) { param_a = a; } void set_b(const result_type& b) { param_b = b; } @@ -3558,14 +3553,14 @@ result_type param_a; result_type param_b; - friend inline bool operator==(const param_type& lhs, + friend inline constexpr bool operator==(const param_type& lhs, const param_type& rhs) { return ( (lhs.param_a == rhs.param_a) && (lhs.param_b == rhs.param_b)); } - friend inline bool operator!=(const param_type& lhs, + friend inline constexpr bool operator!=(const param_type& lhs, const param_type& rhs) { return ( (lhs.param_a != rhs.param_a) @@ -3600,7 +3595,7 @@ template::digits> - result_type operator()(GeneratorType& generator) + constexpr result_type operator()(GeneratorType& generator) { return generate(generator, my_params); } @@ -3618,7 +3613,7 @@ template::digits> - result_type generate(GeneratorType& input_generator, + constexpr result_type generate(GeneratorType& input_generator, const param_type& input_params) { // Generate random numbers r, where a <= r <= b. @@ -3683,7 +3678,7 @@ template - bool operator==(const uniform_int_distribution& lhs, + constexpr bool operator==(const uniform_int_distribution& lhs, const uniform_int_distribution& rhs) { return (lhs.param() == rhs.param()); @@ -3692,7 +3687,7 @@ template - bool operator!=(const uniform_int_distribution& lhs, + constexpr bool operator!=(const uniform_int_distribution& lhs, const uniform_int_distribution& rhs) { return (lhs.param() != rhs.param()); From c78f05415beed3eda243d2e23847c334ce853a15 Mon Sep 17 00:00:00 2001 From: John McFarlane Date: Sat, 1 May 2021 17:52:57 +0100 Subject: [PATCH 2/8] Replace std::fill with constexpr equivalent From cppreference.cpp: https://en.cppreference.com/w/cpp/algorithm/fill --- math/wide_integer/uintwide_t.h | 79 +++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 35 deletions(-) diff --git a/math/wide_integer/uintwide_t.h b/math/wide_integer/uintwide_t.h index a953391c..5a5808f4 100644 --- a/math/wide_integer/uintwide_t.h +++ b/math/wide_integer/uintwide_t.h @@ -362,6 +362,15 @@ namespace math { namespace wide_integer { namespace detail { + template + constexpr void fill(ForwardIt first, ForwardIt last, const T& value) + { + for(; first != last; ++first) + { + *first = value; + } + } + template @@ -376,9 +385,9 @@ const typename base_class_type::allocator_type& a = typename base_class_type::allocator_type()) : base_class_type(MySize, typename base_class_type::value_type(), a) { - std::fill(base_class_type::begin(), - base_class_type::begin() + (std::min)(MySize, (std::uint_fast32_t) s), - v); + fill(base_class_type::begin(), + base_class_type::begin() + (std::min)(MySize, (std::uint_fast32_t) s), + v); } constexpr fixed_dynamic_array(const fixed_dynamic_array& other_array) @@ -430,13 +439,13 @@ constexpr fixed_static_array(const typename base_class_type::size_type s, const typename base_class_type::value_type& v = typename base_class_type::value_type()) { - std::fill(base_class_type::begin(), - base_class_type::begin() + (std::min)(MySize, (std::uint_fast32_t) s), - v); + fill(base_class_type::begin(), + base_class_type::begin() + (std::min)(MySize, (std::uint_fast32_t) s), + v); - std::fill(base_class_type::begin() + (std::min)(MySize, (std::uint_fast32_t) s), - base_class_type::end(), - typename base_class_type::value_type()); + fill(base_class_type::begin() + (std::min)(MySize, (std::uint_fast32_t) s), + base_class_type::end(), + typename base_class_type::value_type()); } constexpr fixed_static_array(const fixed_static_array& other_array) @@ -449,9 +458,9 @@ other_array.cbegin() + (std::min)(OtherSize, MySize), base_class_type::begin()); - std::fill(base_class_type::begin() + (std::min)(OtherSize, MySize), - base_class_type::end(), - typename base_class_type::value_type()); + fill(base_class_type::begin() + (std::min)(OtherSize, MySize), + base_class_type::end(), + typename base_class_type::value_type()); } explicit constexpr fixed_static_array(std::initializer_list lst) @@ -460,9 +469,9 @@ lst.begin() + (std::min)((std::uint_fast32_t) lst.size(), MySize), base_class_type::begin()); - std::fill(base_class_type::begin() + (std::min)((std::uint_fast32_t) lst.size(), MySize), - base_class_type::end(), - typename base_class_type::value_type()); + fill(base_class_type::begin() + (std::min)((std::uint_fast32_t) lst.size(), MySize), + base_class_type::end(), + typename base_class_type::value_type()); } constexpr fixed_static_array(fixed_static_array&& other_array) @@ -749,7 +758,7 @@ right_shift_amount_v += std::uint_fast32_t(std::numeric_limits::digits); } - std::fill(values.begin() + index_u, values.end(), limb_type(0U)); + detail::fill(values.begin() + index_u, values.end(), limb_type(0U)); } // Constructors from built-in signed integral types. @@ -813,7 +822,7 @@ v.crepresentation().cbegin() + sz, values.begin()); - std::fill(values.begin() + sz, values.end(), limb_type(0U)); + detail::fill(values.begin() + sz, values.end(), limb_type(0U)); } // Constructor from a constant character string. @@ -821,7 +830,7 @@ { if(rd_string(str_input) == false) { - std::fill(values.begin(), values.end(), (std::numeric_limits::max)()); + detail::fill(values.begin(), values.end(), (std::numeric_limits::max)()); } } @@ -907,9 +916,9 @@ values.cend(), local_double_width_instance.representation().begin()); - std::fill(local_double_width_instance.representation().begin() + number_of_limbs, - local_double_width_instance.representation().end(), - limb_type(0U)); + fill(local_double_width_instance.representation().begin() + number_of_limbs, + local_double_width_instance.representation().end(), + limb_type(0U)); return local_double_width_instance; } @@ -1002,7 +1011,7 @@ { values.front() = 1U; - std::fill(values.begin() + 1U, values.end(), limb_type(0U)); + detail::fill(values.begin() + 1U, values.end(), limb_type(0U)); } else if(other.is_zero()) { @@ -1021,7 +1030,7 @@ { if(this == &other) { - std::fill(values.begin(), values.end(), limb_type(0U)); + detail::fill(values.begin(), values.end(), limb_type(0U)); } else { @@ -1115,7 +1124,7 @@ } else if(std::uint_fast32_t(n) >= my_digits) { - std::fill(values.begin(), values.end(), limb_type(0U)); + detail::fill(values.begin(), values.end(), limb_type(0U)); } else { @@ -1141,7 +1150,7 @@ } else if(std::uint_fast32_t(n) >= my_digits) { - std::fill(values.begin(), values.end(), limb_type(0U)); + detail::fill(values.begin(), values.end(), limb_type(0U)); } else { @@ -1171,7 +1180,7 @@ } else if(std::uint_fast32_t(n) >= my_digits) { - std::fill(values.begin(), values.end(), limb_type(0U)); + detail::fill(values.begin(), values.end(), limb_type(0U)); } else { @@ -1197,7 +1206,7 @@ } else if(std::uint_fast32_t(n) >= my_digits) { - std::fill(values.begin(), values.end(), limb_type(0U)); + detail::fill(values.begin(), values.end(), limb_type(0U)); } else { @@ -1789,7 +1798,7 @@ if(b == 0U) { - std::fill(r, r + count, limb_type(0U)); + detail::fill(r, r + count, limb_type(0U)); } else { @@ -2207,7 +2216,7 @@ // Clear the data elements that have not // been computed in the division algorithm. - std::fill(values.begin() + (m + 1U), values.end(), limb_type(0U)); + detail::fill(values.begin() + (m + 1U), values.end(), limb_type(0U)); if(remainder != nullptr) { @@ -2232,9 +2241,9 @@ } } - std::fill(remainder->values.begin() + n, - remainder->values.end(), - limb_type(0U)); + detail::fill(remainder->values.begin() + n, + remainder->values.end(), + limb_type(0U)); } } } @@ -2248,7 +2257,7 @@ values.data() + (number_of_limbs - offset), values.data() + number_of_limbs); - std::fill(values.begin(), values.begin() + offset, limb_type(0U)); + detail::fill(values.begin(), values.begin() + offset, limb_type(0U)); } limb_type part_from_previous_value = limb_type(0U); @@ -2276,7 +2285,7 @@ values.begin() + number_of_limbs, values.begin()); - std::fill(values.end() - offset, values.end(), limb_type(0U)); + detail::fill(values.end() - offset, values.end(), limb_type(0U)); } limb_type part_from_previous_value = limb_type(0U); @@ -2299,7 +2308,7 @@ // Read string function. constexpr bool rd_string(const char* str_input) { - std::fill(values.begin(), values.end(), limb_type(0U)); + detail::fill(values.begin(), values.end(), limb_type(0U)); const std::uint_fast32_t str_length = detail::strlen_unsafe(str_input); From 0734207873cdad6306d78b6539427af03d6b0b1e Mon Sep 17 00:00:00 2001 From: John McFarlane Date: Sat, 1 May 2021 18:14:26 +0100 Subject: [PATCH 3/8] Replace std::all_of with constexpr equivalent From cppreference.cpp: https://en.cppreference.com/w/cpp/algorithm/all_of --- math/wide_integer/uintwide_t.h | 67 ++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 24 deletions(-) diff --git a/math/wide_integer/uintwide_t.h b/math/wide_integer/uintwide_t.h index 5a5808f4..a61c71d8 100644 --- a/math/wide_integer/uintwide_t.h +++ b/math/wide_integer/uintwide_t.h @@ -371,6 +371,25 @@ } } + template + constexpr InputIt find_if_not(InputIt first, InputIt last, UnaryPredicate q) + { + for(; first != last; ++first) + { + if(!q(*first)) + { + return first; + } + } + return last; + } + + template< class InputIt, class UnaryPredicate > + constexpr bool all_of(InputIt first, InputIt last, UnaryPredicate p) + { + return find_if_not(first, last, p) == last; + } + template @@ -2447,12 +2466,12 @@ constexpr bool is_zero() const { - return std::all_of(values.cbegin(), - values.cend(), - [](const limb_type& u) -> bool - { - return (u == limb_type(0U)); - }); + return detail::all_of(values.cbegin(), + values.cend(), + [](const limb_type& u) -> bool + { + return (u == limb_type(0U)); + }); } }; @@ -3001,12 +3020,12 @@ using local_wide_integer_type = uintwide_t; using local_limb_type = typename local_wide_integer_type::limb_type; - const bool argument_is_zero = std::all_of(m.crepresentation().cbegin(), - m.crepresentation().cend(), - [](const local_limb_type& a) -> bool - { - return (a == 0U); - }); + const bool argument_is_zero = detail::all_of(m.crepresentation().cbegin(), + m.crepresentation().cend(), + [](const local_limb_type& a) -> bool + { + return (a == 0U); + }); local_wide_integer_type s; @@ -3061,12 +3080,12 @@ local_wide_integer_type s; - const bool argument_is_zero = std::all_of(m.crepresentation().cbegin(), - m.crepresentation().cend(), - [](const local_limb_type& a) -> bool - { - return (a == 0U); - }); + const bool argument_is_zero = detail::all_of(m.crepresentation().cbegin(), + m.crepresentation().cend(), + [](const local_limb_type& a) -> bool + { + return (a == 0U); + }); if(argument_is_zero) { @@ -3144,12 +3163,12 @@ } else { - const bool argument_is_zero = std::all_of(m.crepresentation().cbegin(), - m.crepresentation().cend(), - [](const local_limb_type& a) -> bool - { - return (a == 0U); - }); + const bool argument_is_zero = detail::all_of(m.crepresentation().cbegin(), + m.crepresentation().cend(), + [](const local_limb_type& a) -> bool + { + return (a == 0U); + }); if(argument_is_zero) { From bba6a13dbd3888449a336e41c47a1b4a435c00c6 Mon Sep 17 00:00:00 2001 From: John McFarlane Date: Sat, 1 May 2021 18:23:05 +0100 Subject: [PATCH 4/8] Replace std::copy with constexpr equivalent From cppreference.cpp: https://en.cppreference.com/w/cpp/algorithm/copy --- math/wide_integer/uintwide_t.h | 74 +++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/math/wide_integer/uintwide_t.h b/math/wide_integer/uintwide_t.h index a61c71d8..9bb661ae 100644 --- a/math/wide_integer/uintwide_t.h +++ b/math/wide_integer/uintwide_t.h @@ -362,6 +362,16 @@ namespace math { namespace wide_integer { namespace detail { + template + constexpr OutputIt copy(InputIt first, InputIt last, OutputIt d_first) + { + while(first != last) + { + *d_first++ = *first++; + } + return d_first; + } + template constexpr void fill(ForwardIt first, ForwardIt last, const T& value) { @@ -415,9 +425,9 @@ explicit fixed_dynamic_array(std::initializer_list lst) : base_class_type(MySize) { - std::copy(lst.begin(), - lst.begin() + (std::min)((std::uint_fast32_t) lst.size(), MySize), - base_class_type::begin()); + detail::copy(lst.begin(), + lst.begin() + (std::min)((std::uint_fast32_t) lst.size(), MySize), + base_class_type::begin()); } constexpr fixed_dynamic_array(fixed_dynamic_array&& other_array) @@ -473,9 +483,9 @@ template constexpr fixed_static_array(const fixed_static_array& other_array) { - std::copy(other_array.cbegin(), - other_array.cbegin() + (std::min)(OtherSize, MySize), - base_class_type::begin()); + copy(other_array.cbegin(), + other_array.cbegin() + (std::min)(OtherSize, MySize), + base_class_type::begin()); fill(base_class_type::begin() + (std::min)(OtherSize, MySize), base_class_type::end(), @@ -484,9 +494,9 @@ explicit constexpr fixed_static_array(std::initializer_list lst) { - std::copy(lst.begin(), - lst.begin() + (std::min)((std::uint_fast32_t) lst.size(), MySize), - base_class_type::begin()); + copy(lst.begin(), + lst.begin() + (std::min)((std::uint_fast32_t) lst.size(), MySize), + base_class_type::begin()); fill(base_class_type::begin() + (std::min)((std::uint_fast32_t) lst.size(), MySize), base_class_type::end(), @@ -823,9 +833,9 @@ typename std::enable_if<( (std::is_same::value == true) && (128U <= my_digits))>::type* = nullptr) { - std::copy(v.crepresentation().cbegin(), - v.crepresentation().cbegin() + (v.crepresentation().size() / 2U), - values.begin()); + detail::copy(v.crepresentation().cbegin(), + v.crepresentation().cbegin() + (v.crepresentation().size() / 2U), + values.begin()); } // Constructor from the another type having a different width but the same limb type. @@ -837,9 +847,9 @@ (std::min)(std::uint_fast32_t(v.crepresentation().size()), std::uint_fast32_t(number_of_limbs)); - std::copy(v.crepresentation().cbegin(), - v.crepresentation().cbegin() + sz, - values.begin()); + detail::copy(v.crepresentation().cbegin(), + v.crepresentation().cbegin() + sz, + values.begin()); detail::fill(values.begin() + sz, values.end(), limb_type(0U)); } @@ -931,9 +941,9 @@ { double_width_type local_double_width_instance; - std::copy(values.cbegin(), - values.cend(), - local_double_width_instance.representation().begin()); + copy(values.cbegin(), + values.cend(), + local_double_width_instance.representation().begin()); fill(local_double_width_instance.representation().begin() + number_of_limbs, local_double_width_instance.representation().end(), @@ -1555,9 +1565,9 @@ v.values.data(), local_number_of_limbs); - std::copy(result.cbegin(), - result.cbegin() + local_number_of_limbs, - u.values.begin()); + detail::copy(result.cbegin(), + result.cbegin() + local_number_of_limbs, + u.values.begin()); } template @@ -1586,9 +1596,9 @@ local_number_of_limbs, t.data()); - std::copy(result.cbegin(), - result.cbegin() + local_number_of_limbs, - u.values.begin()); + detail::copy(result.cbegin(), + result.cbegin() + local_number_of_limbs, + u.values.begin()); } static constexpr limb_type eval_add_n( limb_type* r, @@ -1945,7 +1955,7 @@ // r -> t0 eval_multiply_kara_n_by_n_to_2n(r2, a1, b1, nh, t0); eval_multiply_kara_n_by_n_to_2n(r0, a0, b0, nh, t0); - std::copy(r0, r0 + (2U * n), t0); + detail::copy(r0, r0 + (2U * n), t0); // Step 2 // r1 += a1*b1 @@ -2160,7 +2170,7 @@ } else { - std::copy(values.cbegin(), values.cend(), uu.begin()); + detail::copy(values.cbegin(), values.cend(), uu.begin()); uu[number_of_limbs - u_offset] = limb_type(0U); @@ -2241,9 +2251,9 @@ { if(d == 1U) { - std::copy(uu.cbegin(), - uu.cbegin() + (number_of_limbs - v_offset), - remainder->values.begin()); + detail::copy(uu.cbegin(), + uu.cbegin() + (number_of_limbs - v_offset), + remainder->values.begin()); } else { @@ -2300,9 +2310,9 @@ { if(offset > 0U) { - std::copy(values.begin() + offset, - values.begin() + number_of_limbs, - values.begin()); + detail::copy(values.begin() + offset, + values.begin() + number_of_limbs, + values.begin()); detail::fill(values.end() - offset, values.end(), limb_type(0U)); } From a9816dd5641f336be3fdcf702098877865060296 Mon Sep 17 00:00:00 2001 From: John McFarlane Date: Sat, 1 May 2021 18:57:14 +0100 Subject: [PATCH 5/8] Replace std::copy_backward with constexpr equivalent From cppreference.cpp: https://en.cppreference.com/w/cpp/algorithm/copy_backwardcopy --- math/wide_integer/uintwide_t.h | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/math/wide_integer/uintwide_t.h b/math/wide_integer/uintwide_t.h index 9bb661ae..bdb8be63 100644 --- a/math/wide_integer/uintwide_t.h +++ b/math/wide_integer/uintwide_t.h @@ -372,6 +372,16 @@ return d_first; } + template + constexpr BidirIt2 copy_backward(BidirIt1 first, BidirIt1 last, BidirIt2 d_last) + { + while(first != last) + { + *(--d_last) = *(--last); + } + return d_last; + } + template constexpr void fill(ForwardIt first, ForwardIt last, const T& value) { @@ -2282,9 +2292,9 @@ { if(offset > 0U) { - std::copy_backward(values.data(), - values.data() + (number_of_limbs - offset), - values.data() + number_of_limbs); + detail::copy_backward(values.data(), + values.data() + (number_of_limbs - offset), + values.data() + number_of_limbs); detail::fill(values.begin(), values.begin() + offset, limb_type(0U)); } From 4dcc58e77e70bb2ef4358aef4df9203cf6419a55 Mon Sep 17 00:00:00 2001 From: John McFarlane Date: Sat, 1 May 2021 19:07:09 +0100 Subject: [PATCH 6/8] Replace std::mismatch with constexpr equivalent From cppreference.cpp: https://en.cppreference.com/w/cpp/algorithm/mismatch --- math/wide_integer/uintwide_t.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/math/wide_integer/uintwide_t.h b/math/wide_integer/uintwide_t.h index bdb8be63..f2ad6c28 100644 --- a/math/wide_integer/uintwide_t.h +++ b/math/wide_integer/uintwide_t.h @@ -404,6 +404,16 @@ return last; } + template + constexpr std::pair mismatch(InputIt1 first1, InputIt1 last1, InputIt2 first2) + { + while(first1 != last1 && *first1 == *first2) + { + ++first1, ++first2; + } + return std::make_pair(first1, first2); + } + template< class InputIt, class UnaryPredicate > constexpr bool all_of(InputIt first, InputIt last, UnaryPredicate p) { @@ -1537,7 +1547,7 @@ local_const_reverse_iterator_type rcbegin_b(b + count); local_const_reverse_iterator_type rcend_b (b); - const auto mismatch_pair = std::mismatch(rcbegin_a, rcend_a, rcbegin_b); + const auto mismatch_pair = detail::mismatch(rcbegin_a, rcend_a, rcbegin_b); std::int_fast8_t n_return; From f6529a13c8329b5b32ac2f89da50cd6da0e003d4 Mon Sep 17 00:00:00 2001 From: John McFarlane Date: Sun, 2 May 2021 10:01:02 +0100 Subject: [PATCH 7/8] Replace std::fill_n with constexpr equivalent From cppreference.cpp: https://en.cppreference.com/w/cpp/algorithm/fill_n --- math/wide_integer/uintwide_t.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/math/wide_integer/uintwide_t.h b/math/wide_integer/uintwide_t.h index f2ad6c28..42e3cd72 100644 --- a/math/wide_integer/uintwide_t.h +++ b/math/wide_integer/uintwide_t.h @@ -391,6 +391,16 @@ } } + template + constexpr OutputIt fill_n(OutputIt first, Size count, const T& value) + { + for(Size i = 0; i < count; i++) + { + *first++ = value; + } + return first; + } + template constexpr InputIt find_if_not(InputIt first, InputIt last, UnaryPredicate q) { @@ -1789,7 +1799,7 @@ using local_limb_type = typename uintwide_t::limb_type; using local_double_limb_type = typename uintwide_t::double_limb_type; - std::fill_n(r, count, 0); + detail::fill_n(r, count, 0); for(std::uint_fast32_t i = 0U; i < count; ++i) { From f4681d406cce5e3e9296a4fa29b0db02d237cd7b Mon Sep 17 00:00:00 2001 From: John McFarlane Date: Sun, 2 May 2021 10:01:02 +0100 Subject: [PATCH 8/8] Value-initialise variables in constant expressions Required for C++17 conformance --- math/wide_integer/uintwide_t.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/math/wide_integer/uintwide_t.h b/math/wide_integer/uintwide_t.h index 42e3cd72..8c1bb5ea 100644 --- a/math/wide_integer/uintwide_t.h +++ b/math/wide_integer/uintwide_t.h @@ -1559,7 +1559,7 @@ const auto mismatch_pair = detail::mismatch(rcbegin_a, rcend_a, rcbegin_b); - std::int_fast8_t n_return; + std::int_fast8_t n_return{}; if((mismatch_pair.first != rcend_a) || (mismatch_pair.second != rcend_b)) { @@ -1588,7 +1588,7 @@ constexpr std::uint_fast32_t local_number_of_limbs = uintwide_t::number_of_limbs; - representation_type result; + representation_type result{}; eval_multiply_n_by_n_to_lo_part(result.data(), u.values.data(), @@ -2188,8 +2188,8 @@ detail::fixed_static_array , detail::fixed_dynamic_array>::type; - uu_array_type uu; - representation_type vv; + uu_array_type uu{}; + representation_type vv{}; if(d > limb_type(1U)) { @@ -2247,7 +2247,7 @@ // Replace u[j, ... j + n] by u[j, ... j + n] - q_hat * v[1, ... n]. // Set nv = q_hat * (v[1, ... n]). - uu_array_type nv; + uu_array_type nv{}; nv[n] = eval_multiply_1d(nv.data(), vv.data(), q_hat, n); @@ -2907,7 +2907,7 @@ using local_unsigned_integral_type = UnsignedIntegralType; - std::int_fast32_t i; + std::int_fast32_t i{}; // TBD: This could potentially be improved with a binary // search for the highest bit position in the type. @@ -3484,7 +3484,7 @@ // Let shift := lg K, where K is the greatest // power of 2 dividing both u and v. - std::uint_fast32_t left_shift_amount; + std::uint_fast32_t left_shift_amount{}; { const std::uint_fast32_t u_shift = lsb(u);