Fastest way to calculate a 128-bit integer modulo a 64-bit integer
You can use the division version of Russian Peasant Multiplication.
To find the remainder, execute (in pseudo-code):
X = B;while (X <= A/2){ X <<= 1;}while (A >= B){ if (A >= X) A -= X; X >>= 1;}
The modulus is left in A.
You'll need to implement the shifts, comparisons and subtractions to operate on values made up of a pair of 64 bit numbers, but that's fairly trivial (likely you should implement the left-shift-by-1 as X + X
).
This will loop at most 255 times (with a 128 bit A). Of course you need to do a pre-check for a zero divisor.
Perhaps you're looking for a finished program, but the basic algorithms for multi-precision arithmetic can be found in Knuth's Art of Computer Programming, Volume 2. You can find the division algorithm described online here. The algorithms deal with arbitrary multi-precision arithmetic, and so are more general than you need, but you should be able to simplify them for 128 bit arithmetic done on 64- or 32-bit digits. Be prepared for a reasonable amount of work (a) understanding the algorithm, and (b) converting it to C or assembler.
You might also want to check out Hacker's Delight, which is full of very clever assembler and other low-level hackery, including some multi-precision arithmetic.
If your B is small enough for the uint64_t
+
operation to not wrap:
Given A = AH*2^64 + AL
:
A % B == (((AH % B) * (2^64 % B)) + (AL % B)) % B == (((AH % B) * ((2^64 - B) % B)) + (AL % B)) % B
If your compiler supports 64-bit integers, then this is probably the easiest way to go.MSVC's implementation of a 64-bit modulo on 32-bit x86 is some hairy loop filled assembly (VC\crt\src\intel\llrem.asm
for the brave), so I'd personally go with that.