def pow_int(self, a, m): a = int_check_strict(a, ZN_ERR_MSG_NUM) m = int_check_strict(m, ZN_ERR_MSG_EXP, ZN_COND_EXP) n = self.n a %= n result = 1 while m > 0: if m % 2 == 1: result *= a if result >= n: result %= n m //= 2 a *= a if a >= n: a %= n return result
def input_int(self, msg, err_msg, cond = lambda x: True): while True: try: x = float(input(msg)) x = int_check_strict(x, None, cond) except ValueError: print(err_msg) continue else: print('--- Received: {}'.format(x)) return x
def totient(n): # Hàm phi Euler """ Euler's totient function """ n = int_check_strict(n, ZN_ERR_MSG_N, ZN_COND_N) phi = n for i in range(2, int(n ** .5) + 1): # +1 after sqrt to ensure it is included in the range if n % i == 0: phi -= phi / i while n % i == 0: n //= i if n > 1: # Either n is prime in the first place or n is now the last prime factor > sqrt(n) phi -= phi / n return int(phi)
def mul_inv_int(self, num, mode = 'bezout'): num = int_check_strict(num, ZN_ERR_MSG_NUM) n = self.n g = gcd(num, n) if g > 1: return ZN_ERR_MSG_INV.format(a = num, n = n, gcd = g) if mode == 'bezout': _, inv, _ = bezout(num % n, n) return inv % n elif mode == 'euler': return self.pow_int(num, self.totient() - 1) else: raise ValueError
def __pow__(self, m): m = int_check_strict(m, ZN_ERR_MSG_EXP, ZN_COND_EXP) n = self.n a = self.reduced result = 1 while m > 0: if m % 2 == 1: result *= a if result >= n: result %= n m //= 2 a *= a if a >= n: a %= n return ZnNumber(result, n)
def reduce(val, base_n): n = int_check_strict(base_n, ZN_ERR_MSG_N, ZN_COND_N) val = int_check_strict(val, ZN_ERR_MSG_NUM) return val % n
def mul_int(self, a, b): a = int_check_strict(a, ZN_ERR_MSG_NUM) b = int_check_strict(b, ZN_ERR_MSG_NUM) original_product = a * b return self.reduce(original_product), original_product
def add_int(self, a, b): a = int_check_strict(a, ZN_ERR_MSG_NUM) b = int_check_strict(b, ZN_ERR_MSG_NUM) original_sum = a + b return self.reduce(original_sum), original_sum
def reduce(self, num): num = int_check_strict(num, ZN_ERR_MSG_NUM) return num % self.n
def __init__(self, n): n = int_check_strict(n, ZN_ERR_MSG_N, ZN_COND_N) self.n = n