22
33import java .util .Arrays ;
44import java .util .HashMap ;
5+ import java .util .List ;
56import java .util .Map ;
67
8+
9+ /**
10+ * isPrime() using the square root properties
11+ * <p>
12+ * 1 is not a prime. All primes except 2 are odd. All primes greater than 3
13+ * can be written in the form 6k+/-1. Any number n can have only one
14+ * primefactor greater than n . The consequence for primality testing of a
15+ * number n is: if we cannot find a number f less than or equal n that
16+ * divides n then n is prime: the only primefactor of n is n itself
17+ * <br>
18+ * Sieve of Eratosthenes is an another way to check if number is prime.
19+ * <p>
20+ * https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
21+ * <br>
22+ * Miller-Rabin primality test is the fastest way to check if number is prime.
23+ * Regular version of this algorithm returns false when number is composite and true
24+ * when number is probably prime. Here is implemented a deterministic version of this
25+ * algorithm, witnesses are not randomized. Used set of witnesses guarantees that result
26+ * will be correct for sure (not probably) for any number lower than 10^18.
27+ * <p>
28+ * https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test
29+ * <br>
30+ *
31+ * @author Justin Wetherell <[email protected] > 32+ * @author Bartlomiej Drozd <[email protected] > 33+ */
34+
735public class Primes {
836
937 public static final Map <Long , Long > getPrimeFactorization (long number ) {
@@ -34,15 +62,6 @@ public static final Map<Long, Long> getPrimeFactorization(long number) {
3462 return map ;
3563 }
3664
37- /*
38- * isPrime() using the square root properties
39- *
40- * 1 is not a prime. All primes except 2 are odd. All primes greater than 3
41- * can be written in the form 6k+/-1. Any number n can have only one
42- * primefactor greater than n . The consequence for primality testing of a
43- * number n is: if we cannot find a number f less than or equal n that
44- * divides n then n is prime: the only primefactor of n is n itself
45- */
4665 public static final boolean isPrime (long number ) {
4766 if (number == 1 )
4867 return false ;
@@ -52,11 +71,11 @@ public static final boolean isPrime(long number) {
5271 return false ; // short circuit
5372 if (number < 9 )
5473 return true ; // we have already excluded 4, 6 and 8.
55- // (testing for 5 & 7)
74+ // (testing for 5 & 7)
5675 if (number % 3 == 0 )
5776 return false ; // short circuit
5877 long r = (long ) (Math .sqrt (number )); // n rounded to the greatest integer
59- // r so that r*r<=n
78+ // r so that r*r<=n
6079 int f = 5 ;
6180 while (f <= r ) {
6281 if (number % f == 0 )
@@ -80,19 +99,58 @@ public static final boolean sieveOfEratosthenes(int number) {
8099 if (sieve == null || number >= sieve .length ) {
81100 int start = 2 ;
82101 if (sieve == null ) {
83- sieve = new boolean [number + 1 ];
102+ sieve = new boolean [number + 1 ];
84103 } else if (number >= sieve .length ) {
85- sieve = Arrays .copyOf (sieve , number + 1 );
104+ sieve = Arrays .copyOf (sieve , number + 1 );
86105 }
87106
88107 for (int i = start ; i <= Math .sqrt (number ); i ++) {
89108 if (!sieve [i ]) {
90- for (int j = i * 2 ; j <= number ; j += i ) {
109+ for (int j = i * 2 ; j <= number ; j += i ) {
91110 sieve [j ] = true ;
92111 }
93112 }
94113 }
95114 }
96115 return !sieve [number ];
97116 }
117+
118+
119+ public static final boolean millerRabinTest (int number ) {
120+ List <Integer > witnesses = Arrays .asList (2 , 325 , 9375 , 28178 , 450775 , 9780504 , 1795265022 );
121+
122+ if (number == 0 || number == 1 )
123+ return false ;
124+ if (number == 2 || number == 3 )
125+ return true ;
126+
127+ int maximumPowerOf2 = 0 ;
128+ while (((number - 1 ) % Exponentiation .fastRecursiveExponentiation (2 , maximumPowerOf2 )) == 0 )
129+ maximumPowerOf2 ++;
130+ maximumPowerOf2 --;
131+
132+ int d = (number - 1 ) / Exponentiation .fastRecursiveExponentiation (2 , maximumPowerOf2 );
133+
134+ boolean isPrime = true ;
135+
136+ for (int a : witnesses ) {
137+ if (a > number ) break ;
138+ if (Exponentiation .fastRecursiveExponentiationModulo (a , d , number ) != 1 ) {
139+ boolean isLocalPrime = false ;
140+ for (int r = 0 ; r < maximumPowerOf2 ; r ++) {
141+ if (Exponentiation .fastRecursiveExponentiationModulo (a , d * Exponentiation .fastRecursiveExponentiation (2 , r ), number ) == (number - 1 )) {
142+ isLocalPrime = true ;
143+ break ;
144+ }
145+ }
146+ if (!isLocalPrime ) {
147+ isPrime = false ;
148+ break ;
149+ }
150+ }
151+ }
152+
153+
154+ return isPrime ;
155+ }
98156}
0 commit comments