def is_primitive_root(a, p): """ Returns True if ``a`` is a primitive root of ``p`` ``a`` is said to be the primitive root of ``p`` if gcd(a, p) == 1 and totient(p) is the smallest positive number s.t. a**totient(p) cong 1 mod(p) Examples ======== >>> from sympy.ntheory import is_primitive_root, n_order, totient >>> is_primitive_root(3, 10) True >>> is_primitive_root(9, 10) False >>> n_order(3, 10) == totient(10) True >>> n_order(9, 10) == totient(10) False """ a, p = int_tested(a, p) if igcd(a, p) != 1: raise ValueError("The two numbers should be relatively prime") if a > p: a = a % p if n_order(a, p) == totient(p): return True else: return False
def n_order(a, n): """Returns the order of ``a`` modulo ``n``. The order of ``a`` modulo ``n`` is the smallest integer ``k`` such that ``a**k`` leaves a remainder of 1 with ``n``. Examples ======== >>> from sympy.ntheory import n_order >>> n_order(3, 7) 6 >>> n_order(4, 7) 3 """ a, n = int_tested(a, n) if igcd(a, n) != 1: raise ValueError("The two numbers should be relatively prime") group_order = totient(n) factors = factorint(group_order) order = 1 if a > n: a = a % n for p, e in factors.iteritems(): exponent = group_order for f in xrange(0, e + 1): if (a ** (exponent)) % n != 1: order *= p ** (e - f + 1) break exponent = exponent // p return order