Efficiently compute the modulo of the sum of two numbers

2.2k Views Asked by At

I have three N-bit numbers, A, B, and C. I cannot easily calculate (A + B) % C but I can easily calculate A % C and B % C. If the modulo operation is unsigned and I know ahead of time that A + B does not wrap around N bits then I can instead calculate ((A % C) + (B % C)) % C. However, is it possible to do anything for the cases where the modulo operation is signed or the addition of A and B might lead to a wrap-around.

It looks like there might be some confusion as to why ((A % C) + (B % C)) % C cannot be relied upon to always work. Here is an unsigned example:

unsigned A = 0x1U;
unsigned B = 0xFFFFFFFFU;
unsigned C = 0x3U;
((A % C) + (B % C)) % C == 0x1U but (A + B) % C == 0x0U

Here is a signed example:

int A = 0x1;
int B = 0xE27F9803;
int C = 0x3U;
((A % C) + (B % C)) % C == 0x1U but (A + B) % C == -2
2

There are 2 best solutions below

8
On

In math, integer division is normally rounded down towards negative infinity, and the sign of modulo is the same as the same of the "divisor" or it's zero: -10 mod 3 = 2 and 10 mod -3 = -2 (quotient rounded down to -4). In C / C++, integer division is rounded towards zero and the sign of % is the same as the sign of the "dividend" or "numerator" or it's zero, -10 mod 3 = -1 and 10 mod -3 = 1 (quotient rounded towards zero to -3). When doing finite field type math with C / C++, you need to do post correction so that the results match the mathematical definition of modulo. For example, if X % 3 = -1, then add 3 so that X mod 3 = +2.

Assuming C is positive, then the mathematical field modulo C consists of the numbers {0, 1, ... C-1}, without any negative numbers. If C was negative (this is unusual for modulo), then the field is {0, -1, -2, ... C+1}. Assuming C is positive, then if A or B is negative, it is still safe to use ((A%C)+(B%C))%C, and then post correct if the result is negative by adding C to the result.

0
On

What you want is:

((a+b)%2^n)%c

Let

a+b = k 2^n + d

Where k = 0 or 1 and d < 2^n.

Plugging in you get:

 ((k 2^n + d) % 2^n) % c = (d % 2^n) % c = d % c

Taking the previous expression modulo c you get

 (a + b) % c = (k 2^n + d) % c => d % c = a % c + b % c - k 2^n % c

With n = 32, in C:

unsigned myMod(unsigned a, unsigned b, unsigned c)
{
     // k = 1 if the sum overflows
     unsigned k = ( a > UINT_MAX - b or b > UINT_MAX - a);

     return ( a % c + b % c -  k*(UINT_MAX%c + 1))%c;
}

myMod(0x1U,0xFFFFFFFFU,0x3U) == 0