diff --git a/examples/example008_miller_rabin_prime.cpp b/examples/example008_miller_rabin_prime.cpp index ffab25cc..f05ae31d 100644 --- a/examples/example008_miller_rabin_prime.cpp +++ b/examples/example008_miller_rabin_prime.cpp @@ -104,7 +104,11 @@ namespace local_example008_miller_rabin_prime auto example008_miller_rabin_prime_check_known_primes() -> bool { + #if (defined(_MSC_VER) && defined(_DEBUG)) + using known_primes_array_type = std::array(UINT8_C(4))>; + #else using known_primes_array_type = std::array(UINT8_C(28))>; + #endif const known_primes_array_type known_primes = { @@ -112,6 +116,7 @@ namespace local_example008_miller_rabin_prime wide_integer_type("6316533715112802448288092604478054524383926634811945757057640178392735989589363869889681632218704486270766492727631128625563552112105808239098327091824521"), wide_integer_type("4858586217250992689079636758246308353014067931891277522662097117263017348927716654355835947116278934662184099633799310227887262043463022049904058963602113"), wide_integer_type("6019419207947545798517327619748393618031791796951797411174747320842950599875485354843571998416270218797959087329922954007679373990444302239974053043273173"), + #if !(defined(_MSC_VER) && defined(_DEBUG)) wide_integer_type("2623115045263242825415413671896042727657332322988674224271913776550889477454553016178535650310812678634291673863620916079255756983038819930429300055323617"), wide_integer_type("3003848015480415325081996052076028272879191508991266945638241025854760400469061295504211346716924852976586414875652009123799821021749062743721323009536589"), wide_integer_type("5568337324913975213045841890066332347573591111951280366169746765603974031759890673193278087261510160253710813073898966574448941498158599660295718450413969"), @@ -136,6 +141,7 @@ namespace local_example008_miller_rabin_prime wide_integer_type("6297032304320012154880388332146509431687962719889593388307760834122241251586999352542604072606959905346551948057937113980815914420810768937615250771878461"), wide_integer_type("6128722501467469312821769346772700466471416838690252468887811095595451174847178063191879577266340073924505285489011360630545669076007556359186484284685741"), wide_integer_type("5334118887555315545538097460404232946047447099403008196978701351362864400468260258361331949883359663365575253347639015242447351434717477630139194429944273") + #endif }; random_engine1_type generator(time_point()); @@ -165,14 +171,18 @@ auto ::math::wide_integer::example008_miller_rabin_prime() -> bool #endif { auto result_is_ok = true; - + for(auto i = static_cast(UINT8_C(0)); + #if (defined(_MSC_VER) && defined(_DEBUG)) + i < static_cast(UINT8_C(1)); + #else i < static_cast(UINT8_C(8)); + #endif ++i) { const auto result_prime_run_is_ok = local_example008_miller_rabin_prime::example008_miller_rabin_prime_run(); - + result_is_ok = (result_prime_run_is_ok && result_is_ok); } diff --git a/examples/example008a_miller_rabin_prime.cpp b/examples/example008a_miller_rabin_prime.cpp index 62c8322e..8863497b 100644 --- a/examples/example008a_miller_rabin_prime.cpp +++ b/examples/example008a_miller_rabin_prime.cpp @@ -43,6 +43,8 @@ #if (defined(__GNUC__) && !defined(__clang__) && (__GNUC__ >= 12)) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wrestrict" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" #endif #if (BOOST_VERSION < 108000) @@ -210,6 +212,7 @@ auto main() -> int // NOLINT(bugprone-exception-escape) #if (defined(__GNUC__) && !defined(__clang__) && (__GNUC__ >= 12)) #pragma GCC diagnostic pop +#pragma GCC diagnostic pop #endif #if (BOOST_VERSION < 108000) diff --git a/math/wide_integer/uintwide_t.h b/math/wide_integer/uintwide_t.h index 608302aa..20384463 100644 --- a/math/wide_integer/uintwide_t.h +++ b/math/wide_integer/uintwide_t.h @@ -535,12 +535,12 @@ using exact_unsigned_type = std::uintmax_t; }; - template struct uint_type_helper> { using exact_unsigned_type = std::uint8_t; using fast_unsigned_type = std::uint_fast8_t; using fast_signed_type = std::int_fast8_t; }; // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) - template struct uint_type_helper= 9U) && (BitCount <= 16U)>> { using exact_unsigned_type = std::uint16_t; using fast_unsigned_type = std::uint_fast16_t; using fast_signed_type = std::int_fast16_t; }; // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) - template struct uint_type_helper= 17U) && (BitCount <= 32U)>> { using exact_unsigned_type = std::uint32_t; using fast_unsigned_type = std::uint_fast32_t; using fast_signed_type = std::int_fast32_t; }; // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) - template struct uint_type_helper= 33U) && (BitCount <= 64U)>> { using exact_unsigned_type = std::uint64_t; using fast_unsigned_type = std::uint_fast64_t; using fast_signed_type = std::int_fast64_t; }; // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) + template struct uint_type_helper> { using exact_unsigned_type = std::uint8_t; using exact_signed_type = std::int8_t; using fast_unsigned_type = std::uint_fast8_t; using fast_signed_type = std::int_fast8_t; }; // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) + template struct uint_type_helper= 9U) && (BitCount <= 16U)>> { using exact_unsigned_type = std::uint16_t; using exact_signed_type = std::int16_t; using fast_unsigned_type = std::uint_fast16_t; using fast_signed_type = std::int_fast16_t; }; // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) + template struct uint_type_helper= 17U) && (BitCount <= 32U)>> { using exact_unsigned_type = std::uint32_t; using exact_signed_type = std::int32_t; using fast_unsigned_type = std::uint_fast32_t; using fast_signed_type = std::int_fast32_t; }; // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) + template struct uint_type_helper= 33U) && (BitCount <= 64U)>> { using exact_unsigned_type = std::uint64_t; using exact_signed_type = std::int64_t; using fast_unsigned_type = std::uint_fast64_t; using fast_signed_type = std::int_fast64_t; }; // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) #if defined(WIDE_INTEGER_HAS_LIMB_TYPE_UINT64) - template struct uint_type_helper= 65U) && (BitCount <= 128U)>> { using exact_unsigned_type = unsigned __int128; using fast_unsigned_type = unsigned __int128; using fast_signed_type = signed __int128; }; // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) + template struct uint_type_helper= 65U) && (BitCount <= 128U)>> { using exact_unsigned_type = unsigned __int128; using exact_signed_type = signed __int128; using fast_unsigned_type = unsigned __int128; using fast_signed_type = signed __int128; }; // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) #endif using unsigned_fast_type = typename uint_type_helper(std::numeric_limits::digits + 0)>::fast_unsigned_type; @@ -1072,16 +1072,20 @@ using base_class_type = std::array(MySize)>; public: - using size_type = size_t; - using value_type = typename base_class_type::value_type; + using size_type = size_t; + using value_type = typename base_class_type::value_type; + using allocator_type = std::allocator; static constexpr auto static_size() -> size_type { return MySize; } constexpr fixed_static_array() = default; explicit WIDE_INTEGER_CONSTEXPR fixed_static_array(const size_type s, - const value_type& v = value_type()) + const value_type& v = value_type(), + allocator_type a = allocator_type()) { + static_cast(a); + if(s < static_size()) { std::fill(base_class_type::begin(), base_class_type::begin() + s, v); @@ -1189,6 +1193,20 @@ return static_cast(p_str_copy - p_str); } + template + constexpr auto advance_and_point(InputIterator it, IntegralType n) -> InputIterator + { + using local_signed_integral_type = + std::conditional_t::value, + IntegralType, + typename detail::uint_type_helper(std::numeric_limits::digits)>::exact_signed_type>; + + using local_difference_type = typename std::iterator_traits::difference_type; + + return it + static_cast(static_cast(n)); + } + template(std::numeric_limits::digits * 2)>::exact_unsigned_type> constexpr auto make_lo(const UnsignedLargeType& u) -> UnsignedShortType @@ -1490,11 +1508,14 @@ // Constructors from built-in unsigned integral types that // are less wide than limb_type or exactly as wide as limb_type. template - constexpr uintwide_t(const UnsignedIntegralType v, // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) - std::enable_if_t<( std::is_integral ::value - && std::is_unsigned ::value - && (std::numeric_limits::digits <= std::numeric_limits::digits))>* = nullptr) // NOLINT(hicpp-named-parameter,readability-named-parameter) - : values(static_cast(UINT8_C(1)), v) { } + WIDE_INTEGER_CONSTEXPR + uintwide_t(const UnsignedIntegralType v, // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) + std::enable_if_t<( std::is_integral ::value + && std::is_unsigned ::value + && (std::numeric_limits::digits <= std::numeric_limits::digits))>* = nullptr) // NOLINT(hicpp-named-parameter,readability-named-parameter) + { + values.front() = v; + } // Constructors from built-in unsigned integral types that // are wider than limb_type, and do not have exactly the @@ -1508,18 +1529,18 @@ static_cast(p_nullparam == nullptr); auto right_shift_amount_v = static_cast(UINT8_C(0)); - auto index_u = static_cast(UINT8_C(0)); + auto u_it = values.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto) - for( ; ( (static_cast(index_u) < values.size()) // NOLINT(altera-id-dependent-backward-branch) + for( ; ( (u_it != values.end()) // NOLINT(altera-id-dependent-backward-branch) && (right_shift_amount_v < static_cast(std::numeric_limits::digits))); - ++index_u) + ++u_it) { - *(values.begin() + static_cast(index_u)) = static_cast(v >> static_cast(right_shift_amount_v)); + *u_it = static_cast(v >> static_cast(right_shift_amount_v)); right_shift_amount_v += static_cast(std::numeric_limits::digits); } - std::fill(values.begin() + static_cast(index_u), values.end(), static_cast(UINT8_C(0))); + std::fill(u_it, values.end(), static_cast(UINT8_C(0))); } // Constructors from built-in signed integral types. @@ -1527,6 +1548,7 @@ WIDE_INTEGER_CONSTEXPR uintwide_t(const SignedIntegralType v, // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) std::enable_if_t<( std::is_integral::value && std::is_signed ::value)>* p_nullparam = nullptr) + : values(number_of_limbs) { static_cast(p_nullparam == nullptr); @@ -1624,7 +1646,7 @@ if(!v_is_neg) { std::copy(v.crepresentation().cbegin(), - v.crepresentation().cbegin() + sz, + detail::advance_and_point(v.crepresentation().cbegin(), sz), values.begin()); } else @@ -1632,7 +1654,7 @@ const other_wide_integer_type uv(-v); std::copy(uv.crepresentation().cbegin(), - uv.crepresentation().cbegin() + sz, + detail::advance_and_point(uv.crepresentation().cbegin(), sz), values.begin()); negate(); @@ -1655,20 +1677,20 @@ if(!v_is_neg) { std::copy(v.crepresentation().cbegin(), - v.crepresentation().cbegin() + sz, + detail::advance_and_point(v.crepresentation().cbegin(), sz), values.begin()); - std::fill(values.begin() + sz, values.end(), static_cast(UINT8_C(0))); + std::fill(detail::advance_and_point(values.begin(), sz), values.end(), static_cast(UINT8_C(0))); } else { const other_wide_integer_type uv(-v); std::copy(uv.crepresentation().cbegin(), - uv.crepresentation().cbegin() + sz, + detail::advance_and_point(uv.crepresentation().cbegin(), sz), values.begin()); - std::fill(values.begin() + sz, values.end(), static_cast(UINT8_C(0))); + std::fill(detail::advance_and_point(values.begin(), sz), values.end(), static_cast(UINT8_C(0))); negate(); } @@ -1676,6 +1698,12 @@ // Constructor from a constant character string. WIDE_INTEGER_CONSTEXPR uintwide_t(const char* str_input) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) + : values + { + static_cast(number_of_limbs), + static_cast(UINT8_C(0)), + typename representation_type::allocator_type() + } { if(!rd_string(str_input)) { @@ -1809,9 +1837,9 @@ const uintwide_t self(other); // Unary addition function. - const limb_type carry = eval_add_n(values.data(), // LCOV_EXCL_LINE - values.data(), - self.values.data(), + const limb_type carry = eval_add_n(values.begin(), // LCOV_EXCL_LINE + values.cbegin(), + self.values.cbegin(), static_cast(number_of_limbs), static_cast(UINT8_C(0))); @@ -1820,9 +1848,9 @@ else { // Unary addition function. - const limb_type carry = eval_add_n(values.data(), - values.data(), - other.values.data(), + const limb_type carry = eval_add_n(values.begin(), + values.cbegin(), + other.values.cbegin(), static_cast(number_of_limbs), static_cast(UINT8_C(0))); @@ -1836,14 +1864,14 @@ { if(this == &other) { - values.fill(static_cast(UINT8_C(0))); + std::fill(values.begin(), values.end(), static_cast(UINT8_C(0))); // LCOV_EXCL_LINE } else { // Unary subtraction function. - const limb_type has_borrow = eval_subtract_n(values.data(), - values.data(), - other.values.data(), + const limb_type has_borrow = eval_subtract_n(values.begin(), + values.cbegin(), + other.values.cbegin(), number_of_limbs, false); @@ -1873,12 +1901,12 @@ { if(v == static_cast(UINT8_C(0))) { - values.fill(static_cast(UINT8_C(0))); + std::fill(values.begin(), values.end(), static_cast(UINT8_C(0))); } else if(v > static_cast(UINT8_C(1))) { - static_cast(eval_multiply_1d(values.data(), - values.data(), + static_cast(eval_multiply_1d(values.begin(), + values.cbegin(), v, number_of_limbs)); } @@ -1892,7 +1920,7 @@ { values.front() = static_cast(UINT8_C(1)); - std::fill(values.begin() + 1U, values.end(), static_cast(UINT8_C(0))); + std::fill(detail::advance_and_point(values.begin(), 1U), values.end(), static_cast(UINT8_C(0))); // LCOV_EXCL_LINE } else if(other.is_zero()) { @@ -1995,9 +2023,11 @@ if(this != &other) { // Perform bitwise OR. - for(auto i = static_cast(UINT8_C(0)); i < number_of_limbs; ++i) + auto bi = other.values.cbegin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto) // LCOV_EXCL_LINE + + for(auto ai = values.begin(); ai != values.end(); ++ai) // NOLINT(altera-id-dependent-backward-branch,llvm-qualified-auto,readability-qualified-auto) { - *(values.begin() + static_cast(i)) = static_cast(*(values.cbegin() + static_cast(i)) | *(other.values.cbegin() + static_cast(i))); + *ai = static_cast(*ai | *bi++); } } @@ -2008,14 +2038,16 @@ { if(this == &other) { - values.fill(static_cast(UINT8_C(0))); + std::fill(values.begin(), values.end(), static_cast(UINT8_C(0))); // LCOV_EXCL_LINE } else { // Perform bitwise XOR. - for(auto i = static_cast(UINT8_C(0)); i < number_of_limbs; ++i) + auto bi = other.values.cbegin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto) // LCOV_EXCL_LINE + + for(auto ai = values.begin(); ai != values.end(); ++ai) // NOLINT(altera-id-dependent-backward-branch,llvm-qualified-auto,readability-qualified-auto) { - *(values.begin() + static_cast(i)) = static_cast(*(values.cbegin() + static_cast(i)) ^ *(other.values.cbegin() + static_cast(i))); + *ai = static_cast(*ai ^ *bi++); } } @@ -2027,9 +2059,11 @@ if(this != &other) // LCOV_EXCL_LINE { // Perform bitwise AND. - for(auto i = static_cast(UINT8_C(0)); i < number_of_limbs; ++i) + auto bi = other.values.cbegin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto) + + for(auto ai = values.begin(); ai != values.end(); ++ai) // NOLINT(altera-id-dependent-backward-branch,llvm-qualified-auto,readability-qualified-auto) { - *(values.begin() + static_cast(i)) = static_cast(*(values.cbegin() + static_cast(i)) & *(other.values.cbegin() + static_cast(i))); + *ai = static_cast(*ai & *bi++); } } @@ -2475,8 +2509,8 @@ std::enable_if_t<(!RePhraseIsSigned)> const* = nullptr> WIDE_INTEGER_NODISCARD WIDE_INTEGER_CONSTEXPR auto compare(const uintwide_t& other) const -> std::int_fast8_t { - return compare_ranges(values.data(), - other.values.data(), + return compare_ranges(values.cbegin(), + other.values.cbegin(), uintwide_t::number_of_limbs); } @@ -2499,8 +2533,8 @@ } else { - n_result = compare_ranges(values.data(), - other.values.data(), + n_result = compare_ranges(values.cbegin(), + other.values.cbegin(), uintwide_t::number_of_limbs); } @@ -2527,23 +2561,41 @@ // The denominator has one single limb. // Use a one-dimensional division algorithm. - auto long_numerator = static_cast(UINT8_C(0)); - - auto hi_part = static_cast(UINT8_C(0)); + auto long_numerator = double_limb_type { }; + auto hi_part = static_cast(UINT8_C(0)); - for(auto i = static_cast(static_cast(number_of_limbs - static_cast(UINT8_C(1))) - u_offset); static_cast(i) >= static_cast(INT8_C(0)); --i) // NOLINT(altera-id-dependent-backward-branch) { - long_numerator = - static_cast + auto ri = + static_cast ( - static_cast(*(values.cbegin() + static_cast(i))) - + static_cast(static_cast(long_numerator - static_cast(static_cast(short_denominator) * hi_part)) << static_cast(std::numeric_limits::digits)) + detail::advance_and_point + ( + values.begin(), + static_cast(number_of_limbs - static_cast(u_offset)) + ) ); - *(values.begin() + static_cast(i)) = - detail::make_lo(static_cast(long_numerator / short_denominator)); + for( ; ri != values.rend(); ++ri) // NOLINT(altera-id-dependent-backward-branch) + { + long_numerator = + static_cast + ( + *ri + + static_cast + ( + static_cast + ( + long_numerator + - static_cast(static_cast(short_denominator) * hi_part) + ) + << static_cast(std::numeric_limits::digits) + ) + ); - hi_part = *(values.cbegin() + static_cast(i)); + *ri = detail::make_lo(static_cast(long_numerator / short_denominator)); + + hi_part = *ri; + } } if(remainder != nullptr) @@ -2650,7 +2702,13 @@ } private: - representation_type values { }; // NOLINT(readability-identifier-naming) + representation_type + values // NOLINT(readability-identifier-naming) + { + static_cast(number_of_limbs), + static_cast(UINT8_C(0)), + typename representation_type::allocator_type() + }; friend auto ::test_uintwide_t_edge::test_various_isolated_edge_cases() -> bool; @@ -2695,8 +2753,8 @@ { auto n_return = static_cast(INT8_C(0)); - std::reverse_iterator pa(a + count); - std::reverse_iterator pb(b + count); + std::reverse_iterator pa(detail::advance_and_point(a, count)); + std::reverse_iterator pb(detail::advance_and_point(b, count)); while(pa != std::reverse_iterator(a)) // NOLINT(altera-id-dependent-backward-branch) { @@ -2763,7 +2821,7 @@ static_cast ( u - | static_cast(static_cast(*(p_limb + static_cast(i))) << static_cast(static_cast(std::numeric_limits::digits) * i)) + | static_cast(static_cast(*detail::advance_and_point(p_limb, static_cast(i))) << static_cast(static_cast(std::numeric_limits::digits) * i)) ); } @@ -2786,7 +2844,7 @@ // or equally as wide as the limb width or wider than the limb width. return ((digits_ratio_type::value < static_cast(UINT8_C(2))) ? static_cast(*values.cbegin()) - : digits_ratio_type::extract(values.data(), ilim)); + : digits_ratio_type::extract(values.cbegin(), ilim)); } #if !defined(WIDE_INTEGER_DISABLE_FLOAT_INTEROP) @@ -2815,6 +2873,8 @@ auto ldexp_runner = one_ldbl; + auto ui = detail::advance_and_point(u.values.cbegin(), static_cast(UINT8_C(0))); // NOLINT(llvm-qualified-auto,readability-qualified-auto) + for(auto i = static_cast(UINT8_C(0)); i < ilim; ++i) // NOLINT(altera-id-dependent-backward-branch) { auto ld = static_cast(0.0L); @@ -2824,7 +2884,7 @@ j < static_cast(std::numeric_limits::digits); ++j) { - if(static_cast(*(u.values.cbegin() + static_cast(i)) & lm_mask) != static_cast(UINT8_C(0))) + if(static_cast(*ui & lm_mask) != static_cast(UINT8_C(0))) { ld = static_cast(ld + ldexp_runner); } @@ -2836,6 +2896,8 @@ } a += static_cast(ld); + + ++ui; } return static_cast((!u_is_neg) ? a : -a); @@ -2852,19 +2914,26 @@ // Unary multiplication function using schoolbook multiplication, // but we only need to retain the low half of the n*n algorithm. // In other words, this is an n*n->n bit multiplication. + using local_other_wide_integer_type = uintwide_t; - constexpr size_t local_number_of_limbs = - uintwide_t::number_of_limbs; + const auto local_other_number_of_limbs = local_other_wide_integer_type::number_of_limbs; - representation_type result { }; + using local_other_representation_type = typename local_other_wide_integer_type::representation_type; + + local_other_representation_type result + { + static_cast(local_other_number_of_limbs), + static_cast(UINT8_C(0)), + typename representation_type::allocator_type() + }; - eval_multiply_n_by_n_to_lo_part(result.data(), - u.values.data(), - v.values.data(), - local_number_of_limbs); + eval_multiply_n_by_n_to_lo_part(result.begin(), + u.values.cbegin(), + v.values.cbegin(), + local_other_number_of_limbs); std::copy(result.cbegin(), - result.cbegin() + local_number_of_limbs, + detail::advance_and_point(result.cbegin(), local_other_number_of_limbs), u.values.begin()); } @@ -2904,11 +2973,11 @@ result_array_type result; storage_array_type t; - eval_multiply_kara_n_by_n_to_2n(result.data(), - u.values.data(), - v.values.data(), + eval_multiply_kara_n_by_n_to_2n(result.begin(), + u.values.cbegin(), + v.values.cbegin(), local_number_of_limbs, - t.data()); + t.begin()); std::copy(result.cbegin(), result.cbegin() + local_number_of_limbs, @@ -2939,17 +3008,19 @@ typename detail::uint_type_helper(std::numeric_limits::digits * 2)>::exact_unsigned_type; using result_difference_type = typename std::iterator_traits::difference_type; - using left_difference_type = typename std::iterator_traits::difference_type; - using right_difference_type = typename std::iterator_traits::difference_type; for(auto i = static_cast(UINT8_C(0)); i < count; ++i) { const auto uv_as_ularge = - static_cast(static_cast(static_cast(*(u + static_cast(i))) + *(v + static_cast(i))) + carry_out); + static_cast + ( + static_cast(static_cast(*u++) + *v++) + + carry_out + ); carry_out = static_cast(detail::make_hi(uv_as_ularge)); - *(r + static_cast(i)) = static_cast(uv_as_ularge); + *detail::advance_and_point(r, static_cast(i)) = static_cast(uv_as_ularge); } return static_cast(carry_out); @@ -2984,16 +3055,25 @@ typename detail::uint_type_helper(std::numeric_limits::digits * 2)>::exact_unsigned_type; using result_difference_type = typename std::iterator_traits::difference_type; - using left_difference_type = typename std::iterator_traits::difference_type; - using right_difference_type = typename std::iterator_traits::difference_type; for(auto i = static_cast(UINT8_C(0)); i < count; ++i) { - const auto uv_as_ularge = static_cast(static_cast(static_cast(*(u + static_cast(i))) - *(v + static_cast(i))) - has_borrow_out); + const auto uv_as_ularge = + static_cast + ( + static_cast(static_cast(*u++) - *v++) + - has_borrow_out + ); - has_borrow_out = (detail::make_hi(uv_as_ularge) != static_cast(UINT8_C(0))) ? 1U : 0U; + has_borrow_out = + static_cast + ( + (detail::make_hi(uv_as_ularge) != static_cast(UINT8_C(0))) + ? static_cast(UINT8_C(1)) + : static_cast(UINT8_C(0)) + ); - *(r + static_cast(i)) = static_cast(uv_as_ularge); + *detail::advance_and_point(r, static_cast(i)) = static_cast(uv_as_ularge); } return (has_borrow_out != static_cast(UINT8_C(0))); @@ -3052,17 +3132,17 @@ local_double_limb_type r1; local_double_limb_type r2; - const auto a0b0 = static_cast(*(a + static_cast(0)) * static_cast(*(b + static_cast(0)))); - const auto a0b1 = static_cast(*(a + static_cast(0)) * static_cast(*(b + static_cast(1)))); - const auto a1b0 = static_cast(*(a + static_cast(1)) * static_cast(*(b + static_cast(0)))); - const auto a1b1 = static_cast(*(a + static_cast(1)) * static_cast(*(b + static_cast(1)))); + const auto a0b0 = static_cast(*detail::advance_and_point(a, static_cast(0)) * static_cast(*detail::advance_and_point(b, static_cast(0)))); + const auto a0b1 = static_cast(*detail::advance_and_point(a, static_cast(0)) * static_cast(*detail::advance_and_point(b, static_cast(1)))); + const auto a1b0 = static_cast(*detail::advance_and_point(a, static_cast(1)) * static_cast(*detail::advance_and_point(b, static_cast(0)))); + const auto a1b1 = static_cast(*detail::advance_and_point(a, static_cast(1)) * static_cast(*detail::advance_and_point(b, static_cast(1)))); // One special case is considered, the case of multiplication // of the form BITS/2 * BITS/2 = BITS. In this case, the algorithm // can be significantly simplified by using only the 'lower-halves' // of the data. - if( (*(a + static_cast(2)) == 0U) && (*(b + static_cast(2)) == 0U) - && (*(a + static_cast(3)) == 0U) && (*(b + static_cast(3)) == 0U)) + if( (*detail::advance_and_point(a, static_cast(2)) == 0U) && (*detail::advance_and_point(b, static_cast(2)) == 0U) + && (*detail::advance_and_point(a, static_cast(3)) == 0U) && (*detail::advance_and_point(b, static_cast(3)) == 0U)) { r1 = static_cast ( @@ -3085,7 +3165,7 @@ + detail::make_hi(a1b0) ) ; - *(r + static_cast(3)) + *detail::advance_and_point(r, static_cast(3)) = static_cast ( detail::make_hi(r2) @@ -3095,8 +3175,8 @@ } else { - const auto a0b2 = static_cast(*(a + static_cast(0)) * static_cast(*(b + static_cast(2)))); - const auto a2b0 = static_cast(*(a + static_cast(2)) * static_cast(*(b + static_cast(0)))); + const auto a0b2 = static_cast(*detail::advance_and_point(a, static_cast(0)) * static_cast(*detail::advance_and_point(b, static_cast(2)))); + const auto a2b0 = static_cast(*detail::advance_and_point(a, static_cast(2)) * static_cast(*detail::advance_and_point(b, static_cast(0)))); r1 = static_cast ( @@ -3121,14 +3201,14 @@ + detail::make_hi(a0b1) ) ; - *(r + static_cast(3)) + *detail::advance_and_point(r, static_cast(3)) = static_cast ( detail::make_hi(r2) - + static_cast (*(a + static_cast(3)) * static_cast(*(b + static_cast(0)))) - + static_cast (*(a + static_cast(2)) * static_cast(*(b + static_cast(1)))) - + static_cast (*(a + static_cast(1)) * static_cast(*(b + static_cast(2)))) - + static_cast (*(a + static_cast(0)) * static_cast(*(b + static_cast(3)))) + + static_cast (*detail::advance_and_point(a, static_cast(3)) * static_cast(*detail::advance_and_point(b, static_cast(0)))) + + static_cast (*detail::advance_and_point(a, static_cast(2)) * static_cast(*detail::advance_and_point(b, static_cast(1)))) + + static_cast (*detail::advance_and_point(a, static_cast(1)) * static_cast(*detail::advance_and_point(b, static_cast(2)))) + + static_cast (*detail::advance_and_point(a, static_cast(0)) * static_cast(*detail::advance_and_point(b, static_cast(3)))) + detail::make_hi(a2b0) + detail::make_hi(a1b1) + detail::make_hi(a0b2) @@ -3136,9 +3216,9 @@ ; } - *(r + static_cast(0)) = static_cast(a0b0); - *(r + static_cast(1)) = static_cast(r1); - *(r + static_cast(2)) = static_cast(r2); + *detail::advance_and_point(r, static_cast(0)) = static_cast(a0b0); + *detail::advance_and_point(r, static_cast(1)) = static_cast(r1); + *detail::advance_and_point(r, static_cast(2)) = static_cast(r2); } #if defined(WIDE_INTEGER_HAS_MUL_8_BY_8_UNROLL) @@ -3191,28 +3271,28 @@ // https://www.wolframalpha.com/input/?i=Column%5BCoefficientList%5B+++Expand%5B%28a0+%2B+a1+x+%2B+a2+x%5E2+%2B+a3+x%5E3%29+%28b0+%2B+b1+x+%2B+b2+x%5E2+%2B+b3+x%5E3%29%5D%2C++++x%5D%5D // ... and take the upper half of the pyramid. - const local_double_limb_type a0b0 = *(a + static_cast(0)) * static_cast(*(b + static_cast(0))); + const local_double_limb_type a0b0 = *detail::advance_and_point(a, static_cast(0)) * static_cast(*detail::advance_and_point(b, static_cast(0))); - const local_double_limb_type a1b0 = *(a + static_cast(1)) * static_cast(*(b + static_cast(0))); - const local_double_limb_type a0b1 = *(a + static_cast(0)) * static_cast(*(b + static_cast(1))); + const local_double_limb_type a1b0 = *detail::advance_and_point(a, static_cast(1)) * static_cast(*detail::advance_and_point(b, static_cast(0))); + const local_double_limb_type a0b1 = *detail::advance_and_point(a, static_cast(0)) * static_cast(*detail::advance_and_point(b, static_cast(1))); - const local_double_limb_type a2b0 = *(a + static_cast(2)) * static_cast(*(b + static_cast(0))); - const local_double_limb_type a1b1 = *(a + static_cast(1)) * static_cast(*(b + static_cast(1))); - const local_double_limb_type a0b2 = *(a + static_cast(0)) * static_cast(*(b + static_cast(2))); + const local_double_limb_type a2b0 = *detail::advance_and_point(a, static_cast(2)) * static_cast(*detail::advance_and_point(b, static_cast(0))); + const local_double_limb_type a1b1 = *detail::advance_and_point(a, static_cast(1)) * static_cast(*detail::advance_and_point(b, static_cast(1))); + const local_double_limb_type a0b2 = *detail::advance_and_point(a, static_cast(0)) * static_cast(*detail::advance_and_point(b, static_cast(2))); - const local_double_limb_type a3b0 = *(a + static_cast(3)) * static_cast(*(b + static_cast(0))); - const local_double_limb_type a2b1 = *(a + static_cast(2)) * static_cast(*(b + static_cast(1))); - const local_double_limb_type a1b2 = *(a + static_cast(1)) * static_cast(*(b + static_cast(2))); - const local_double_limb_type a0b3 = *(a + static_cast(0)) * static_cast(*(b + static_cast(3))); + const local_double_limb_type a3b0 = *detail::advance_and_point(a, static_cast(3)) * static_cast(*detail::advance_and_point(b, static_cast(0))); + const local_double_limb_type a2b1 = *detail::advance_and_point(a, static_cast(2)) * static_cast(*detail::advance_and_point(b, static_cast(1))); + const local_double_limb_type a1b2 = *detail::advance_and_point(a, static_cast(1)) * static_cast(*detail::advance_and_point(b, static_cast(2))); + const local_double_limb_type a0b3 = *detail::advance_and_point(a, static_cast(0)) * static_cast(*detail::advance_and_point(b, static_cast(3))); - const local_double_limb_type a3b1 = *(a + static_cast(3)) * static_cast(*(b + static_cast(1))); - const local_double_limb_type a2b2 = *(a + static_cast(2)) * static_cast(*(b + static_cast(2))); - const local_double_limb_type a1b3 = *(a + static_cast(1)) * static_cast(*(b + static_cast(3))); + const local_double_limb_type a3b1 = *detail::advance_and_point(a, static_cast(3)) * static_cast(*detail::advance_and_point(b, static_cast(1))); + const local_double_limb_type a2b2 = *detail::advance_and_point(a, static_cast(2)) * static_cast(*detail::advance_and_point(b, static_cast(2))); + const local_double_limb_type a1b3 = *detail::advance_and_point(a, static_cast(1)) * static_cast(*detail::advance_and_point(b, static_cast(3))); - const local_double_limb_type a3b2 = *(a + static_cast(3)) * static_cast(*(b + static_cast(2))); - const local_double_limb_type a2b3 = *(a + static_cast(2)) * static_cast(*(b + static_cast(3))); + const local_double_limb_type a3b2 = *detail::advance_and_point(a, static_cast(3)) * static_cast(*detail::advance_and_point(b, static_cast(2))); + const local_double_limb_type a2b3 = *detail::advance_and_point(a, static_cast(2)) * static_cast(*detail::advance_and_point(b, static_cast(3))); - const local_double_limb_type a3b3 = *(a + static_cast(3)) * static_cast(*(b + static_cast(3))); + const local_double_limb_type a3b3 = *detail::advance_and_point(a, static_cast(3)) * static_cast(*detail::advance_and_point(b, static_cast(3))); local_double_limb_type rd1; local_double_limb_type rd2; @@ -3225,10 +3305,10 @@ // of the form BITS/2 * BITS/2 = BITS. In this case, the algorithm // can be significantly simplified by using only the 'lower-halves' // of the data. - if( (*(a + static_cast(INT32_C(7))) == 0U) && (*(b + static_cast(INT32_C(7))) == 0U) - && (*(a + static_cast(INT32_C(6))) == 0U) && (*(b + static_cast(INT32_C(6))) == 0U) - && (*(a + static_cast(INT32_C(5))) == 0U) && (*(b + static_cast(INT32_C(5))) == 0U) - && (*(a + static_cast(INT32_C(4))) == 0U) && (*(b + static_cast(INT32_C(4))) == 0U)) + if( (*detail::advance_and_point(a, static_cast(INT32_C(7))) == 0U) && (*detail::advance_and_point(b, static_cast(INT32_C(7))) == 0U) + && (*detail::advance_and_point(a, static_cast(INT32_C(6))) == 0U) && (*detail::advance_and_point(b, static_cast(INT32_C(6))) == 0U) + && (*detail::advance_and_point(a, static_cast(INT32_C(5))) == 0U) && (*detail::advance_and_point(b, static_cast(INT32_C(5))) == 0U) + && (*detail::advance_and_point(a, static_cast(INT32_C(4))) == 0U) && (*detail::advance_and_point(b, static_cast(INT32_C(4))) == 0U)) { rd1 = static_cast ( @@ -3305,23 +3385,23 @@ } else { - const local_double_limb_type a4b0 = *(a + static_cast(INT32_C(4))) * static_cast(*(b + static_cast(INT32_C(0)))); - const local_double_limb_type a0b4 = *(a + static_cast(INT32_C(0))) * static_cast(*(b + static_cast(INT32_C(4)))); + const local_double_limb_type a4b0 = *detail::advance_and_point(a, static_cast(INT32_C(4))) * static_cast(*detail::advance_and_point(b, static_cast(INT32_C(0)))); + const local_double_limb_type a0b4 = *detail::advance_and_point(a, static_cast(INT32_C(0))) * static_cast(*detail::advance_and_point(b, static_cast(INT32_C(4)))); - const local_double_limb_type a5b0 = *(a + static_cast(INT32_C(5))) * static_cast(*(b + static_cast(INT32_C(0)))); - const local_double_limb_type a4b1 = *(a + static_cast(INT32_C(4))) * static_cast(*(b + static_cast(INT32_C(1)))); + const local_double_limb_type a5b0 = *detail::advance_and_point(a, static_cast(INT32_C(5))) * static_cast(*detail::advance_and_point(b, static_cast(INT32_C(0)))); + const local_double_limb_type a4b1 = *detail::advance_and_point(a, static_cast(INT32_C(4))) * static_cast(*detail::advance_and_point(b, static_cast(INT32_C(1)))); - const local_double_limb_type a1b4 = *(a + static_cast(INT32_C(1))) * static_cast(*(b + static_cast(INT32_C(4)))); - const local_double_limb_type a0b5 = *(a + static_cast(INT32_C(0))) * static_cast(*(b + static_cast(INT32_C(5)))); + const local_double_limb_type a1b4 = *detail::advance_and_point(a, static_cast(INT32_C(1))) * static_cast(*detail::advance_and_point(b, static_cast(INT32_C(4)))); + const local_double_limb_type a0b5 = *detail::advance_and_point(a, static_cast(INT32_C(0))) * static_cast(*detail::advance_and_point(b, static_cast(INT32_C(5)))); - const local_double_limb_type a6b0 = *(a + static_cast(INT32_C(6))) * static_cast(*(b + static_cast(INT32_C(0)))); - const local_double_limb_type a5b1 = *(a + static_cast(INT32_C(5))) * static_cast(*(b + static_cast(INT32_C(1)))); + const local_double_limb_type a6b0 = *detail::advance_and_point(a, static_cast(INT32_C(6))) * static_cast(*detail::advance_and_point(b, static_cast(INT32_C(0)))); + const local_double_limb_type a5b1 = *detail::advance_and_point(a, static_cast(INT32_C(5))) * static_cast(*detail::advance_and_point(b, static_cast(INT32_C(1)))); - const local_double_limb_type a4b2 = *(a + static_cast(INT32_C(4))) * static_cast(*(b + static_cast(INT32_C(2)))); - const local_double_limb_type a2b4 = *(a + static_cast(INT32_C(2))) * static_cast(*(b + static_cast(INT32_C(4)))); + const local_double_limb_type a4b2 = *detail::advance_and_point(a, static_cast(INT32_C(4))) * static_cast(*detail::advance_and_point(b, static_cast(INT32_C(2)))); + const local_double_limb_type a2b4 = *detail::advance_and_point(a, static_cast(INT32_C(2))) * static_cast(*detail::advance_and_point(b, static_cast(INT32_C(4)))); - const local_double_limb_type a1b5 = *(a + static_cast(INT32_C(1))) * static_cast(*(b + static_cast(INT32_C(5)))); - const local_double_limb_type a0b6 = *(a + static_cast(INT32_C(0))) * static_cast(*(b + static_cast(INT32_C(6)))); + const local_double_limb_type a1b5 = *detail::advance_and_point(a, static_cast(INT32_C(1))) * static_cast(*detail::advance_and_point(b, static_cast(INT32_C(5)))); + const local_double_limb_type a0b6 = *detail::advance_and_point(a, static_cast(INT32_C(0))) * static_cast(*detail::advance_and_point(b, static_cast(INT32_C(6)))); rd1 = static_cast ( @@ -3410,14 +3490,14 @@ = static_cast ( detail::make_hi(rd6) - + static_cast (*(a + static_cast(INT32_C(7))) * static_cast(*(b + static_cast(INT32_C(0))))) - + static_cast (*(a + static_cast(INT32_C(6))) * static_cast(*(b + static_cast(INT32_C(1))))) - + static_cast (*(a + static_cast(INT32_C(5))) * static_cast(*(b + static_cast(INT32_C(2))))) - + static_cast (*(a + static_cast(INT32_C(4))) * static_cast(*(b + static_cast(INT32_C(3))))) - + static_cast (*(a + static_cast(INT32_C(3))) * static_cast(*(b + static_cast(INT32_C(4))))) - + static_cast (*(a + static_cast(INT32_C(2))) * static_cast(*(b + static_cast(INT32_C(5))))) - + static_cast (*(a + static_cast(INT32_C(1))) * static_cast(*(b + static_cast(INT32_C(6))))) - + static_cast (*(a + static_cast(INT32_C(0))) * static_cast(*(b + static_cast(INT32_C(7))))) + + static_cast (*detail::advance_and_point(a, static_cast(INT32_C(7))) * static_cast(*detail::advance_and_point(b, static_cast(INT32_C(0))))) + + static_cast (*detail::advance_and_point(a, static_cast(INT32_C(6))) * static_cast(*detail::advance_and_point(b, static_cast(INT32_C(1))))) + + static_cast (*detail::advance_and_point(a, static_cast(INT32_C(5))) * static_cast(*detail::advance_and_point(b, static_cast(INT32_C(2))))) + + static_cast (*detail::advance_and_point(a, static_cast(INT32_C(4))) * static_cast(*detail::advance_and_point(b, static_cast(INT32_C(3))))) + + static_cast (*detail::advance_and_point(a, static_cast(INT32_C(3))) * static_cast(*detail::advance_and_point(b, static_cast(INT32_C(4))))) + + static_cast (*detail::advance_and_point(a, static_cast(INT32_C(2))) * static_cast(*detail::advance_and_point(b, static_cast(INT32_C(5))))) + + static_cast (*detail::advance_and_point(a, static_cast(INT32_C(1))) * static_cast(*detail::advance_and_point(b, static_cast(INT32_C(6))))) + + static_cast (*detail::advance_and_point(a, static_cast(INT32_C(0))) * static_cast(*detail::advance_and_point(b, static_cast(INT32_C(7))))) + detail::make_hi(a6b0) + detail::make_hi(a5b1) + detail::make_hi(a4b2) @@ -3465,34 +3545,30 @@ using local_double_limb_type = typename detail::uint_type_helper(std::numeric_limits::digits * 2)>::exact_unsigned_type; - using result_difference_type = typename std::iterator_traits::difference_type; - using left_difference_type = typename std::iterator_traits::difference_type; - using right_difference_type = typename std::iterator_traits::difference_type; - std::fill_n(r, count, static_cast(UINT8_C(0))); for(auto i = static_cast(UINT8_C(0)); i < count; ++i) { - if(*(a + static_cast(i)) != static_cast(UINT8_C(0))) + if(*a != static_cast(UINT8_C(0))) { auto carry = static_cast(UINT8_C(0)); - for(auto j = static_cast(UINT8_C(0)); j < static_cast(count - i); ++j) - { - const auto i_plus_j = - static_cast - ( - static_cast(i) - + static_cast(j) - ); + auto r_i_plus_j = detail::advance_and_point(r, i); // NOLINT(llvm-qualified-auto,readability-qualified-auto) + auto bj = b; // NOLINT(llvm-qualified-auto,readability-qualified-auto) - carry = static_cast(carry + static_cast(static_cast(*(a + static_cast(i))) * *(b + static_cast(j)))); - carry = static_cast(carry + *(r + i_plus_j)); + for(auto j = static_cast(UINT8_C(0)); + j < static_cast(count - i); + ++j) + { + carry = static_cast(carry + static_cast(static_cast(*a) * *bj++)); + carry = static_cast(carry + *r_i_plus_j); - *(r + i_plus_j) = static_cast(carry); - carry = detail::make_hi(carry); + *r_i_plus_j++ = static_cast(carry); + carry = detail::make_hi(carry); } } + + ++a; } } @@ -3516,45 +3592,38 @@ using local_double_limb_type = typename detail::uint_type_helper(std::numeric_limits::digits * 2)>::exact_unsigned_type; - using result_difference_type = typename std::iterator_traits::difference_type; - using left_difference_type = typename std::iterator_traits::difference_type; - using right_difference_type = typename std::iterator_traits::difference_type; - std::fill_n(r, static_cast(count * 2U), static_cast(UINT8_C(0))); for(auto i = static_cast(UINT8_C(0)); i < count; ++i) { - if(*(a + static_cast(i)) != static_cast(UINT8_C(0))) + if(*a != static_cast(UINT8_C(0))) { - auto j = static_cast(UINT8_C(0)); - auto carry = static_cast(UINT8_C(0)); - for( ; j < count; ++j) - { - const auto i_plus_j = - static_cast - ( - static_cast(i) + static_cast(j) - ); - - carry = static_cast(carry + static_cast(static_cast(*(a + static_cast(i))) * *(b + static_cast(j)))); - carry = static_cast(carry + *(r + i_plus_j)); - - *(r + i_plus_j) = static_cast(carry); - carry = detail::make_hi(carry); - } + auto r_i_plus_j = detail::advance_and_point(r, i); // NOLINT(llvm-qualified-auto,readability-qualified-auto) + auto bj = b; // NOLINT(llvm-qualified-auto,readability-qualified-auto) + for(auto j = static_cast(UINT8_C(0)); j < count; ++j) { - const auto i_plus_count = - static_cast + carry = + static_cast ( - static_cast(i) + static_cast(count) + static_cast + ( + carry + + static_cast(static_cast(*a) * *bj++) + ) + + *r_i_plus_j ); - *(r + i_plus_count) = static_cast(carry); + *r_i_plus_j++ = static_cast(carry); + carry = detail::make_hi(carry); } + + *r_i_plus_j = static_cast(carry); } + + ++a; } } @@ -3577,23 +3646,25 @@ using local_double_limb_type = typename detail::uint_type_helper(std::numeric_limits::digits * 2)>::exact_unsigned_type; - using result_difference_type = typename std::iterator_traits::difference_type; - using left_difference_type = typename std::iterator_traits::difference_type; - auto carry = static_cast(UINT8_C(0)); if(b == static_cast(UINT8_C(0))) { - std::fill(r, r + count, static_cast(UINT8_C(0))); + std::fill(r, detail::advance_and_point(r, count), static_cast(UINT8_C(0))); } else { for(auto i = static_cast(UINT8_C(0)) ; i < count; ++i) { - carry = static_cast(carry + static_cast(static_cast(*(a + static_cast(i))) * b)); + carry = + static_cast + ( + carry + + static_cast(static_cast(*a++) * b) + ); - *(r + static_cast(i)) = static_cast(carry); - carry = detail::make_hi(carry); + *r++ = static_cast(carry); + carry = detail::make_hi(carry); } } @@ -3611,19 +3682,21 @@ using local_double_limb_type = typename detail::uint_type_helper(std::numeric_limits::digits * 2)>::exact_unsigned_type; - using left_difference_type = typename std::iterator_traits::difference_type; - auto i = static_cast(UINT8_C(0)); - local_limb_type carry_out = carry; + auto carry_out = carry; while((i < n) && (carry_out != static_cast(UINT8_C(0)))) // NOLINT(altera-id-dependent-backward-branch) { - const local_double_limb_type uv_as_ularge = static_cast(*(t + static_cast(i))) + carry_out; + const auto uv_as_ularge = + static_cast + ( + static_cast(*t) + carry_out + ); carry_out = detail::make_hi(uv_as_ularge); - *(t + static_cast(i)) = static_cast(uv_as_ularge); + *t++ = static_cast(uv_as_ularge); ++i; } @@ -3640,24 +3713,25 @@ using local_double_limb_type = typename detail::uint_type_helper(std::numeric_limits::digits * 2)>::exact_unsigned_type; - using left_difference_type = typename std::iterator_traits::difference_type; - auto i = static_cast(UINT8_C(0)); - bool has_borrow_out = has_borrow; + auto has_borrow_out = has_borrow; while((i < n) && has_borrow_out) // NOLINT(altera-id-dependent-backward-branch) { - auto uv_as_ularge = static_cast(*(t + static_cast(i))); + auto uv_as_ularge = static_cast(*t); if(has_borrow_out) { --uv_as_ularge; } - has_borrow_out = (detail::make_hi(uv_as_ularge) != static_cast(UINT8_C(0))); + has_borrow_out = + ( + detail::make_hi(uv_as_ularge) != static_cast(UINT8_C(0)) + ); - *(t + static_cast(i)) = static_cast(uv_as_ularge); + *t++ = static_cast(uv_as_ularge); ++i; } @@ -3732,21 +3806,21 @@ const auto nh = static_cast(n / 2U); - const InputIteratorLeft a0 = a + static_cast(0); - const InputIteratorLeft a1 = a + static_cast(nh); + const InputIteratorLeft a0 = detail::advance_and_point(a, static_cast(0)); + const InputIteratorLeft a1 = detail::advance_and_point(a, static_cast(nh)); - const InputIteratorRight b0 = b + static_cast(0); - const InputIteratorRight b1 = b + static_cast(nh); + const InputIteratorRight b0 = detail::advance_and_point(b, static_cast(0)); + const InputIteratorRight b1 = detail::advance_and_point(b, static_cast(nh)); - ResultIterator r0 = r + static_cast(0); - ResultIterator r1 = r + static_cast(nh); - ResultIterator r2 = r + static_cast(n); - ResultIterator r3 = r + static_cast(static_cast(n) + static_cast(nh)); + ResultIterator r0 = detail::advance_and_point(r, static_cast(0)); + ResultIterator r1 = detail::advance_and_point(r, static_cast(nh)); + ResultIterator r2 = detail::advance_and_point(r, static_cast(n)); + ResultIterator r3 = detail::advance_and_point(r, static_cast(static_cast(n) + static_cast(nh))); - InputIteratorTemp t0 = t + static_cast(0); - InputIteratorTemp t1 = t + static_cast(nh); - InputIteratorTemp t2 = t + static_cast(n); - InputIteratorTemp t4 = t + static_cast(static_cast(n) + static_cast(n)); + InputIteratorTemp t0 = detail::advance_and_point(t, static_cast(0)); + InputIteratorTemp t1 = detail::advance_and_point(t, static_cast(nh)); + InputIteratorTemp t2 = detail::advance_and_point(t, static_cast(n)); + InputIteratorTemp t4 = detail::advance_and_point(t, static_cast(static_cast(n) + static_cast(n))); // Step 1 // a1*b1 -> r2 @@ -3754,7 +3828,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 + static_cast(static_cast(n) * static_cast(2U)), t0); + std::copy(r0, detail::advance_and_point(r0, static_cast(static_cast(n) * static_cast(2U))), t0); local_limb_type carry; @@ -3830,12 +3904,17 @@ using local_uint_index_type = unsigned_fast_type; - auto u_offset = static_cast(UINT8_C(0)); - auto v_offset = static_cast(UINT8_C(0)); + const auto u_offset = + static_cast + ( + std::distance(values.crbegin(), std::find_if(values.crbegin(), values.crend(), [](const limb_type& elem) { return (elem != static_cast(UINT8_C(0))); })) + ); - // Compute the offsets for u and v. - for(auto i = static_cast(UINT8_C(0)); (i < static_cast(number_of_limbs)) && (*( values.cbegin() + static_cast(static_cast(number_of_limbs - 1U) - i)) == static_cast(UINT8_C(0))); ++i) { ++u_offset; } // NOLINT(altera-id-dependent-backward-branch) - for(auto i = static_cast(UINT8_C(0)); (i < static_cast(number_of_limbs)) && (*(other.values.cbegin() + static_cast(static_cast(number_of_limbs - 1U) - i)) == static_cast(UINT8_C(0))); ++i) { ++v_offset; } // NOLINT(altera-id-dependent-backward-branch) + const auto v_offset = + static_cast + ( + std::distance(other.values.crbegin(), std::find_if(other.values.crbegin(), other.values.crend(), [](const limb_type& elem) { return (elem != static_cast(UINT8_C(0))); })) + ); if(v_offset == static_cast(number_of_limbs)) { @@ -3845,7 +3924,7 @@ if(remainder != nullptr) // LCOV_EXCL_LINE { - remainder->values.fill(static_cast(UINT8_C(0))); + std::fill(remainder->values.begin(), remainder->values.end(), static_cast(UINT8_C(0))); // LCOV_EXCL_LINE } } else if(u_offset == static_cast(number_of_limbs)) @@ -3919,7 +3998,7 @@ static_cast ( static_cast(static_cast(1U) << static_cast(std::numeric_limits::digits)) - / static_cast(static_cast(*(other.values.cbegin() + static_cast(static_cast(number_of_limbs - 1U) - v_offset))) + static_cast(1U)) + / static_cast(static_cast(*detail::advance_and_point(other.values.cbegin(), static_cast(static_cast(number_of_limbs - 1U) - v_offset))) + static_cast(1U)) ); // Step D1(b), normalize u -> u * d = uu. @@ -3934,8 +4013,15 @@ std::allocator, AllocatorType>>::template rebind_alloc>>; - uu_array_type uu; - representation_type vv; + uu_array_type uu; + + representation_type + vv + { + static_cast(number_of_limbs), + static_cast(UINT8_C(0)), + typename representation_type::allocator_type() + }; if(d > static_cast(UINT8_C(1))) { @@ -3948,8 +4034,8 @@ *(uu.begin() + num_limbs_minus_u_ofs) = eval_multiply_1d ( - uu.data(), - values.data(), + uu.begin(), + values.cbegin(), d, static_cast(num_limbs_minus_u_ofs) ); @@ -3958,8 +4044,8 @@ ( eval_multiply_1d ( - vv.data(), - other.values.data(), + vv.begin(), + other.values.cbegin(), d, static_cast(number_of_limbs - v_offset) ) @@ -3981,6 +4067,13 @@ const auto m = static_cast(static_cast(number_of_limbs - u_offset) - n); const auto vj0 = static_cast(static_cast(number_of_limbs - 1U) - v_offset); + auto vv_at_vj0_it = detail::advance_and_point(vv.cbegin(), static_cast(vj0)); // NOLINT(llvm-qualified-auto,readability-qualified-auto) + + const auto vv_at_vj0 = *vv_at_vj0_it--; + const auto vv_at_vj0_minus_one = *vv_at_vj0_it; + + auto values_at_m_minus_j_it = detail::advance_and_point(values.begin(), static_cast(m)); // NOLINT(llvm-qualified-auto,readability-qualified-auto) + for(auto j = static_cast(UINT8_C(0)); j <= m; ++j) // NOLINT(altera-id-dependent-backward-branch) { // Step D3 [Calculate q_hat]. @@ -3995,9 +4088,9 @@ auto q_hat = static_cast ( - (*(uu.cbegin() + static_cast(uj)) == *(vv.cbegin() + static_cast(vj0))) + (*(uu.cbegin() + static_cast(uj)) == vv_at_vj0) ? (std::numeric_limits::max)() - : static_cast(u_j_j1 / *(vv.cbegin() + static_cast(vj0))) + : static_cast(u_j_j1 / vv_at_vj0) ); // Decrease q_hat if necessary. @@ -4005,11 +4098,13 @@ // expression [(u[uj] * b + u[uj - 1] - q_hat * v[vj0 - 1]) * b] // exceeds the range of uintwide_t. - for(auto t = static_cast(u_j_j1 - static_cast(q_hat * static_cast(*(vv.cbegin() + static_cast(vj0))))); ; --q_hat, t = static_cast(t + *(vv.cbegin() + static_cast(vj0)))) + for(auto t = static_cast(u_j_j1 - static_cast(q_hat * static_cast(vv_at_vj0))); + ; + --q_hat, t = static_cast(t + vv_at_vj0)) { if( (detail::make_hi(t) != static_cast(UINT8_C(0))) - || ( static_cast(static_cast(*(vv.cbegin() + static_cast(vj0 - 1U))) * q_hat) - <= static_cast(static_cast(t << static_cast(std::numeric_limits::digits)) + *(uu.cbegin() + static_cast(uj - 2U))))) + || ( static_cast(static_cast(vv_at_vj0_minus_one) * q_hat) + <= static_cast(static_cast(t << static_cast(std::numeric_limits::digits)) + *detail::advance_and_point(uu.cbegin(), static_cast(uj - 2U))))) { break; } @@ -4021,12 +4116,12 @@ // Set nv = q_hat * (v[1, ... n]). uu_array_type nv; - *(nv.begin() + static_cast(n)) = eval_multiply_1d(nv.data(), vv.data(), q_hat, n); + *(nv.begin() + static_cast(n)) = eval_multiply_1d(nv.begin(), vv.cbegin(), q_hat, n); const bool has_borrow = - eval_subtract_n(uu.data() + static_cast(static_cast(uj - n)), - uu.data() + static_cast(static_cast(uj - n)), - nv.data(), + eval_subtract_n(detail::advance_and_point(uu.begin(), static_cast(static_cast(uj - n))), + detail::advance_and_point(uu.cbegin(), static_cast(static_cast(uj - n))), + nv.cbegin(), n + 1U); @@ -4043,14 +4138,22 @@ // Add v[1, ... n] back to u[j, ... j + n], // and decrease the result by 1. - static_cast(eval_add_n(uu.data() + static_cast(static_cast(uj - n)), - uu.data() + static_cast(static_cast(uj - n)), - vv.data(), - n)); + static_cast + ( + eval_add_n(uu.begin() + static_cast(static_cast(uj - n)), + detail::advance_and_point(uu.cbegin(), static_cast(static_cast(uj - n))), + vv.cbegin(), + n) + ); } // Get the result data. - *(values.begin() + static_cast(m - j)) = static_cast(q_hat); + *values_at_m_minus_j_it = static_cast(q_hat); + + if(j < m) + { + --values_at_m_minus_j_it; + } } // Clear the data elements that have not @@ -4062,35 +4165,48 @@ static_cast(m) + static_cast(UINT8_C(1)) ); - std::fill(values.begin() + m_plus_one, values.end(), static_cast(UINT8_C(0))); + std::fill(detail::advance_and_point(values.begin(), m_plus_one), values.end(), static_cast(UINT8_C(0))); } if(remainder != nullptr) { + auto rl_it_fwd = // NOLINT(llvm-qualified-auto,readability-qualified-auto) + detail::advance_and_point(remainder->values.begin(), static_cast(n)); + if(d == static_cast(UINT8_C(1))) { std::copy(uu.cbegin(), - uu.cbegin() + static_cast(static_cast(number_of_limbs - v_offset)), + detail::advance_and_point(uu.cbegin(), static_cast(static_cast(number_of_limbs - v_offset))), remainder->values.begin()); } else { auto previous_u = static_cast(UINT8_C(0)); - for(auto rl = static_cast(n - 1U), ul = static_cast(number_of_limbs - (v_offset + 1U)); rl >= 0; --rl, --ul) // NOLINT(altera-id-dependent-backward-branch) + auto rl_it_rev = static_cast(rl_it_fwd); + + auto ul = + static_cast + ( + static_cast + ( + number_of_limbs + - static_cast(v_offset + static_cast(UINT8_C(1))) + ) + ); + + for( ; rl_it_rev != remainder->values.rend(); ++rl_it_rev, --ul) // NOLINT(altera-id-dependent-backward-branch) { const auto t = static_cast( *(uu.cbegin() + static_cast(ul)) + static_cast(static_cast(previous_u) << static_cast(std::numeric_limits::digits))); - *(remainder->values.begin() + static_cast(rl)) = static_cast(static_cast(t / d)); - previous_u = static_cast(static_cast(t - static_cast(static_cast(d) * *(remainder->values.cbegin() + static_cast(rl))))); + *rl_it_rev = static_cast(static_cast(t / d)); + previous_u = static_cast(static_cast(t - static_cast(static_cast(d) * *rl_it_rev))); } } - std::fill(remainder->values.begin() + static_cast(n), - remainder->values.end(), - static_cast(UINT8_C(0))); + std::fill(rl_it_fwd, remainder->values.end(), static_cast(UINT8_C(0))); } } } @@ -4133,13 +4249,13 @@ const auto offset = static_cast(static_cast(n) / static_cast(std::numeric_limits::digits)); const auto left_shift_amount = static_cast(static_cast(n) % static_cast(std::numeric_limits::digits)); - if(offset > 0U) + if(offset > static_cast(UINT8_C(0))) { - std::copy_backward(values.data(), - values.data() + static_cast(number_of_limbs - offset), - values.data() + static_cast(number_of_limbs)); + std::copy_backward(values.cbegin(), + detail::advance_and_point(values.cbegin(), static_cast(number_of_limbs - offset)), + detail::advance_and_point(values.begin(), static_cast(number_of_limbs))); - std::fill(values.begin(), values.begin() + static_cast(offset), static_cast(UINT8_C(0))); + std::fill(values.begin(), detail::advance_and_point(values.begin(), static_cast(offset)), static_cast(UINT8_C(0))); } using local_integral_type = unsigned_fast_type; @@ -4148,15 +4264,24 @@ { auto part_from_previous_value = static_cast(UINT8_C(0)); - for(unsigned_fast_type i = offset; i < static_cast(number_of_limbs); ++i) // NOLINT(altera-id-dependent-backward-branch) + auto ai = detail::advance_and_point(values.begin(), offset); // NOLINT(llvm-qualified-auto,readability-qualified-auto) + + while(ai != values.end()) // NOLINT(altera-id-dependent-backward-branch) { - const limb_type t = *(values.cbegin() + static_cast(i)); + const limb_type t = *ai; - *(values.begin() + static_cast(i)) = - static_cast(static_cast(t << static_cast(left_shift_amount)) | part_from_previous_value); + *ai++ = + static_cast + ( + static_cast(t << static_cast(left_shift_amount)) + | part_from_previous_value + ); part_from_previous_value = - static_cast(t >> static_cast(static_cast(std::numeric_limits::digits - left_shift_amount))); + static_cast + ( + t >> static_cast(static_cast(std::numeric_limits::digits - left_shift_amount)) + ); } } } @@ -4167,13 +4292,13 @@ const auto offset = static_cast(static_cast(n) / static_cast(std::numeric_limits::digits)); const auto right_shift_amount = static_cast(static_cast(n) % static_cast(std::numeric_limits::digits)); - if(offset > 0U) + if(offset > static_cast(UINT8_C(0))) { - std::copy(values.begin() + static_cast(offset), - values.begin() + static_cast(number_of_limbs), + std::copy(detail::advance_and_point(values.cbegin(), static_cast(offset)), + detail::advance_and_point(values.cbegin(), static_cast(number_of_limbs)), values.begin()); - std::fill(values.end() - static_cast(offset), + std::fill(detail::advance_and_point(values.begin(), static_cast(static_cast(number_of_limbs) - static_cast(offset))), values.end(), right_shift_fill_value()); } @@ -4190,11 +4315,24 @@ : static_cast((std::numeric_limits::max)() << static_cast(static_cast(std::numeric_limits::digits) - right_shift_amount)) ); - for(auto i = static_cast((number_of_limbs - 1U) - offset); i >= static_cast(0); --i) // NOLINT(altera-id-dependent-backward-branch) + auto r_ai = + static_cast + ( + detail::advance_and_point + ( + values.begin(), + static_cast + ( + static_cast(number_of_limbs) - offset + ) + ) + ); + + while(r_ai != values.rend()) // NOLINT(altera-id-dependent-backward-branch) { - const limb_type t = *(values.cbegin() + static_cast(i)); + const limb_type t = *r_ai; - *(values.begin() + static_cast(i)) = static_cast(static_cast(t >> static_cast(right_shift_amount)) | part_from_previous_value); + *r_ai++ = static_cast(static_cast(t >> static_cast(right_shift_amount)) | part_from_previous_value); part_from_previous_value = static_cast(t << static_cast(static_cast(std::numeric_limits::digits - right_shift_amount))); } @@ -4332,9 +4470,9 @@ WIDE_INTEGER_CONSTEXPR auto bitwise_not() -> void { - for(auto i = static_cast(UINT8_C(0)); i < number_of_limbs; ++i) + for(auto it = values.begin(); it != values.end(); ++it) // NOLINT(llvm-qualified-auto,readability-qualified-auto,altera-id-dependent-backward-branch) { - *(values.begin() + static_cast(i)) = static_cast(~(*(values.cbegin() + static_cast(i)))); + *it = static_cast(~(*it)); } } @@ -5517,13 +5655,13 @@ if(u == v) { // This handles cases having (u = v) and also (u = v = 0). - result = u; + result = u; // LCOV_EXCL_LINE } if((static_cast(v) == static_cast(UINT8_C(0))) && (v == 0U)) { // This handles cases having (v = 0) with (u != 0). - result = u; + result = u; // LCOV_EXCL_LINE } if((static_cast(u) == static_cast(UINT8_C(0))) && (u == 0U)) @@ -5565,8 +5703,8 @@ { if(v <= (std::numeric_limits::max)()) { - const auto vs = *(v.crepresentation().cbegin() + static_cast(UINT8_C(0))); - const auto us = *(u.crepresentation().cbegin() + static_cast(UINT8_C(0))); + const auto vs = *v.crepresentation().cbegin(); + const auto us = *u.crepresentation().cbegin(); u = detail::integer_gcd_reduce_short(vs, us); } @@ -5576,7 +5714,7 @@ static_cast ( (v.crepresentation().size() >= static_cast(2U)) - ? static_cast(*(v.crepresentation().cbegin() + static_cast(UINT8_C(1)))) + ? static_cast(*detail::advance_and_point(v.crepresentation().cbegin(), static_cast(UINT8_C(1)))) : static_cast(UINT8_C(0)) ); @@ -5584,12 +5722,12 @@ static_cast ( (u.crepresentation().size() >= static_cast(2U)) - ? static_cast(*(u.crepresentation().cbegin() + static_cast(UINT8_C(1)))) + ? static_cast(*detail::advance_and_point(u.crepresentation().cbegin(), static_cast(UINT8_C(1)))) : static_cast(UINT8_C(0)) ); - const local_ularge_type v_large = detail::make_large(*(v.crepresentation().cbegin() + static_cast(UINT8_C(0))), my_v_hi); - const local_ularge_type u_large = detail::make_large(*(u.crepresentation().cbegin() + static_cast(UINT8_C(0))), my_u_hi); + const local_ularge_type v_large = detail::make_large(*v.crepresentation().cbegin(), my_v_hi); + const local_ularge_type u_large = detail::make_large(*u.crepresentation().cbegin(), my_u_hi); u = detail::integer_gcd_reduce_large(v_large, u_large); } @@ -6436,19 +6574,21 @@ if(msv_first) { std::copy(first, - first + copy_len, - local_result_iterator_type(val.representation().begin() + copy_len)); + detail::advance_and_point(first, copy_len), + local_result_iterator_type(detail::advance_and_point(val.representation().begin(), copy_len))); } else { using local_input_reverse_iterator_type = std::reverse_iterator; - std::copy(local_input_reverse_iterator_type(last), - local_input_reverse_iterator_type(last) + static_cast(copy_len), - local_result_iterator_type(val.representation().begin() + copy_len)); + using local_difference_type = typename local_result_iterator_type::difference_type; + + std::copy(local_input_reverse_iterator_type(detail::advance_and_point(first, static_cast(input_distance))), + local_input_reverse_iterator_type(detail::advance_and_point(first, static_cast(static_cast(input_distance) - static_cast(copy_len)))), + local_result_iterator_type (detail::advance_and_point(val.representation().begin(), copy_len))); } - std::fill(val.representation().begin() + copy_len, + std::fill(detail::advance_and_point(val.representation().begin(), copy_len), val.representation().end(), static_cast(UINT8_C(0))); } @@ -6484,7 +6624,7 @@ ) ); - auto it_result = local_result_iterator_type(val.representation().begin() + result_distance); + auto it_result = local_result_iterator_type(detail::advance_and_point(val.representation().begin(), result_distance)); if(msv_first) { @@ -6566,7 +6706,7 @@ ) ); - auto it_result = local_result_iterator_type(val.representation().begin() + result_distance); + auto it_result = local_result_iterator_type(detail::advance_and_point(val.representation().begin(), result_distance)); if(msv_first) { @@ -6648,14 +6788,14 @@ using local_input_const_reverse_iterator_type = typename local_unsigned_wide_integer_type::representation_type::const_reverse_iterator; - out = std::copy(local_input_const_reverse_iterator_type(val.representation().cbegin() + input_distance), + out = std::copy(local_input_const_reverse_iterator_type(detail::advance_and_point(val.representation().cbegin(), input_distance)), val.representation().crend(), out); } else { out = std::copy(val.representation().cbegin(), - val.representation().cbegin() + input_distance, + detail::advance_and_point(val.representation().cbegin(), input_distance), out); } } @@ -6665,7 +6805,7 @@ { using local_input_reverse_iterator_type = std::reverse_iterator; - out = detail::import_export_helper(local_input_reverse_iterator_type(val_unsigned.crepresentation().cbegin() + input_distance), out, msb_plus_one, chunk_size_in, chunk_size_out) + out = detail::import_export_helper(local_input_reverse_iterator_type(detail::advance_and_point(val_unsigned.crepresentation().cbegin(), input_distance)), out, msb_plus_one, chunk_size_in, chunk_size_out) + static_cast(UINT8_C(1)); } else @@ -6687,8 +6827,8 @@ using local_input_reverse_iterator_type = typename local_unsigned_wide_integer_type::representation_type::const_reverse_iterator; using local_result_reverse_iterator_type = std::reverse_iterator; - static_cast(detail::import_export_helper(local_input_reverse_iterator_type (val_unsigned.crepresentation().cbegin() + input_distance), - local_result_reverse_iterator_type(out + output_distance), // LCOV_EXCL_LINE + static_cast(detail::import_export_helper(local_input_reverse_iterator_type (detail::advance_and_point(val_unsigned.crepresentation().cbegin(), input_distance)), + local_result_reverse_iterator_type(detail::advance_and_point(out, output_distance)), // LCOV_EXCL_LINE msb_plus_one, chunk_size_in, chunk_size_out)); @@ -6761,7 +6901,7 @@ out = detail::import_export_helper ( - local_input_reverse_iterator_type(val_unsigned.crepresentation().cbegin() + input_distance), + local_input_reverse_iterator_type(detail::advance_and_point(val_unsigned.crepresentation().cbegin(), input_distance)), out, static_cast(msb_plus_one), chunk_size_in, @@ -6793,8 +6933,8 @@ ( detail::import_export_helper ( - local_input_reverse_iterator_type (val_unsigned.crepresentation().cbegin() + input_distance), - local_result_reverse_iterator_type(out + output_distance), + local_input_reverse_iterator_type (detail::advance_and_point(val_unsigned.crepresentation().cbegin(), input_distance)), + local_result_reverse_iterator_type(detail::advance_and_point(out, output_distance)), static_cast(msb_plus_one), chunk_size_in, chunk_size_out diff --git a/test/test.cpp b/test/test.cpp index 6c9a64ca..03004792 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -91,6 +91,10 @@ #if defined(__SANITIZE_THREAD__) || defined(WIDE_INTEGER_HAS_COVERAGE) #define UINTWIDE_T_REDUCE_TEST_DEPTH #endif +#elif defined(_MSC_VER) + #if defined(_DEBUG) + #define UINTWIDE_T_REDUCE_TEST_DEPTH + #endif #endif namespace local { @@ -144,7 +148,7 @@ auto test_uintwide_t_small_bits() -> bool local_uint24_t c = a * b; - result_is_ok = ((c == UINT32_C(0xF368039C)) && result_is_ok); // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) + result_is_ok = ((c == UINT32_C(0x0068039C)) && result_is_ok); // NOLINT(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) } { diff --git a/test/test_uintwide_t_edge_cases.cpp b/test/test_uintwide_t_edge_cases.cpp index bb2582c1..e63e6ff2 100644 --- a/test/test_uintwide_t_edge_cases.cpp +++ b/test/test_uintwide_t_edge_cases.cpp @@ -73,11 +73,21 @@ namespace test_uintwide_t_edge { namespace local_edge_cases { + #if !(defined(_MSC_VER) && defined(_DEBUG)) constexpr auto local_digits2 = static_cast(UINT32_C(16384)); + #endif constexpr auto local_digits2_small = static_cast(UINT32_C( 256)); } // namespace local_edge_cases +#if (defined(_MSC_VER) && defined(_DEBUG)) +constexpr auto loop_count_lo = static_cast(UINT32_C(4)); +constexpr auto loop_count_hi = static_cast(UINT32_C(8)); +#else +constexpr auto loop_count_lo = static_cast(UINT32_C(64)); +constexpr auto loop_count_hi = static_cast(UINT32_C(256)); +#endif + // Forward declaration template @@ -99,6 +109,7 @@ using local_uintwide_t_small_signed_type = ::math::wide_integer::uintwide_t; #endif +#if !(defined(_MSC_VER) && defined(_DEBUG)) using local_uint_backend_type = boost::multiprecision::uintwide_t_backend; +#endif enum class local_base { @@ -234,6 +246,7 @@ auto generate_wide_integer_value(bool is_positive = true, return local_integral_type(str_x.c_str()); } +#if !(defined(_MSC_VER) && defined(_DEBUG)) auto test_various_edge_operations() -> bool { const auto u_max_local = (std::numeric_limits::max)(); @@ -335,13 +348,13 @@ auto test_various_edge_operations() -> bool local_derived_uint_type dt(static_cast(INT8_C(-3))); - dt.representation().fill(static_cast(UINT8_C(0))); + std::fill(dt.representation().begin(), dt.representation().end(), static_cast(UINT8_C(0))); const auto result_fill_with_zero_is_ok = (dt == 0U); result_is_ok = (result_fill_with_zero_is_ok && result_is_ok); - dt.representation().fill((std::numeric_limits::max)()); + std::fill(dt.representation().begin(), dt.representation().end(), (std::numeric_limits::max)()); const auto result_fill_with_effs_is_ok = (dt == (std::numeric_limits::max)()); @@ -350,6 +363,7 @@ auto test_various_edge_operations() -> bool return result_is_ok; } +#endif auto test_various_ostream_ops() -> bool { @@ -619,8 +633,7 @@ auto test_various_roots_and_pow_etc() -> bool const auto ten_pow_forty = local_uintwide_t_small_unsigned_type("10000000000000000000000000000000000000000"); { - const auto u = ten_pow_forty; - const auto u_root = rootk(u, static_cast(UINT8_C(1))); + const auto u_root = rootk(ten_pow_forty, static_cast(UINT8_C(1))); const auto result_u_root_is_ok = (u_root == ten_pow_forty); @@ -628,13 +641,12 @@ auto test_various_roots_and_pow_etc() -> bool } { - const auto u = ten_pow_forty; - const auto u_root = rootk(u, static_cast(UINT8_C(2))); + const auto u_root = rootk(ten_pow_forty, static_cast(UINT8_C(2))); const auto ten_pow_twenty = local_uintwide_t_small_unsigned_type("100000000000000000000"); const auto result_u_root_is_ok = ( (u_root == ten_pow_twenty) - && (u_root == sqrt(u))); + && (u_root == sqrt(ten_pow_forty))); result_is_ok = (result_u_root_is_ok && result_is_ok); } @@ -667,7 +679,7 @@ auto test_various_roots_and_pow_etc() -> bool } for(auto i = static_cast(UINT32_C(0)); - i < static_cast(UINT32_C(256)); + i < static_cast(loop_count_hi); ++i) { auto b_gen = generate_wide_integer_value(); // NOLINT @@ -719,7 +731,7 @@ auto test_various_roots_and_pow_etc() -> bool } for(auto i = static_cast(UINT32_C(0)); - i < static_cast(UINT32_C(256)); + i < static_cast(loop_count_hi); ++i) { const auto high_bit = @@ -749,7 +761,7 @@ auto test_various_roots_and_pow_etc() -> bool } for(auto i = static_cast(UINT32_C(0)); - i < static_cast(UINT32_C(256)); + i < static_cast(loop_count_hi); ++i) { const auto b_gen = generate_wide_integer_value(); @@ -762,7 +774,7 @@ auto test_various_roots_and_pow_etc() -> bool } for(auto i = static_cast(UINT32_C(0)); - i < static_cast(UINT32_C(256)); + i < static_cast(loop_count_hi); ++i) { constexpr auto digits10_to_get_b = @@ -853,21 +865,26 @@ auto test_various_isolated_edge_cases() -> bool // NOLINT(readability-function-c using local_rep_type = typename local_uintwide_t_small_unsigned_type::representation_type; using local_value_type = typename local_rep_type::value_type; - local_rep_type rep(local_rep_type::static_size(), (std::numeric_limits::max)()); + local_rep_type + rep + ( + local_uintwide_t_small_unsigned_type::number_of_limbs, + (std::numeric_limits::max)(), + typename local_rep_type::allocator_type() + ); const auto rep_as_max_is_ok = (local_uintwide_t_small_unsigned_type(rep) == (std::numeric_limits::max)()); result_is_ok = (rep_as_max_is_ok && result_is_ok); - rep.fill(static_cast(0U)); + std::fill(rep.begin(), rep.end(), static_cast(0U)); - const auto rep_as_zero_is_ok = - (local_uintwide_t_small_unsigned_type(rep) == 0); + const auto rep_as_zero_is_ok = (local_uintwide_t_small_unsigned_type(rep) == 0); result_is_ok = (rep_as_zero_is_ok && result_is_ok); - rep.fill((std::numeric_limits::max)()); + std::fill(rep.begin(), rep.end(), (std::numeric_limits::max)()); const auto rep_as_max2_is_ok = (local_uintwide_t_small_unsigned_type(rep) == (std::numeric_limits::max)()); @@ -878,11 +895,14 @@ auto test_various_isolated_edge_cases() -> bool // NOLINT(readability-function-c local_rep_type ( static_cast(rep.size()), - (std::numeric_limits::max)() + (std::numeric_limits::max)(), + typename local_rep_type::allocator_type() ); const auto rep_as_max3_is_ok = - (local_uintwide_t_small_unsigned_type(rep) == (std::numeric_limits::max)()); + ( + local_uintwide_t_small_unsigned_type(rep) == (std::numeric_limits::max)() + ); result_is_ok = (rep_as_max3_is_ok && result_is_ok); } @@ -924,7 +944,7 @@ auto test_various_isolated_edge_cases() -> bool // NOLINT(readability-function-c } for(auto i = static_cast(UINT32_C(0)); - i < static_cast(UINT32_C(256)); + i < static_cast(loop_count_hi); ++i) { // Verify division of finite, unsigned numerator by zero which returns the maximum of the type. @@ -939,7 +959,7 @@ auto test_various_isolated_edge_cases() -> bool // NOLINT(readability-function-c } for(auto i = static_cast(UINT32_C(0)); - i < static_cast(UINT32_C(256)); + i < static_cast(loop_count_hi); ++i) { // Verify division of finite, signed numerator by zero which returns the maximum of the type. @@ -967,7 +987,7 @@ auto test_various_isolated_edge_cases() -> bool // NOLINT(readability-function-c } for(auto i = static_cast(UINT32_C(0)); - i < static_cast(UINT32_C(256)); + i < static_cast(loop_count_hi); ++i) { // Verify modulus of zero with a finite denominator which returns zero modulus. @@ -1007,7 +1027,7 @@ auto test_various_isolated_edge_cases() -> bool // NOLINT(readability-function-c for(auto i = static_cast(UINT32_C(0)); - i < static_cast(UINT32_C(256)); + i < static_cast(loop_count_hi); ++i) { auto shift_amount = @@ -1043,7 +1063,7 @@ auto test_various_isolated_edge_cases() -> bool // NOLINT(readability-function-c } for(auto i = static_cast(UINT32_C(0)); - i < static_cast(UINT32_C(256)); + i < static_cast(loop_count_hi); ++i) { auto shift_amount = @@ -1092,7 +1112,7 @@ auto test_to_chars_and_to_string() -> bool // NOLINT(readability-function-cognit #if defined(__cpp_lib_to_chars) for(auto i = static_cast(UINT32_C(0)); - i < static_cast(UINT32_C(256)); + i < static_cast(loop_count_hi); ++i) { // Verify write to_chars() and read back from string of unsigned uintwide_t. @@ -1139,7 +1159,7 @@ auto test_to_chars_and_to_string() -> bool // NOLINT(readability-function-cognit } for(auto i = static_cast(UINT32_C(0)); - i < static_cast(UINT32_C(256)); + i < static_cast(loop_count_hi); ++i) { // Verify write to_chars() and read back from string of signed uintwide_t. @@ -1172,7 +1192,7 @@ auto test_to_chars_and_to_string() -> bool // NOLINT(readability-function-cognit #if !defined(WIDE_INTEGER_DISABLE_TO_STRING) for(auto i = static_cast(UINT32_C(0)); - i < static_cast(UINT32_C(256)); + i < static_cast(loop_count_hi); ++i) { // Verify write to_string() and read back from string of unsigned uintwide_t. @@ -1191,7 +1211,7 @@ auto test_to_chars_and_to_string() -> bool // NOLINT(readability-function-cognit } for(auto i = static_cast(UINT32_C(0)); - i < static_cast(UINT32_C(256)); + i < static_cast(loop_count_hi); ++i) { // Verify write to_string() and read back from string of signed uintwide_t. @@ -1242,6 +1262,7 @@ auto test_to_chars_and_to_string() -> bool // NOLINT(readability-function-cognit result_is_ok = (result_to_strings_are_ok && result_is_ok); } + #if !(defined(_MSC_VER) && defined(_DEBUG)) for(auto i = static_cast(UINT32_C(0)); i < static_cast(UINT32_C(32)); ++i) @@ -1266,6 +1287,7 @@ auto test_to_chars_and_to_string() -> bool // NOLINT(readability-function-cognit result_is_ok = (result_u_to_from_string_is_ok && result_is_ok); } + #endif #endif // !WIDE_INTEGER_DISABLE_TO_STRING return result_is_ok; @@ -1294,7 +1316,7 @@ auto test_import_bits() -> bool // NOLINT(readability-function-cognitive-complex for(const auto& msv_first : msv_options) // NOLINT { for(auto i = static_cast(UINT32_C(0)); - i < static_cast(UINT32_C(64)); + i < static_cast(loop_count_lo); ++i) { // Verify import_bits() and compare with Boost control value(s). @@ -1345,7 +1367,7 @@ auto test_import_bits() -> bool // NOLINT(readability-function-cognitive-complex for(const auto& chunk_size : bits_for_chunks) { for(auto i = static_cast(UINT32_C(0)); - i < static_cast(UINT32_C(64)); + i < static_cast(loop_count_lo); ++i) { // Verify import_bits() and compare with Boost control value(s). @@ -1386,7 +1408,7 @@ auto test_import_bits() -> bool // NOLINT(readability-function-cognitive-complex for(const auto& msv_first : msv_options) // NOLINT { for(auto i = static_cast(UINT32_C(0)); - i < static_cast(UINT32_C(64)); + i < static_cast(loop_count_lo); ++i) { // Verify import_bits() and compare with Boost control value(s). @@ -1412,7 +1434,7 @@ auto test_import_bits() -> bool // NOLINT(readability-function-cognitive-complex #endif using local_double_width_input_array_type = - std::array; + std::array; local_double_width_input_array_type bits_double_width; @@ -1435,7 +1457,13 @@ auto test_import_bits() -> bool // NOLINT(readability-function-cognitive-complex index + static_cast(UINT8_C(1)) ); - elem = make_large(bits[index], bits[index_plus_one]); + #if defined(WIDE_INTEGER_NAMESPACE) + elem = make_large(*WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::advance_and_point(bits.cbegin(), index), + *WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::advance_and_point(bits.cbegin(), index_plus_one)); + #else + elem = make_large(*::math::wide_integer::detail::advance_and_point(bits.cbegin(), index), + *::math::wide_integer::detail::advance_and_point(bits.cbegin(), index_plus_one)); + #endif index = static_cast(index + static_cast(UINT8_C(2))); } @@ -1461,7 +1489,7 @@ auto test_import_bits() -> bool // NOLINT(readability-function-cognitive-complex for(const auto& msv_first : msv_options) // NOLINT { for(auto i = static_cast(UINT32_C(0)); - i < static_cast(UINT32_C(64)); + i < static_cast(loop_count_lo); ++i) { // Verify import_bits() and compare with Boost control value(s). @@ -1476,12 +1504,16 @@ auto test_import_bits() -> bool // NOLINT(readability-function-cognitive-complex auto u_gen = generate_wide_integer_value(); using local_representation_less_wide_type = - std::array(static_cast(local_representation_type::static_size()) - 2U)>; + std::array(static_cast(local_uintwide_t_small_unsigned_type::number_of_limbs) - 2U)>; local_representation_less_wide_type bits { }; std::copy(u_gen.crepresentation().cbegin(), - u_gen.crepresentation().cbegin() + std::tuple_size::value, + #if defined(WIDE_INTEGER_NAMESPACE) + WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::advance_and_point(u_gen.crepresentation().cbegin(), std::tuple_size::value), + #else + ::math::wide_integer::detail::advance_and_point(u_gen.crepresentation().cbegin(), std::tuple_size::value), + #endif bits.begin()); #if defined(WIDE_INTEGER_NAMESPACE) @@ -1495,7 +1527,7 @@ auto test_import_bits() -> bool // NOLINT(readability-function-cognitive-complex using local_double_width_less_wide_input_array_type = std::array::value / 2U>; - static_assert(std::tuple_size::value == static_cast(static_cast(static_cast(local_representation_type::static_size()) / 2U) - 1U), + static_assert(std::tuple_size::value == static_cast(static_cast(static_cast(local_uintwide_t_small_unsigned_type::number_of_limbs) / 2U) - 1U), "Error: Type definition widths are not OK"); local_double_width_less_wide_input_array_type bits_double_width; @@ -1603,7 +1635,7 @@ auto test_export_bits() -> bool // NOLINT(readability-function-cognitive-complex for(const auto& msv_first : msv_options) // NOLINT { for(auto i = static_cast(UINT32_C(0)); - i < static_cast(UINT32_C(64)); + i < static_cast(loop_count_lo); ++i) { // Verify export_bits() and compare with Boost control value(s). @@ -1620,7 +1652,7 @@ auto test_export_bits() -> bool // NOLINT(readability-function-cognitive-complex const auto val_boost = local_boost_small_uint_type(to_string(val_uintwide_t)); using local_output_array_type = - std::array; + std::array; using local_result_value_type = typename local_output_array_type::value_type; @@ -1645,7 +1677,7 @@ auto test_export_bits() -> bool // NOLINT(readability-function-cognitive-complex for(const auto& chunk_size : bits_for_chunks) { for(auto i = static_cast(UINT32_C(0)); - i < static_cast(UINT32_C(64)); + i < static_cast(loop_count_lo); ++i) { // Verify export_bits() and compare with Boost control value(s). @@ -1704,7 +1736,7 @@ auto test_export_bits() -> bool // NOLINT(readability-function-cognitive-complex for(const auto& msv_first : msv_options) // NOLINT { for(auto i = static_cast(UINT32_C(0)); - i < static_cast(UINT32_C(64)); + i < static_cast(loop_count_lo); ++i) { // Verify export_bits() and compare with Boost control value(s). @@ -1731,7 +1763,7 @@ auto test_export_bits() -> bool // NOLINT(readability-function-cognitive-complex #endif using local_double_width_output_array_type = - std::array; + std::array; local_double_width_output_array_type bits_result_double_width_from_uintwide_t { }; local_double_width_output_array_type bits_result_double_width_from_boost { }; @@ -1783,7 +1815,9 @@ auto ::math::wide_integer::test_uintwide_t_edge_cases() -> bool auto result_is_ok = true; + #if !(defined(_MSC_VER) && defined(_DEBUG)) result_is_ok = (test_uintwide_t_edge::test_various_edge_operations () && result_is_ok); + #endif result_is_ok = (test_uintwide_t_edge::test_various_ostream_ops () && result_is_ok); result_is_ok = (test_uintwide_t_edge::test_various_roots_and_pow_etc () && result_is_ok); result_is_ok = (test_uintwide_t_edge::test_various_isolated_edge_cases() && result_is_ok); diff --git a/test/test_uintwide_t_examples.cpp b/test/test_uintwide_t_examples.cpp index 6e22f95a..f6862282 100644 --- a/test/test_uintwide_t_examples.cpp +++ b/test/test_uintwide_t_examples.cpp @@ -38,7 +38,9 @@ auto ::math::wide_integer::test_uintwide_t_examples() -> bool result_is_ok = (math::wide_integer::example009b_timed_mul_8_by_8 () && result_is_ok); std::cout << "result_is_ok after example009b_timed_mul_8_by_8 : " << std::boolalpha << result_is_ok << std::endl; result_is_ok = (math::wide_integer::example010_uint48_t () && result_is_ok); std::cout << "result_is_ok after example010_uint48_t : " << std::boolalpha << result_is_ok << std::endl; result_is_ok = (math::wide_integer::example011_uint24_t () && result_is_ok); std::cout << "result_is_ok after example011_uint24_t : " << std::boolalpha << result_is_ok << std::endl; + #if !(defined(_MSC_VER) && defined(_DEBUG)) result_is_ok = (math::wide_integer::example012_rsa_crypto () && result_is_ok); std::cout << "result_is_ok after example012_rsa_crypto : " << std::boolalpha << result_is_ok << std::endl; + #endif return result_is_ok; } diff --git a/test/test_uintwide_t_spot_values.cpp b/test/test_uintwide_t_spot_values.cpp index f1dbf214..5fb1df0c 100644 --- a/test/test_uintwide_t_spot_values.cpp +++ b/test/test_uintwide_t_spot_values.cpp @@ -109,18 +109,18 @@ namespace from_issue_316 88, 53, 153, 106, 94, 112, 136, 40, 229, 3, 176, 116, 42, 179, 23, 109, 103, 70, 57, 154, 157, 110, 148, 87, - 86, 78, 175, 99, 6, 111, 16, 103, + 86, 78, 175, 99, 6, 111, 16, 103, 142, 61, 253, 224, 39, 52, 137, 252, - 56, 116, 147, 71, 168, 16, 155, 245, + 56, 116, 147, 71, 168, 16, 155, 245, 197, 97, 57, 69, 226, 13, 239, 164, - 40, 228, 250, 130, 128, 186, 150, 3, - 64, 81, 241, 165, 43, 136, 99, 79, + 40, 228, 250, 130, 128, 186, 150, 3, + 64, 81, 241, 165, 43, 136, 99, 79, 124, 188, 50, 46, 152, 197, 205, 204, 103, 254, 61, 143, 94, 31, 6, 98, 165, 16, 223, 175, 30, 87, 156, 176, 232, 56, 179, 56, 184, 220, 100, 141, 212, 201, 55, 246, 199, 117, 28, 154, - 51, 140, 5, 95, 102, 187, 133, 248 + 51, 140, 5, 95, 102, 187, 133, 248 }; auto test_uintwide_t_spot_values_from_issue_316_import_export_original() -> bool @@ -285,7 +285,7 @@ namespace from_issue_234 using uint512 = ::math::wide_integer::uintwide_t(UINT32_C(512)), std::uint32_t>; #endif - inline WIDE_INTEGER_CONSTEXPR auto convert_to_uint80(uint512 value) -> uint80 + WIDE_INTEGER_CONSTEXPR auto convert_to_uint80(const uint512& value) -> uint80 { #if defined(WIDE_INTEGER_NAMESPACE) using WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::make_lo; @@ -304,16 +304,24 @@ namespace from_issue_234 uint80::from_rep ( { - make_lo(*(value.crepresentation().data() + 0U)), - make_hi(*(value.crepresentation().data() + 0U)), - make_lo(*(value.crepresentation().data() + 1U)), - make_hi(*(value.crepresentation().data() + 1U)), - make_lo(*(value.crepresentation().data() + 2U)) + #if defined(WIDE_INTEGER_NAMESPACE) + make_lo(*WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::advance_and_point(value.crepresentation().cbegin(), 0U)), + make_hi(*WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::advance_and_point(value.crepresentation().cbegin(), 0U)), + make_lo(*WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::advance_and_point(value.crepresentation().cbegin(), 1U)), + make_hi(*WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::advance_and_point(value.crepresentation().cbegin(), 1U)), + make_lo(*WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::advance_and_point(value.crepresentation().cbegin(), 2U)) + #else + make_lo(*::math::wide_integer::detail::advance_and_point(value.crepresentation().cbegin(), 0U)), + make_hi(*::math::wide_integer::detail::advance_and_point(value.crepresentation().cbegin(), 0U)), + make_lo(*::math::wide_integer::detail::advance_and_point(value.crepresentation().cbegin(), 1U)), + make_hi(*::math::wide_integer::detail::advance_and_point(value.crepresentation().cbegin(), 1U)), + make_lo(*::math::wide_integer::detail::advance_and_point(value.crepresentation().cbegin(), 2U)) + #endif } ); } - inline WIDE_INTEGER_CONSTEXPR auto convert_to_uint512(uint80 value) -> uint512 + WIDE_INTEGER_CONSTEXPR auto convert_to_uint512(const uint80& value) -> uint512 { #if defined(WIDE_INTEGER_NAMESPACE) using WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::make_large; @@ -330,11 +338,19 @@ namespace from_issue_234 uint512::from_rep ( { - make_large(*(value.crepresentation().data() + 0U), - *(value.crepresentation().data() + 1U)), - make_large(*(value.crepresentation().data() + 2U), - *(value.crepresentation().data() + 3U)), - make_large(*(value.crepresentation().data() + 4U), + #if defined(WIDE_INTEGER_NAMESPACE) + make_large(*WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::advance_and_point(value.crepresentation().cbegin(), 0U), + *WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::advance_and_point(value.crepresentation().cbegin(), 1U)), + make_large(*WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::advance_and_point(value.crepresentation().cbegin(), 2U), + *WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::advance_and_point(value.crepresentation().cbegin(), 3U)), + make_large(*WIDE_INTEGER_NAMESPACE::math::wide_integer::detail::advance_and_point(value.crepresentation().cbegin(), 4U), + #else + make_large(*::math::wide_integer::detail::advance_and_point(value.crepresentation().cbegin(), 0U), + *::math::wide_integer::detail::advance_and_point(value.crepresentation().cbegin(), 1U)), + make_large(*::math::wide_integer::detail::advance_and_point(value.crepresentation().cbegin(), 2U), + *::math::wide_integer::detail::advance_and_point(value.crepresentation().cbegin(), 3U)), + make_large(*::math::wide_integer::detail::advance_and_point(value.crepresentation().cbegin(), 4U), + #endif static_cast(0U)) } ); @@ -344,7 +360,7 @@ namespace from_issue_234 namespace from_issue_145 { template - auto test_uintwide_t_spot_values_from_issue_145(const UnknownIntegerType x) -> bool + auto test_uintwide_t_spot_values_from_issue_145(const UnknownIntegerType& x) -> bool { // See also https://github.com/ckormanyos/wide-integer/issues/145#issuecomment-1006374713 @@ -352,27 +368,25 @@ namespace from_issue_145 bool local_result_is_ok = true; - const auto a0(x); - #if (defined(__clang__) && (defined(__clang_major__) && (__clang_major__ > 6))) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wself-assign-overloaded" #endif { - local_unknown_integer_type a = a0; a += a; // NOLINT(clang-diagnostic-self-assign-overloaded) + local_unknown_integer_type a = x; a += a; // NOLINT(clang-diagnostic-self-assign-overloaded) - local_result_is_ok = ((a == (2U * a0)) && local_result_is_ok); + local_result_is_ok = ((a == (2U * x)) && local_result_is_ok); } { - local_unknown_integer_type a = a0; a -= a; // NOLINT(clang-diagnostic-self-assign-overloaded) + local_unknown_integer_type a = x; a -= a; // NOLINT(clang-diagnostic-self-assign-overloaded) local_result_is_ok = ((a == 0U) && local_result_is_ok); } { - local_unknown_integer_type a = a0; a /= a; // NOLINT(clang-diagnostic-self-assign-overloaded) + local_unknown_integer_type a = x; a /= a; // NOLINT(clang-diagnostic-self-assign-overloaded) local_result_is_ok = ((a == 1U) && local_result_is_ok); } @@ -889,7 +903,7 @@ auto local_test_spot_values::test() -> bool // NOLINT(readability-function-cogni assert((std::numeric_limits::max)() != 0U); // NOLINT assert((std::numeric_limits::max)() != 0U); // NOLINT assert((std::numeric_limits::max)() != 0U); // NOLINT - assert((std::numeric_limits::max)() != 0U); // NOLINT + assert((std::numeric_limits::max)() != 0U); // NOLINT // LCOV_EXCL_LINE assert((std::numeric_limits::min)() == 0U); // NOLINT assert((std::numeric_limits::min)() == 0U); // NOLINT