3

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).

2 Answers 2

4

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.)

Sign up to request clarification or add additional context in comments.

Comments

0

You could convert a, b, and fieldPrime to doubles and cast the result back to a long once you know you're in a safe range again (after modulo). However it's possible that doubles could cause rounding errors in some cases.

Other than that I'd say BigInteger is your best bet, if it's too slow, maybe you could make something that would work with byte arrays instead of longs, but I doubt that would be much quicker.

2 Comments

If you're going to down vote me for an answer that is at least trying to be helpful you should probably tell me why to give me a chance to check it out...
I didn't down-vote it. I agree with you, down-votes should be followed by a comment.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.