-3

I'm looking for a way to square a number n, x times and get the answer in modulo m (m is prime)? For example, if n = 5, x = 3 and m = 7, it would be (((5^2)^2)^2) % 7 = 390625 % 7 = 4

I tried exponentiation by squaring (I have a function called modularPow that accepts base, power, mod), and in this case it would simply be modularPow(5, 2^3, 7), which produces the correct answer. But the problem is, that x can be very big, even 10^12, so I would have to do modularPow(5, 2^(10^12), 7), which won't work. Is there any better way to do it? Preferably in Javascript, but Python would also work for me

  • 1
    The built-in `pow` function in Python already handles modular exponentiation efficiently. – chepner Apr 07 '23 at 12:30
  • Please visit [help], take [tour] to see what and [ask]. Do some research, search for related topics on SO; if you get stuck, post a [mcve] of your attempt, noting input and expected output, preferably in a [Stacksnippet](https://blog.stackoverflow.com/2014/09/introducing-runnable-javascript-css-and-html-code-snippets/) – mplungjan Apr 07 '23 at 12:33
  • @chepner As I said in the question, modular exponentiation won't be enough, because the second argument (power) may be too big (2^(10^12) in my example). I'm looking for a way to somehow reduce this value, so that it could be provided there – Patryk Grzyb Apr 07 '23 at 12:33
  • @mplungjan I did the research for half of the day, and the best thing I found was the `modularPow` thing, which turned out to be already built-in in Python. I also provided an example input and expected output, so everything is in place. I don't think there's anything more I can provide. I couldn't find anything similar to my question – Patryk Grzyb Apr 07 '23 at 12:36
  • Perhaps [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) or [other stuff](https://www.google.com/search?q=javascript+math+large+numbers&sxsrf=APwXEde1IZTNeb9Qnh1k4NM4WMw3tEJOBA:1680871122686&source=lnt&tbs=qdr:y&sa=X&ved=2ahUKEwjQ9rjx5Jf-AhWRHuwKHfX_Da4QpwV6BAgBEBk&biw=2047&bih=1203&dpr=2) – mplungjan Apr 07 '23 at 12:39
  • 4
    `x**p ≡ x (mod p)` for any integer `x` and prime `p`. [Fermat's little theorem.](https://en.wikipedia.org/wiki/Fermat%27s_little_theorem) Use that. – user2357112 Apr 07 '23 at 12:40
  • 1
    So instead of modularPow(x, y, N) use modularPow(x, (y % phi(N)), N) provided the exponent is small enough to handle normally. https://stackoverflow.com/questions/62668927/eulers-totient-function-in-javascript – Simon Goater Apr 07 '23 at 12:52
  • @PatrykGrzyb can you please write an answer to your own question, providing details about the approach that worked? – MvG Apr 07 '23 at 16:13

1 Answers1

0

Euler's Theorem states that if gcd(a,n) = 1, where gcd() is the greatest common divisor, then

a^(phi(n)) = 1 mod n

where phi() is Euler's Totient function. So, from this we know that any exponent of a can instead be calculated modulo phi(n). Suppose y = w phi(n) + u where 0 <= u < phi(n), then

a^y mod n = a^(w phi(n) + u) mod n = (a^(phi(n))^w)a^u mod n = a^u mod n

Therefore,

gcd(a,n) = 1 => (a^y mod n = a^(y mod phi(n)) mod n)

If y = z^k, with gcd(y,phi(n)) = 1, then

y mod phi(n) = z^(k mod phi(phi(n))) mod phi(n) 

and so on. So for example,

modularPow(5, 2^(10^12), 7) = modularPow(5, modularPow(2, 10^12, 6), 7)

since gcd(5,7) = 1 and phi(7) = 6 but we can't go on to another level in this case because gcd(2,6) = 2. If gcd(a,n) = g where g != 1, then it's a bit trickier. You have to compute

a^y mod (n/g)

and

a^y mod g

separately and then combine the results with the Chinese Remainder Theorem.

Simon Goater
  • 759
  • 1
  • 1
  • 7