Lab 13 : Modular Exponentiation¶
In this lab, we will implement modular exponentiation and experiment with the difficulty of finding roots modulo n.
0 Preliminaries¶
To run doctests, add the following to the bottom of your file:
if (__name__ == '__main__'):
import doctest
doctest.testmod(optionflags= doctest.NORMALIZE_WHITESPACE)
1 Slow exponentiation¶
Exercise 1 Write a function which computes exponentiation by repeated multiplication.
def slow_exp(x, e):
"""
Assume e is a non-negative integer.
>>> slow_exp(2, 10)
1024
"""
Exercise 2 Run your function from Exercise 2 on inputs which take many seconds to a minute to compute. When you do this, assign the output to a variable (i.e. >>> out = slow_exp(..., ...)
, so that the slowness will not simply be due to printing a large number in the interaction buffer. (Include these tests as comments in your file for your instructor to see.)
2 Binary representation¶
Exercise 3 Write a function which takes a non-negative number and returns a string of 0s and 1s which represent that number in binary. Do not use bin
or the like.
def bin_rep(n):
"""
Assume that n is a non-negative integer.
>>> bin_rep(12345)
'11000000111001'
"""
3 Square and multiply¶
We can significantly reduce the number of steps computing exponentiation by using repeated squaring as opposed to repeated multiplication. The key insight is that if the exponent e is even then \(x^e = (x^2)^{\frac{e}{2}}\); and if the exponent e is odd then \(x^e = x(x^2)^{\frac{e-1}{2}}\).
- If we further convert the exponent to binary, we can exponentiate using the following algorithm:
- Initialize
result = 1
. - If there are no remaining bits in the exponent, return
result
. - Read the next bit
b
of the exponent (left-to-right). - If
b
is 1,result = x * result * result
. - If
b
is 0,result = result * result
. - Goto 2.
- Initialize
Exercise 4 Write a function which computes exponentiation by the square and multiply algorithm.
def sqr_and_mult(x, e):
"""
Assume e is a non-negative integer.
>>> sqr_and_mult(10, 3)
1000
>>> sqr_and_mult(2, 10)
1024
>>> sqr_and_mult(2, 12)
4096
"""
4 Modular square and multiply¶
Exercise 5 Write a function which computes modular exponentiation by the modular square and multiply algorithm.
def sqr_and_mult_mod(x, e, n):
"""
Assume e is a non-negative integer.
>>> sqr_and_mult_mod(2, 5, 64)
32
>>> sqr_and_mult_mod(2, 6, 64)
0
"""
5 Brute force modular root finding¶
Exercise 6 Write a function which given a number c, a modulus n and an exponent e, tries to find m such that \(m^e \equiv c \pmod{n}\).
def slow_root_mod(e, c, n):
"""
>>> slow_root_mod(5, 32, 119)
2
>>> slow_root_mod(4, 81, 77)
3
"""
Exercise 7 Run your function from Exercise 6 on inputs which take many seconds to minutes to compute. For added realism, try taking n to be the product of two primes, and choose e so that it’s somewhat less than n. (Include these tests as comments in your file for your instructor to see.)