diff --git a/include/real/exact_number.hpp b/include/real/exact_number.hpp index 5080259..7e07aca 100644 --- a/include/real/exact_number.hpp +++ b/include/real/exact_number.hpp @@ -145,6 +145,20 @@ namespace boost { this->normalize(); } + // returns (a+b)%mod + T addn(T a, T b, T mod){ + T min = std::min(a, b); + T max = std::max(a, b); + if(max<(mod-min)){ + return (max+min); + } + if(mod%2==0){ + return (max-mod/2)-(mod/2-min); + }else{ + return (max-mod/2)-(mod/2-min)-1; + } + } + //Returns (a*b)%mod T mulmod(T a, T b, T mod) { @@ -154,10 +168,10 @@ namespace boost { { // If b is odd, add 'a' to result if (b % 2 == 1) - res = (res + a) % mod; + res = addn(res, a, mod); // Multiply 'a' with 2 - a = (a * 2) % mod; + a = addn(a, a, mod); // Divide b by 2 b /= 2; @@ -175,17 +189,19 @@ namespace boost { // a < c, rem < c. while (b != 0) { if (b & 1) { - rem += a; - if (rem >= c) { - rem -= c; - res++; + if(rem >= (c-a)){ + rem = addn(rem, a, c); + res++; + }else{ + rem = rem + a; } } b /= 2; - a *= 2; - if (a >= c) { - a -= c; - res += b; + if(a >= (c-a)){ + a = addn(a, a, c); + res += b; + }else{ + a *= 2; } } return res; diff --git a/test/real_overflow_multiplication_test.cpp b/test/real_overflow_multiplication_test.cpp new file mode 100644 index 0000000..f21efd6 --- /dev/null +++ b/test/real_overflow_multiplication_test.cpp @@ -0,0 +1,48 @@ +#include +// #include + +#include +#include + +TEST_CASE("Overflow in Multiplication check") { + SECTION("A"){ + boost::real::real a1("2123643646"); + boost::real::real b1("2147471816"); + boost::real::real c1; + boost::real::real d1("4560464877012481136"); + c1 = a1*b1; + CHECK(d1 == c1); + } + SECTION("B"){ + boost::real::real a2("2320102120234"); + boost::real::real b2("1201320452302"); + boost::real::real c2; + boost::real::real d2("2787186128466338066078668"); + c2 = a2*b2; + CHECK(d2 == c2); + } + SECTION("C"){ + boost::real::real a3("4524435689"); + boost::real::real b3("6870530492"); + boost::real::real c3; + boost::real::real d3("31085273360367528988"); + c3 = a3*b3; + CHECK(d3 == c3); + } + SECTION("D"){ + boost::real::real a4("7869349424036"); + boost::real::real b4("3435469507547"); + boost::real::real c4; + boost::real::real d4("27034909990508225005199692"); + c4 = a4*b4; + CHECK(d4 == c4); + } + SECTION("E"){ + boost::real::real a5("2123453646"); + boost::real::real b5("2147482316"); + boost::real::real c5; + boost::real::real d5("4560079153630724136"); + c5 = a5*b5; + CHECK(d5 == c5); + } +} \ No newline at end of file