Here is a proof that your C code generates overflows even with uint64_t
type.
I have just converted the C code into Python, adding an overflow test. The first value not representable as an uint64_t
is 2**64 or 0x10000000000000000 or 18446744073709551616. So I tested all products before the mod operation:
def Power(A, B, X):
res = 1
step = 1
while (B > 0):
if B & 1:
if (res * A) >= 0x1000000000000000:
print("uint64_t overflow at res step", step)
res = (res * A) % X
if (A * A) >= 0x1000000000000000:
print("uint64_t overflow at A step", step)
A = (A * A) % X
B >>= 1
step += 1
return res
>>> Power(15, 47413144071, 94826288143)
uint64_t overflow at A step 4
uint64_t overflow at A step 5
uint64_t overflow at A step 6
uint64_t overflow at A step 7
uint64_t overflow at A step 8
uint64_t overflow at A step 9
uint64_t overflow at res step 10
uint64_t overflow at A step 10
uint64_t overflow at A step 11
uint64_t overflow at res step 12
uint64_t overflow at A step 12
uint64_t overflow at A step 13
uint64_t overflow at res step 14
uint64_t overflow at A step 14
uint64_t overflow at A step 15
uint64_t overflow at A step 16
uint64_t overflow at res step 17
uint64_t overflow at A step 17
uint64_t overflow at res step 18
uint64_t overflow at A step 18
uint64_t overflow at A step 19
uint64_t overflow at res step 20
uint64_t overflow at A step 20
uint64_t overflow at A step 21
uint64_t overflow at A step 22
uint64_t overflow at A step 23
uint64_t overflow at A step 24
uint64_t overflow at A step 25
uint64_t overflow at res step 26
uint64_t overflow at A step 26
uint64_t overflow at A step 27
uint64_t overflow at res step 28
uint64_t overflow at A step 28
uint64_t overflow at A step 29
uint64_t overflow at A step 30
uint64_t overflow at A step 31
uint64_t overflow at A step 32
uint64_t overflow at res step 33
uint64_t overflow at A step 33
uint64_t overflow at res step 34
uint64_t overflow at A step 34
uint64_t overflow at A step 35
uint64_t overflow at res step 36
uint64_t overflow at A step 36
1
This definitely proves that the algo is correct (we get 1
in the end) but also that you get a number of overflows if you try to use 64 bits integers.
Long story made short, if you need to implement that in C, you need either a system having a uint128_t
type, or use a multiprecision library like gmplib.