forked from keon/algorithms
-
Notifications
You must be signed in to change notification settings - Fork 0
/
find_primitive_root_simple.py
71 lines (67 loc) · 2.2 KB
/
find_primitive_root_simple.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import math
"""
For positive integer n and given integer a that satisfies gcd(a, n) = 1,
the order of a modulo n is the smallest positive integer k that satisfies
pow (a, k) % n = 1. In other words, (a^k) ≡ 1 (mod n).
Order of certain number may or may not be exist. If so, return -1.
"""
def find_order(a, n):
if ((a == 1) & (n == 1)):
return 1
""" Exception Handeling :
1 is the order of of 1 """
else:
if (math.gcd(a, n) != 1):
print ("a and n should be relative prime!")
return -1
else:
for i in range(1, n):
if (pow(a, i) % n == 1):
return i
return -1
"""
Euler's totient function, also known as phi-function ϕ(n),
counts the number of integers between 1 and n inclusive,
which are coprime to n.
(Two numbers are coprime if their greatest common divisor (GCD) equals 1).
Code from /algorithms/maths/euler_totient.py, written by 'goswami-rahul'
"""
def euler_totient(n):
"""Euler's totient function or Phi function.
Time Complexity: O(sqrt(n))."""
result = n;
for i in range(2, int(n ** 0.5) + 1):
if n % i == 0:
while n % i == 0:
n //= i
result -= result // i
if n > 1:
result -= result // n;
return result;
"""
For positive integer n and given integer a that satisfies gcd(a, n) = 1,
a is the primitive root of n, if a's order k for n satisfies k = ϕ(n).
Primitive roots of certain number may or may not be exist.
If so, return empty list.
"""
def find_primitive_root(n):
if (n == 1):
return [0]
""" Exception Handeling :
0 is the only primitive root of 1 """
else:
phi = euler_totient(n)
p_root_list = []
""" It will return every primitive roots of n. """
for i in range (1, n):
if (math.gcd(i, n) != 1):
continue
""" To have order, a and n must be
relative prime with each other. """
else:
order = find_order(i, n)
if (order == phi):
p_root_list.append(i)
else:
continue
return p_root_list