diff --git a/doc/modular_arithmetic/mod_inverse.qbk b/doc/modular_arithmetic/mod_inverse.qbk index 2f3e66e..669311b 100644 --- a/doc/modular_arithmetic/mod_inverse.qbk +++ b/doc/modular_arithmetic/mod_inverse.qbk @@ -14,7 +14,7 @@ A fast algorithm for computing modular multiplicative inverses based on the exte namespace boost { namespace integer { template - boost::optional mod_inverse(Z a, Z m); + Z mod_inverse(Z a, Z m); }} @@ -22,20 +22,19 @@ A fast algorithm for computing modular multiplicative inverses based on the exte [section Usage] -Multiplicative modular inverses exist if and only if /a/ and /m/ are coprime. -So for example + int x = mod_inverse(2, 5); + // prints x = 3: + std::cout << "x = " << x << "\n"; - auto x = mod_inverse(2, 5); - if (x) - { - int should_be_three = x.value(); - } - auto y = mod_inverse(2, 4); - if (!y) + int y = mod_inverse(2, 4); + if (y == 0) { std::cout << "There is no inverse of 2 mod 4\n"; } +Multiplicative modular inverses exist if and only if /a/ and /m/ are coprime. +If /a/ and /m/ share a common factor, then `mod_inverse(a, m)` returns zero. + [endsect] [section References] diff --git a/include/boost/integer/mod_inverse.hpp b/include/boost/integer/mod_inverse.hpp index 2f07227..d735d19 100644 --- a/include/boost/integer/mod_inverse.hpp +++ b/include/boost/integer/mod_inverse.hpp @@ -8,7 +8,6 @@ #define BOOST_INTEGER_MOD_INVERSE_HPP #include #include -#include #include namespace boost { namespace integer { @@ -21,7 +20,7 @@ namespace boost { namespace integer { // Would mod_inverse be sometimes mistaken as the modular *additive* inverse? // In any case, I think this is the best name we can get for this function without agonizing. template -boost::optional mod_inverse(Z a, Z modulus) +Z mod_inverse(Z a, Z modulus) { if (modulus < 2) { @@ -32,12 +31,12 @@ boost::optional mod_inverse(Z a, Z modulus) if (a == 0) { // a doesn't have a modular multiplicative inverse: - return boost::none; + return 0; } euclidean_result_t u = extended_euclidean(a, modulus); if (u.gcd > 1) { - return boost::none; + return 0; } // x might not be in the range 0 < x < m, let's fix that: while (u.x <= 0) diff --git a/test/mod_inverse_test.cpp b/test/mod_inverse_test.cpp index 793c5c1..8c99b4d 100644 --- a/test/mod_inverse_test.cpp +++ b/test/mod_inverse_test.cpp @@ -36,17 +36,17 @@ void test_mod_inverse() for (Z a = 1; a < modulus; ++a) { Z gcdam = gcd(a, modulus); - boost::optional inv_a = mod_inverse(a, modulus); + Z inv_a = mod_inverse(a, modulus); // Should fail if gcd(a, mod) != 1: if (gcdam > 1) { - BOOST_TEST(!inv_a); + BOOST_TEST(inv_a == 0); } else { - BOOST_TEST(inv_a.value() > 0); + BOOST_TEST(inv_a > 0); // Cast to a bigger type so the multiplication won't overflow. - int256_t a_inv = inv_a.value(); + int256_t a_inv = inv_a; int256_t big_a = a; int256_t m = modulus; int256_t outta_be_one = (a_inv*big_a) % m;