Skip to content

Commit d77d0ed

Browse files
saahil-mahatosedatguzelsemme
authored andcommitted
Add Solovay-Strassen Primality test (TheAlgorithms#10335)
* Add Solovay-Strassen Primality test * fix: resolve comments * refactor: docs change
1 parent e800d9a commit d77d0ed

File tree

1 file changed

+107
-0
lines changed

1 file changed

+107
-0
lines changed

Diff for: maths/solovay_strassen_primality_test.py

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
"""
2+
This script implements the Solovay-Strassen Primality test.
3+
4+
This probabilistic primality test is based on Euler's criterion. It is similar
5+
to the Fermat test but uses quadratic residues. It can quickly identify
6+
composite numbers but may occasionally classify composite numbers as prime.
7+
8+
More details and concepts about this can be found on:
9+
https://en.wikipedia.org/wiki/Solovay%E2%80%93Strassen_primality_test
10+
"""
11+
12+
13+
import random
14+
15+
16+
def jacobi_symbol(random_a: int, number: int) -> int:
17+
"""
18+
Calculate the Jacobi symbol. The Jacobi symbol is a generalization
19+
of the Legendre symbol, which can be used to simplify computations involving
20+
quadratic residues. The Jacobi symbol is used in primality tests, like the
21+
Solovay-Strassen test, because it helps determine if an integer is a
22+
quadratic residue modulo a given modulus, providing valuable information
23+
about the number's potential primality or compositeness.
24+
25+
Parameters:
26+
random_a: A randomly chosen integer from 2 to n-2 (inclusive)
27+
number: The number that is tested for primality
28+
29+
Returns:
30+
jacobi_symbol: The Jacobi symbol is a mathematical function
31+
used to determine whether an integer is a quadratic residue modulo
32+
another integer (usually prime) or not.
33+
34+
>>> jacobi_symbol(2, 13)
35+
-1
36+
>>> jacobi_symbol(5, 19)
37+
1
38+
>>> jacobi_symbol(7, 14)
39+
0
40+
"""
41+
42+
if random_a in (0, 1):
43+
return random_a
44+
45+
random_a %= number
46+
t = 1
47+
48+
while random_a != 0:
49+
while random_a % 2 == 0:
50+
random_a //= 2
51+
r = number % 8
52+
if r in (3, 5):
53+
t = -t
54+
55+
random_a, number = number, random_a
56+
57+
if random_a % 4 == number % 4 == 3:
58+
t = -t
59+
60+
random_a %= number
61+
62+
return t if number == 1 else 0
63+
64+
65+
def solovay_strassen(number: int, iterations: int) -> bool:
66+
"""
67+
Check whether the input number is prime or not using
68+
the Solovay-Strassen Primality test
69+
70+
Parameters:
71+
number: The number that is tested for primality
72+
iterations: The number of times that the test is run
73+
which effects the accuracy
74+
75+
Returns:
76+
result: True if number is probably prime and false
77+
if not
78+
79+
>>> random.seed(10)
80+
>>> solovay_strassen(13, 5)
81+
True
82+
>>> solovay_strassen(9, 10)
83+
False
84+
>>> solovay_strassen(17, 15)
85+
True
86+
"""
87+
88+
if number <= 1:
89+
return False
90+
if number <= 3:
91+
return True
92+
93+
for _ in range(iterations):
94+
a = random.randint(2, number - 2)
95+
x = jacobi_symbol(a, number)
96+
y = pow(a, (number - 1) // 2, number)
97+
98+
if x == 0 or y != x % number:
99+
return False
100+
101+
return True
102+
103+
104+
if __name__ == "__main__":
105+
import doctest
106+
107+
doctest.testmod()

0 commit comments

Comments
 (0)