Skip to content

Commit 51e858c

Browse files
authored
Update modular_inverse_fermat_little_theorem.cpp
1 parent fec9656 commit 51e858c

File tree

1 file changed

+58
-52
lines changed

1 file changed

+58
-52
lines changed

math/modular_inverse_fermat_little_theorem.cpp

Lines changed: 58 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -43,91 +43,97 @@
4343
* (as \f$a\times a^{-1} = 1\f$)
4444
*/
4545

46-
#include <cassert> /// for assert
47-
#include <iostream> /// for IO implementations
46+
#include <cassert> /// for assert
47+
#include <cstdint> /// for int64_t
48+
#include <iostream> /// for IO implementations
4849

4950
/**
5051
* @namespace math
51-
* @brief Maths algorithms
52+
* @brief Maths algorithms.
5253
*/
5354
namespace math {
5455
/**
55-
* @namespace modular_inverse_fermat_little_theorem
56-
* @brief Calculate modular inverse using Fermat's Little Theorem
56+
* @namespace modular_inverse_fermat
57+
* @brief Calculate modular inverse using Fermat's Little Theorem.
5758
*/
58-
namespace modular_inverse_fermat_little_theorem {
59-
/**
60-
* @brief Calculate exponent with modulo using divide-and-conquer.
59+
namespace modular_inverse_fermat {
60+
/**
61+
* @brief Calculate exponent with modulo using binary exponentiation.
6162
* @param a The base
6263
* @param b The exponent
6364
* @param m The modulo
64-
* @return res The result of \f$a^{b} % m\f$
65+
* @return The result of \f$a^{b} % m\f$
6566
*/
66-
int64_t binExpo(int64_t a, int64_t b, int64_t m) {
67-
a %= m;
68-
int64_t res = 1;
69-
while (b > 0) {
70-
if (b % 2) {
71-
res = res * a % m;
72-
}
73-
a = a * a % m;
74-
// Dividing b by 2 is similar to right shift.
75-
b >>= 1;
67+
std::int64_t binExpo(std::int64_t a, std::int64_t b, std::int64_t m) {
68+
a %= m;
69+
std::int64_t res = 1;
70+
while (b > 0) {
71+
if (b % 2 != 0) {
72+
res = res * a % m;
7673
}
77-
return res;
74+
a = a * a % m;
75+
// Dividing b by 2 is similar to right shift by 1 bit
76+
b >>= 1;
77+
}
78+
return res;
7879
}
7980
/**
80-
* @brief Check if a given integer is a prime number
81+
* @brief Check if a given integer is a prime number.
8182
* @param m An intger to check for primality
82-
* @return 'true' if the number is prime
83-
* @return 'false' if the number is not prime
83+
* @return 'true' if the number is prime, otherwise 'false'
8484
*/
85-
bool isPrime(int64_t m) {
86-
if (m <= 1) {
87-
return false;
88-
} else {
89-
for (int64_t i = 2; i * i <= m; i++) {
90-
if (m % i == 0) {
91-
return false;
92-
}
93-
}
85+
bool isPrime(std::int64_t m) {
86+
if (m <= 1) {
87+
return false;
88+
}
89+
for (std::int64_t i = 2; i * i <= m; i++) {
90+
if (m % i == 0) {
91+
return false;
9492
}
95-
return true;
93+
}
94+
return true;
9695
}
9796
/**
98-
* @brief Main function to calculate modular inverse
99-
* @param a Integer value for base
97+
* @brief Main function to calculate the modular inverse.
98+
* @param a Integer value for the base
10099
* @param m Integer value for modulo
101-
* @return the result that is the modular inverse of a modulo m
100+
* @return The result that is the modular inverse of a modulo m
102101
*/
103-
int64_t modular_inverse(int64_t a, int64_t m) {
104-
// modulo m is not prime
105-
if (!isPrime(m)) {
106-
return -1; // Using -1 to mark for invalid input
107-
}
108-
return binExpo(a, m - 2, m);
102+
std::int64_t modular_inverse(std::int64_t a, std::int64_t m) {
103+
while (a < 0) {
104+
a += m;
105+
}
106+
107+
// Check for invalid cases
108+
if (!isPrime(m) || a == 0) {
109+
return -1; // Invalid input
110+
}
111+
112+
return binExpo(a, m - 2, m); // Fermat's Little Theorem
109113
}
110-
} // namespace modular_inverse_fermat_little_theorem
111-
} // namespace math
114+
} // namespace modular_inverse_fermat
115+
} // namespace math
112116

113117
/**
114118
* @brief Self-test implementation
115119
* @return void
116120
*/
117121
static void test() {
118-
assert(math::modular_inverse_fermat_little_theorem::modular_inverse(3, 6) == -1);
119-
assert(math::modular_inverse_fermat_little_theorem::modular_inverse(3, 7) == 5);
120-
assert(math::modular_inverse_fermat_little_theorem::modular_inverse(1, 1) == 1);
121-
assert(math::modular_inverse_fermat_little_theorem::modular_inverse(1, 1) == 1);
122-
assert(math::modular_inverse_fermat_little_theorem::modular_inverse(1, 1) == 1);
123-
assert(math::modular_inverse_fermat_little_theorem::modular_inverse(1, 1) == 1);
122+
assert(math::modular_inverse_fermat::modular_inverse(0, 97) == -1);
123+
assert(math::modular_inverse_fermat::modular_inverse(15, -2) == -1);
124+
assert(math::modular_inverse_fermat::modular_inverse(3, 10) == -1);
125+
assert(math::modular_inverse_fermat::modular_inverse(3, 7) == 5);
126+
assert(math::modular_inverse_fermat::modular_inverse(1, 101) == 1);
127+
assert(math::modular_inverse_fermat::modular_inverse(-1337, 285179) == 165519);
128+
assert(math::modular_inverse_fermat::modular_inverse(123456789, 998244353) == 25170271);
129+
assert(math::modular_inverse_fermat::modular_inverse(-9876543210, 1000000007) == 784794281);
124130
}
125131

126132
/**
127133
* @brief Main function
128134
* @return 0 on exit
129135
*/
130136
int main() {
131-
test();
132-
return 0;
137+
test(); // run self-test implementation
138+
return 0;
133139
}

0 commit comments

Comments
 (0)