I have to perform (a * b) % m
, but a
, b
, and m
are 128-bit unsigned types, and overflow during multiplication is a large possibility. How can I still get a correct answer (probably using %
more)?
I'm trying to implement the modular exponent function in Rust, where the largest built-in type is u128
(which is the max I can use). All three variables are really large, and so (a * b) > 2^128
is easy. I can use a.overflowing_mul(b)
to detect whether an overflow occurred, but I do not know how to go back from the overflowed result (which can be thought of as (a * b) % 2^128
) to get (a * b) % m
.
My modular exponent code looks like this (currently no overflowing support is added):
fn mod_exp(b: u128, e: u128, m: u128) {
(0..e).fold(1, |x, _| (x * b) % m)
// ^^^^^^^^^^^
}
From a mathematical perspective:
(a * b) % m IS ACTUALLY (a * b) % B % m
| B = current base (2^128)
Examples:
// Mathematical
(9 * 13) % 11 = 7
// Real (base 20):
(9 * 13) % (B = 20) % 11 = 6
^^^^^^^^^^ ^ should be 7
(8 * 4) % 14 = 4
(8 * 4) % (B = 16) % 14 = 0
^^^^^^^^^^ ^ should be 4