I have a function Java which looks like this:
private static long fieldPrime = 4294967291L; // 2^32-5
public final static long modMult(long a, long b) {
long r = (a*b) % fieldPrime;
return r;
}
It multiplies two values (which are guaranteed to be between 0 and 2^32-5) and then does modulo a large prime.
It works for most numbers but sometimes a*b overflows and this causes the function to return the wrong value. Unfortunately Java doesn't support unsigned longs (which would have solved the issue) and BigInteger is too slow. Can I solve this some other way? I.e. can I adjust r somehow when I detect overflow (in this case a*b < 0 always means it has overflowed).
This should work (if both a and b are between 0 and fieldPrime-1):
private static long fieldPrime = 4294967291L; // 2^32-5
private static long correctionFactor = fieldPrime+25; //fieldPrime + (2^64) mod fieldPrime
public final static long modMult(long a, long b) {
long r = (a*b);
if (r>=0)
{
return r % fieldPrime;
}
else
{
return ((r% fieldPrime)+correctionFactor)%fieldPrime;
}
}
When overflow occurs a*b will actually be a * b - 2^64 so adding (2^64 mod fieldPrime) is what is needed. Adding one more fieldPrime and one more % operation is needed to make the result in range 0 to fieldPrime-1 (otherwise it may be negative).
(It won't work this way if fieldPrime>2^32.)
EDIT The else part can also be changed to:
return (fieldPrime-a)*(fieldPrime-b)%fieldPrime;
(I don't known which is faster.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With