Skip to content

Commit 263fef6

Browse files
authored
Merge pull request algorithm-visualizer#225 from kopiro/pr-rabinmiller
Added Miller-Rabin primality test
2 parents 4a7fc39 + c62d5c8 commit 263fef6

File tree

4 files changed

+124
-1
lines changed

4 files changed

+124
-1
lines changed

algorithm/category.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@
6262
"number_theory": {
6363
"list": {
6464
"euclidean_algorithm": "Euclidean Algorithm",
65-
"sieve_of_eratosthenes": "Sieve of Eratosthenes"
65+
"sieve_of_eratosthenes": "Sieve of Eratosthenes",
66+
"miller_rabin_primality_test": "Miller-Rabin primality test"
6667
},
6768
"name": "Number Theory"
6869
},
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// Utility function to do modular exponentiation.
2+
// It returns (x^y) % p
3+
function power(x, y, p)
4+
{
5+
var res = 1;
6+
x = x % p;
7+
while (y > 0) {
8+
// If y is odd, multiply x with result
9+
if (y & 1) res = (res*x) % p;
10+
// y must be even now
11+
y = y>>1; // y = y/2
12+
x = (x*x) % p;
13+
}
14+
return res;
15+
}
16+
17+
18+
/**
19+
* Determine if N is prime using Miller-Rabin probabilistic algorithm
20+
* @param {Number} n The number
21+
* @param {Number} k An integer that determine the accuracy of the solution
22+
* @return {Boolean}
23+
*/
24+
function testProbablyPrime(n, k) {
25+
logger._print("==> Testing number " + n);
26+
27+
if (n === 1 || n === 3) {
28+
logger._print("==> Simple case, N is 1 or 3");
29+
return true;
30+
}
31+
if (n % 2 === 0) {
32+
logger._print("==> Simple case, " + n + " mod 2 = 0");
33+
return false;
34+
}
35+
36+
// Write (n - 1) as 2^s * d
37+
var d = n-1;
38+
while (d % 2 === 0) {
39+
d /= 2;
40+
}
41+
logger._print("d = " + d);
42+
43+
// Do 5 iterations if none supplied
44+
k = k || 5;
45+
var P = 100 * (1 - (1/Math.pow(4, k)));
46+
47+
WitnessLoop: do {
48+
logger._print("Remaining iterations: #" + k);
49+
50+
var a = 2 + Math.floor(Math.random() * (n - 4));
51+
logger._print("--> first test with random = " + a);
52+
53+
// Compute a^d % n
54+
var x = power(a, d, n);
55+
56+
if (x === 1 || x === n - 1) {
57+
logger._print("--> continue WitnessLoop, x = 1 or x = n-1");
58+
continue;
59+
}
60+
61+
logger._print("--> second test");
62+
63+
// Keep squaring x while one of the following doesn't
64+
// happen
65+
// (i) d does not reach n-1
66+
// (ii) (x^2) % n is not 1
67+
// (iii) (x^2) % n is not n-1
68+
var i = d;
69+
while (i != n-1) {
70+
x = (x * x) % n;
71+
i *= 2;
72+
73+
if (x == 1) {
74+
logger._print("--> exiting, " + n + " is composite");
75+
return false;
76+
}
77+
78+
if (x == n-1) {
79+
logger._print("--> continue WitnessLoop");
80+
continue WitnessLoop;
81+
}
82+
}
83+
84+
logger._print("--> exiting, " + n + " is composite 'cause (n-1) is reached");
85+
return false;
86+
87+
} while (--k);
88+
89+
logger._print("End of tests, " + n + " is probably prime with probabilty of " + P + "%");
90+
return true;
91+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
var logger = new LogTracer();
2+
3+
var a = Math.floor(Math.random()*300); if (a % 2 === 0) a += 1;
4+
testProbablyPrime(a);
5+
logger._print("----------");
6+
7+
var a = Math.floor(Math.random()*300); if (a % 2 === 0) a += 1;
8+
testProbablyPrime(a);
9+
logger._print("----------");
10+
11+
var a = Math.floor(Math.random()*300); if (a % 2 === 0) a += 1;
12+
testProbablyPrime(a);
13+
logger._print("----------");
14+
15+
testProbablyPrime(151);
16+
logger._print("----------");
17+
18+
testProbablyPrime(199, 10);
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"Miller-Rabin primality test": "Determines whether a given number is prime",
3+
"Complexity": {
4+
"time": "$O(klog^{3}(n)))$",
5+
"probability": "$1 - (1/(4^{k}))$"
6+
},
7+
"References": [
8+
"<a href='https://www.wikiwand.com/en/Miller%E2%80%93Rabin_primality_test'>Wikipedia</a>"
9+
],
10+
"files": {
11+
"basic": "Miller Rabin primality test"
12+
}
13+
}

0 commit comments

Comments
 (0)