How to calculate a**b % m where all the members are integers, and a^b is outside the int range?
I.e. to raise a to the power b under modulo m. I.e. an equivalent of this Python code:
pow(a, b, m)
It should be possible to do this in a more memory-efficient way, without resorting to big integers.
This is a direct translation from the pseudocode found on Wikipedia:
package main
import (
"fmt"
)
func modPow(a, b, m int) int {
if m == 1 {
return 0
}
c := 1
for i := 0; i < b; i++ {
c = (c * a) % m
}
return c
}
func main() {
fmt.Println(modPow(1234, 5678, 9012))
}
Disclaimer: I don't know golang :)
m had better be a 32bit integer if int is 64bit (otherwise c * a could overflow) (this also requires that a < m but that's a reasonable limitation). Also looping b times is very inefficient, exponentiation by squaring does it in log(b) steps. Having to convert to and from BigInt is a disadvantage but at least that approach avoids these things.Calculating the exponent manually as suggested by Robby, but efficiently:
func pow(a, b, m int) int {
if b < 0 {
panic("Negative power given")
}
result := 1
power := a
for b > 0 {
if b & 1 == 1 {
result = result * power % m
}
power = power * power % m
b >>= 1
}
return result
}
This is an iterative version of exponentiation by squaring. The time complexity is O(log(b)) if we assume that every multiplication takes O(1) time.
If m is prime, it's possible to calculate the negative power. It requires 2 steps:
func powUniversal(a, b, m int) int {
if b >= 0 {
return pow(a, b, m)
}
subResult := pow(a, -b, m)
return pow(subResult, m - 2, m)
}
You can check that it works by asserting powUniversal(a, b, m) * powUniversal(a, -b, m) % m == 1.