diff --git a/math/wide_integer/uintwide_t.h b/math/wide_integer/uintwide_t.h index 6d91dd3d..8c1bb5ea 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 + constexpr OutputIt copy(InputIt first, InputIt last, OutputIt d_first) + { + while(first != last) + { + *d_first++ = *first++; + } + 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) + { + for(; first != last; ++first) + { + *first = value; + } + } + + 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) + { + for(; first != last; ++first) + { + if(!q(*first)) + { + return first; + } + } + 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) + { + return find_if_not(first, last, p) == last; + } + template @@ -376,9 +444,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) @@ -387,9 +455,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) @@ -425,65 +493,63 @@ using base_class_type = std::array; 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(), - 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) : 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), - base_class_type::begin()); + copy(other_array.cbegin(), + 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 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), - base_class_type::begin()); + copy(lst.begin(), + 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) : 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 +626,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 +637,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 +664,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 +691,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 +801,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) @@ -751,12 +817,12 @@ 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. 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) @@ -797,44 +863,41 @@ 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. // 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()), 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()); - 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. - uintwide_t(const char* str_input) + constexpr uintwide_t(const char* str_input) { 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)()); } } // 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 +908,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 +921,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 +931,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,31 +967,31 @@ // 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; - std::copy(values.cbegin(), - values.cend(), - local_double_width_instance.representation().begin()); + copy(values.cbegin(), + 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; } // 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 +1012,7 @@ return *this; } - uintwide_t& operator-=(const uintwide_t& other) + constexpr uintwide_t& operator-=(const uintwide_t& other) { if(this == &other) { @@ -970,7 +1033,7 @@ return *this; } - uintwide_t& operator*=(const uintwide_t& other) + constexpr uintwide_t& operator*=(const uintwide_t& other) { if(this == &other) { @@ -984,7 +1047,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,13 +1064,13 @@ return *this; } - uintwide_t& operator/=(const uintwide_t& other) + constexpr uintwide_t& operator/=(const uintwide_t& other) { if(this == &other) { 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()) { @@ -1022,11 +1085,11 @@ return *this; } - uintwide_t& operator%=(const uintwide_t& other) + constexpr uintwide_t& operator%=(const uintwide_t& other) { if(this == &other) { - std::fill(values.begin(), values.end(), limb_type(0U)); + detail::fill(values.begin(), values.end(), limb_type(0U)); } else { @@ -1104,7 +1167,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) @@ -1120,7 +1183,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 { @@ -1134,7 +1197,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) @@ -1146,7 +1209,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 { @@ -1160,7 +1223,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) @@ -1176,7 +1239,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 { @@ -1190,7 +1253,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) @@ -1202,7 +1265,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 { @@ -1216,12 +1279,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 +1498,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 +1512,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 +1544,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; @@ -1494,9 +1557,9 @@ 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; + std::int_fast8_t n_return{}; if((mismatch_pair.first != rcend_a) || (mismatch_pair.second != rcend_b)) { @@ -1515,9 +1578,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. @@ -1525,22 +1588,22 @@ 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(), 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 - 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. @@ -1563,16 +1626,16 @@ 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 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 +1651,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 +1673,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 +1760,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 +1799,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)); + detail::fill_n(r, count, 0); for(std::uint_fast32_t i = 0U; i < count; ++i) { @@ -1785,16 +1848,16 @@ } } - 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; if(b == 0U) { - std::fill(r, r + count, limb_type(0U)); + detail::fill(r, r + count, limb_type(0U)); } else { @@ -1922,7 +1985,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 @@ -2029,7 +2092,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 @@ -2125,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)) { @@ -2137,7 +2200,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); @@ -2184,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); @@ -2212,15 +2275,15 @@ // 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) { 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 { @@ -2237,23 +2300,23 @@ } } - std::fill(remainder->values.begin() + n, - remainder->values.end(), - limb_type(0U)); + detail::fill(remainder->values.begin() + n, + remainder->values.end(), + limb_type(0U)); } } } } - 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) { - 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); - 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); @@ -2273,15 +2336,15 @@ } } - 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) { - std::copy(values.begin() + offset, - values.begin() + number_of_limbs, - values.begin()); + detail::copy(values.begin() + offset, + 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); @@ -2302,9 +2365,9 @@ } // 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)); + detail::fill(values.begin(), values.end(), limb_type(0U)); const std::uint_fast32_t str_length = detail::strlen_unsafe(str_input); @@ -2401,7 +2464,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 +2472,7 @@ } } - void preincrement() + constexpr void preincrement() { // Implement pre-increment. std::uint_fast32_t i = 0U; @@ -2425,7 +2488,7 @@ } } - void predecrement() + constexpr void predecrement() { // Implement pre-decrement. std::uint_fast32_t i = 0U; @@ -2441,14 +2504,14 @@ } } - bool is_zero() const + 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)); + }); } }; @@ -2504,31 +2567,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 +2600,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 +2627,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 +2655,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 +2868,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 +2897,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) @@ -2844,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. @@ -2861,7 +2924,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 +2941,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 +2957,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 +2976,8 @@ template - void swap(uintwide_t& x, - uintwide_t& y) + constexpr void swap(uintwide_t& x, + uintwide_t& y) { if(&x != &y) { @@ -2930,7 +2993,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 +3023,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,19 +3053,19 @@ template - uintwide_t sqrt(const uintwide_t& m) + constexpr uintwide_t sqrt(const uintwide_t& m) { // Calculate the square root. 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; @@ -3048,7 +3111,7 @@ template - uintwide_t cbrt(const uintwide_t& m) + constexpr uintwide_t cbrt(const uintwide_t& m) { // Calculate the cube root. @@ -3057,12 +3120,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) { @@ -3120,7 +3183,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. @@ -3140,12 +3203,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) { @@ -3205,8 +3268,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 +3320,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 +3378,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 +3403,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 +3447,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. @@ -3421,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); @@ -3482,9 +3545,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 +3611,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 +3621,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 +3663,7 @@ template::digits> - result_type operator()(GeneratorType& generator) + constexpr result_type operator()(GeneratorType& generator) { return generate(generator, my_params); } @@ -3618,7 +3681,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 +3746,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 +3755,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());