-1

I have a problem with my binary powering function. Variable which contains the result overflows while performing multiplication and gives me a wrong result. It happens when the source value is greater than 4,312,952,827. So how do I solve this problem? Here's the code of my function.

unsigned long long binpow(unsigned long long a, unsigned long long n, unsigned long long m)
{
    unsigned long long res;
    res=1;
    while (n)
    {
        if (n & 1)
        {
            res=(res*a)%m;
            n--;
        }
        a=(a*a)%m;
        n >>= 1;
    }
    return res;
}
Simon Rusinov
  • 29
  • 1
  • 5

2 Answers2

1

The expression a*a requires room that is twice as much as the source's size. In your scenario 4,312,952,827 > 2^32-1, hence you are out the unsigned long long's range.

The rule of thumb for implementing modular exponentation's binary ladders is to able to perform arithmetic on range that is at least twice of the datatype of arguments, thus in your case it is 128-bit.

Grzegorz Szpetkowski
  • 36,988
  • 6
  • 90
  • 137
0

Both your residue and modulus are exceeding the width of an unsigned long long (shifted by m).

You can put off the problem by using a compiler extension type like unsigned __int128, which produces the correct result for 4,312,952,827.

unsigned __int128 binpow(unsigned __int128 a, unsigned __int128 n, unsigned __int128 m)
{
    unsigned __int128 res;
    res = 1;
    while (n)
        {
            if (n & 1)
                {
                    res = (res*a)%m;
                    n--;
                }
            a = (a*a) % m;
            n >>= 1;
        }
    return res;
}

Alternatively, if you want to work with large numbers in a safe fashion, there are general-purpose bignum libraries like gmplib

zetavolt
  • 2,989
  • 1
  • 23
  • 33
  • Thank you my friend, your answer is very helpful. Actually I am using this function as a part of algorithm which defines whether number is prime or not. So the speed of calculations here is vital. May I ask you will that library slow calculations down much? – Simon Rusinov Jun 01 '16 at 01:57