# Extended Euclidean algorithm (builtin)
# xgcd(a,b) returns a triple, where the first number is gcd, and the
# next two numbers are coefficients c,d such that ac + bd =1
xgcd(3,5)
3*2 + 5*(-1)
# modular exponentiation is important for public key cryptography
(2^5) % 19
(17^100000) % 19 # this works, but if 100000 is replaced by a huge number, an error will occur
def exp_mod_slow(a,e,b):
"""Return (a^e) % b, reducing at every stage."""
prod = 1
for i in range(e):
prod = (prod*a) % b # reduce at every stage, rather than just at end
return prod
# runtime (for fixed a,b) is about e, which exponential in number of digits of e
exp_mod_slow(17,10000,19)
# In-class Exercise: compute a^(2^n) mod b
def exp_mod_powtwo(a,n,b):
"""Returns a^(2^n) % b, using the repeated squaring method."""
prod = a
for i in range(n):
prod = (prod)^2 % b
return prod
#runtime (for fixed a,b) is about n (exp_mod_slow would take time 2^n)
exp_mod_powtwo(3,1000,23) # fast even to compute 3^(2^1000) mod 23
bin(235) # builtin function outputs binary expansion; ignore first two characters of output
# kth bit of binary expansion of 235
k=1
bin(235)[-1-k]
length = len(bin(235))-2
bin(235)[-1-(length-1)] # gets the highest bit in binary expansion
def exp_mod(a,e,b):
"""Return a^e % b, computed using repeated squaring."""
bin_rep=bin(e) # first find binary representation of e
prod = 1
cur_pow_two = a # this will run through a^(2^0), a^(2^1), a^(2^2),...
for i in range(len(bin_rep)-2):
if bin_rep[-1-i]=='1':
prod = prod * cur_pow_two % b # multiply by cur_pow_two if the corresponding bit is 1
cur_pow_two = (cur_pow_two)^2 % b
return prod
# runtime (for fixed a,b) is approx number of bits of e
exp_mod(2,10,18)
exp_mod(2,10000000,19) # this is very fast
exp_mod_slow(2,10000000,19) # takes several seconds
exp_mod(3, 3^1000 + 17^1000, 23) # very fast; this would produce an error with exp_mod_slow
# Fermat's little theorem: a^(p-1) mod p = 1
# if p prime, and a is not a multiple of p
# Example
exp_mod(3,16,17)
# Euler's theorem: a^(phi(n)) = 1 mod n,
# n is any number, a relatively prime to n
# What is phi(n)? (For n prime, phi(n)=n-1)
# phi(n) = # of positive integer less than n
# that are relatively prime to n
# Example: phi(10) = 4
exp_mod(3,4,10)