Это должно работать (если и a, и b находятся между 0 и 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;
}
}
Когда происходит переполнение, a * b фактически будет a * b - 2 ^ 64, поэтому необходимо добавить (2 ^ 64 mod fieldPrime). Добавление еще одного fieldPrime и еще одной операции% необходимо для получения результата в диапазоне от 0 до fieldPrime-1 (в противном случае он может быть отрицательным).
(Это не будет работать, если fieldPrime> 2 ^ 32.)
EDIT
Другая часть также может быть изменена на:
return (fieldPrime-a)*(fieldPrime-b)%fieldPrime;
(я не знаю, что быстрее.)