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:
Nick Thompson
2018-10-26 11:19:43 -06:00
parent 3f1603938c
commit 2d463f3ee7
4 changed files with 35 additions and 34 deletions

View File

@ -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};
}

View File

@ -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;
}
}}