The power function is defined as:
bigint_t power(const bigint_t& n, size_t p);
This calculates
The naive implementation for power is:
bigint::bigint_t power(const bigint::bigint_t& n, size_t p)
{
bigint::bigint_t result = 1ULL;
for (size_t i = 0; i < p; ++i)
result *= n;
return result;
}
This approach suffers from 2 downsides:
- It requires
p
multiplications. - The multiplications (
result * n
) are all done against the samen
.
The multiplication algorithms get increasingly more efficient with the number of limbs of each operand ((a * b) * (c * d)
is faster to calculate than((a * b) * c ) * d
).$n$ remaining the same, its number of limbs never grows either and efficient multiplication algorithm can never be leveraged.
This library uses exponentiation by squaring, which addresses the 2 downsides listed above.
Exponentiation by squaring is an important algorithm, which is also used in the calculation of Fibonacci numbers.
Instead of simply multiplying
The algorithm makes use of the fact that
Illustration for
- Decompose the exposant into its binary digits:
$19 = 2^0 + 2^1 + 2^4$ - We start with
$i = 0$ , i.e.$3^{2^0} = 3$ . - For
$i = 1$ , we calculate$3^{2^1} = 3 \times 3 = 9$ . - For
$i = 2$ , we calculate$3^{2^2} = 9 \times 9 = 81$ .
$2^2$ does not enter into the decomposition of 19; this is not going to be used in the final product but we need it for the next step of the calculation. - For
$i = 3$ , we calculate$3^{2^3} = 81 \times 81 = 6{,}561$ .
Same as above, this is only useful to get to the next step of the calculation. - For
$i = 4$ , we calculate$3^{2^4} = 6{,}561 \times 6{,}561 = 43{,}046{,}721$ . - We have now covered all the binary digits of
$19$ .
We can calculate$3^{19} = 3 \times 9 \times 43{,}046{,}721 = 1{,}162{,}261{,}467$ .
The algorithm uses
In other words, setting aside the complexity of the multiplication operation, this algorithm has a complexity of
- Initialize
$\text{result} \leftarrow 1, \text{cache} \leftarrow n$ . - If
$p = 0$ , stop and return$\text{result}$ . - If
$p \bmod 2 = 1$ , do$\text{result} \leftarrow \text{result} \times \text{cache}$ . - Do
$\text{cache} \leftarrow \text{cache} \times \text{cache}$ . - Do
$p \leftarrow \lfloor p / 2 \rfloor$ . - Go back to step 2.