forked from boostorg/integer
a*p % m may overflow, do not perform naive multiplication in unit tests or undefined behavior may result. [CI SKIP]
This commit is contained in:
@ -6,12 +6,9 @@
|
||||
*/
|
||||
#ifndef BOOST_INTEGER_EXTENDED_EUCLIDEAN_HPP
|
||||
#define BOOST_INTEGER_EXTENDED_EUCLIDEAN_HPP
|
||||
#include <tuple>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <iostream>
|
||||
|
||||
namespace boost { namespace integer {
|
||||
|
||||
@ -71,14 +68,8 @@ euclidean_result_t<Z> extended_euclidean(Z m, Z n)
|
||||
|
||||
if (swapped)
|
||||
{
|
||||
std::swap(u1, u2);
|
||||
BOOST_ASSERT(u2*m+u1*n==u0);
|
||||
return {u0, u2, u2};
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT(u1*m+u2*n==u0);
|
||||
}
|
||||
|
||||
return {u0, u1, u2};
|
||||
}
|
||||
|
||||
|
@ -35,20 +35,19 @@ boost::optional<Z> mod_inverse(Z a, Z modulus)
|
||||
return {};
|
||||
}
|
||||
euclidean_result_t<Z> u = extended_euclidean(a, modulus);
|
||||
Z gcd = u.gcd;
|
||||
if (gcd > 1)
|
||||
if (u.gcd > 1)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
Z x = u.x;
|
||||
x = x % modulus;
|
||||
// x might not be in the range 0 < x < m, let's fix that:
|
||||
while (x <= 0)
|
||||
while (u.x <= 0)
|
||||
{
|
||||
x += modulus;
|
||||
u.x += modulus;
|
||||
}
|
||||
BOOST_ASSERT(x*a % modulus == 1);
|
||||
return x;
|
||||
// While indeed this is an inexpensive and comforting check,
|
||||
// the multiplication overflows and hence makes the check itself buggy.
|
||||
//BOOST_ASSERT(u.x*a % modulus == 1);
|
||||
return u.x;
|
||||
}
|
||||
|
||||
}}
|
||||
|
Reference in New Issue
Block a user