#!/usr/bin/env python3 def gcd(a, b): """ This function calculate the GCD (Greatest Common Divisor of the number a of b Args: a (Integer): the number a b (integer): the number b Return: the GCD """ if b == 0: return a return gcd(b, a%b) def egcd(a, b): """ This function compute the Extended Euclidean algorithm https://user.eng.umd.edu/~danadach/Cryptography_20/ExtEuclAlg.pdf https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm Args: a (Integer): the number a b (Integer): the number b """ if a == 0: return b, 0, 1 gcd, x1, y1 = egcd(b % a, a) x = y1 - (b // a) * x1 y = x1 return gcd, x, y def bin_expo(n, e) -> int: """ This function perform an binary exponentiation, also known as Exponentiation squaring. A binary exponentiation is the process for computing an integer power of a number, such as a ** n. For doing that, the first step is to convert the exponent into a binary representation And for each 1 bit, we compute the exponent. Args: n (Integer): it's the base e (Integer): it's the exponent Returns: Return the result of the exponentation of n ** e """ binary = bin(e)[2:] # Remove the prefix 0b r = 1 exp = 1 # We need to reverse, and to start from the right to left # Otherwise, we do on left to the right # It's dirty, maybe we can find another way to do that for b in binary[::-1]: if b == '1': r *= n ** exp print(n ** exp, exp) exp *= 2 return r def exponent_squaring(n, e): """ This function perform an exponentiation squaring, which compute an integer power of a number based on the following algorithm: n ** e = { 1 # if n is 0 (n ** (e / 2)) ** 2 # if n is even ((n ** (e - 1 / 2)) ** 2) * n # if n is odd } Args: n (Integer): n is the base of n ** e e (Integer): e is the exponent """ if e < 0: return exponent_squaring(1 / n, -e) elif e == 0: return 1 elif e % 2 == 1: # n is odd return exponent_squaring(n * n, (e - 1) / 2) * n elif e % 2 == 0: # n is even return exponent_squaring(n * n, e / 2)