def fibonacci_primitive_roots(p): """Returns a sorted list of the Fibonacci primitive roots mod p. Input: * p: int A prime number. The primality of p is not verified. Returns: * roots: list This is a list of the Fibonacci primitive roots mod p. This list will contain no more than 2 elements. Examples: >>> fibonacci_primitive_roots(11) [8] >>> fibonacci_primitive_roots(19) [15] >>> fibonacci_primitive_roots(41) [7, 35] Details: A Fibonacci primitive root mod p is a primitive root satisfying g**2 = g + 1. These can only exist for primes p = 1, 9 (mod 10). See the paper "Fibonacci Primitive Roots" by Shanks for details. """ if p % 2 == 0: return [] if p == 5: return [3] if p < 5 or jacobi_symbol(5, p) != 1: return [] sqrts = sqrts_mod_p(5, p) inverse = inverse_mod(2, p) quad_roots = [(1 + root) * inverse % p for root in sqrts] phi_divisors = factor.prime_divisors(p - 1) roots = [] for r in quad_roots: if is_primitive_root(r, p, phi=p - 1, phi_divisors=phi_divisors): roots.append(r) return sorted(roots)
def fibonacci_primitive_roots(p): """Returns a sorted list of the Fibonacci primitive roots mod p. Input: * p: int A prime number. The primality of p is not verified. Returns: * roots: list This is a list of the Fibonacci primitive roots mod p. This list will contain no more than 2 elements. Examples: >>> fibonacci_primitive_roots(11) [8] >>> fibonacci_primitive_roots(19) [15] >>> fibonacci_primitive_roots(41) [7, 35] Details: A Fibonacci primitive root mod p is a primitive root satisfying g**2 = g + 1. These can only exist for primes p = 1, 9 (mod 10). See the paper "Fibonacci Primitive Roots" by Shanks for details. """ if p % 2 == 0: return [] if p == 5: return [3] if p < 5 or jacobi_symbol(5, p) != 1: return [] sqrts = sqrts_mod_p(5, p) inverse = inverse_mod(2, p) quad_roots = [(1 + root)*inverse % p for root in sqrts] phi_divisors = factor.prime_divisors(p - 1) roots = [] for r in quad_roots: if is_primitive_root(r, p, phi=p - 1, phi_divisors=phi_divisors): roots.append(r) return sorted(roots)
def primitive_root(n, n_factorization=None, phi=None, phi_divisors=None): """Returns a primitive root modulo n. Given a positive integer n of the form n = 2, 4, p**a, or 2*p**a for p an odd prime and a >= 1, this function returns the least primitive root of n. Input: * n: int (n > 1) * n_factorization: list (default=None) The prime factorization of n. * phi: int (default=None) The value of euler_phi(n). * phi_divisors: list (default=None) A list of the prime divisors of euler_phi(n). Returns: * g: int The least primitive root of n. Raises: * ValueError: if primitive roots don't exist modulo n. Examples: >>> primitive_root(7) 3 >>> primitive_root(11) 2 >>> primitive_root(14) 3 >>> primitive_root(12) Traceback (most recent call last): ... ValueError: primitive_root: No primitive root for n. Details: An integer a is called a primitive root mod n if a generates the multiplicative group of units modulo n. Equivalently, a is a primitive root modulo n if the order of a modulo m is euler_phi(n). As noted above, primitive roots only exist for moduli of the form n = 2, 4, p**a, 2*p**a, where p > 2 is prime, and a >= 1. See Theorem 6.11 of "Elementary Number Theory" by Jones and Jones for a proof of this fact. See also Chapter 10 of "Introduction to Analytic Number Theory" by Apostol. This method uses the fact that an integer a coprime to n is a primitive root if and only if a**(euler_phi(n)/p) != 1 (mod n) for each prime p dividing euler_phi(n). See Lemma 6.4 in Jones and Jones for a proof of this. Note also that there is another way to construct primitive roots for composite moduli. To find a primitive root modulu p**a for p an odd prime and a >= 2, first compute g, a primitive root modulo p using the above criteria. Next, compute g1 = g**(p - 1) (mod p**2). If g1 != 1, then g is a primitive root modulo p**a for every a >= 1. Otherwise, g + p is. Finally, note that when p is an odd prime, if g is a primitive root modulo p**a, then either g or g + p**a (whichever is odd) is a primitive root modulo 2*p**a. See Lemma 1.4.5 of "A Course in Computational Algebraic Number Theory" by Cohen for more details. """ if n_factorization is None: n_factorization = factor.factor(n) if n % 4 == 0 and n != 4: raise ValueError("primitive_root: No primitive root for n.") if len(n_factorization) > 2: raise ValueError("primitive_root: No primitive root for n.") if n % 2 == 1 and len(n_factorization) > 1: raise ValueError("primitive_root: No primitive root for n.") if phi is None: phi = functions.euler_phi(n_factorization) if phi_divisors is None: phi_divisors = factor.prime_divisors(phi) for g in xrange(1, n): if is_primitive_root(g, n, phi=phi, phi_divisors=phi_divisors): return g
def is_primitive_root(a, n, phi=None, phi_divisors=None): """Returns True if a is a primitive root mod n and False otherwise. Given an integer a and modulus n, this method determines whether or not a is a primitive root modulo n. Input: * a: int * n: int (n > 0) The modulus. * phi: int (default=None) Value of euler_phi(n). * phi_divisors: list (default=None) List of prime divisors of euler_phi(n). Returns: * b: bool b is True if a is a primitive root mod n and False otherwise. Note that b will be False when no primitive roots exist modulo n. Raises: * ValueError: if n <= 1. Examples: >>> is_primitive_root(2, 11) True >>> is_primitive_root(3, 11) False >>> is_primitive_root(3, -2) Traceback (most recent call last): ... ValueError: is_primitive_root: n must be >= 2. Details: An integer a is called a primitive root mod n if a generates the multiplicative group of units modulo n. Equivalently, a is a primitive root modulo n if the order of a modulo m is euler_phi(n). The algorithm is based on the observation that an integer a coprime to n is a primitive root modulo n if and only if a**(euler_phi(n)/d) != 1 (mod n) for each divisor d of euler_phi(n). See Lemma 6.4 of "Elementary Number Theory" by Jones and Jones for a proof. Primitive roots exist only for the moduli n = 1, 2, 4, p**a, and 2*p**a, where p is an odd prime and a >= 1. These cases are captured in the above Lemma, however some simple divisibility tests allow us to exit early for certain moduli. See Chapter 6 of "Elementary Number Theory" by Jones and Jones for more details. See also Chapter 10 of "Introduction to Analytic Number Theory" by Apostol. """ if n <= 1: raise ValueError("is_primitive_root: n must be >= 2.") if n > 4 and n % 4 == 0: return False if gcd(a, n) != 1: return False if phi is None: phi = functions.euler_phi(n) if phi_divisors is None: phi_divisors = factor.prime_divisors(phi) for d in phi_divisors: if pow(a, phi // d, n) == 1: return False return True
def is_primitive_root(a, n, phi=None, phi_divisors=None): """Returns True if a is a primitive root mod n and False otherwise. Given an integer a and modulus n, this method determines whether or not a is a primitive root modulo n. Input: * a: int * n: int (n > 0) The modulus. * phi: int (default=None) Value of euler_phi(n). * phi_divisors: list (default=None) List of prime divisors of euler_phi(n). Returns: * b: bool b is True if a is a primitive root mod n and False otherwise. Note that b will be False when no primitive roots exist modulo n. Raises: * ValueError: if n <= 1. Examples: >>> is_primitive_root(2, 11) True >>> is_primitive_root(3, 11) False >>> is_primitive_root(3, -2) Traceback (most recent call last): ... ValueError: is_primitive_root: n must be >= 2. Details: An integer a is called a primitive root mod n if a generates the multiplicative group of units modulo n. Equivalently, a is a primitive root modulo n if the order of a modulo m is euler_phi(n). The algorithm is based on the observation that an integer a coprime to n is a primitive root modulo n if and only if a**(euler_phi(n)/d) != 1 (mod n) for each divisor d of euler_phi(n). See Lemma 6.4 of "Elementary Number Theory" by Jones and Jones for a proof. Primitive roots exist only for the moduli n = 1, 2, 4, p**a, and 2*p**a, where p is an odd prime and a >= 1. These cases are captured in the above Lemma, however some simple divisibility tests allow us to exit early for certain moduli. See Chapter 6 of "Elementary Number Theory" by Jones and Jones for more details. See also Chapter 10 of "Introduction to Analytic Number Theory" by Apostol. """ if n <= 1: raise ValueError("is_primitive_root: n must be >= 2.") if n > 4 and n % 4 == 0: return False if gcd(a, n) != 1: return False if phi is None: phi = functions.euler_phi(n) if phi_divisors is None: phi_divisors = factor.prime_divisors(phi) for d in phi_divisors: if pow(a, phi//d, n) == 1: return False return True