Skip to content

Commit b7b2427

Browse files
committed
add Miller–Rabin_primality_tes
1 parent 6a9ad3d commit b7b2427

File tree

4 files changed

+98
-11
lines changed

4 files changed

+98
-11
lines changed

include/imath.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include <stdint.h>
1616
#include <string.h>
17+
#include <limits.h>
1718

1819
namespace alg
1920
{
@@ -67,6 +68,27 @@ namespace alg
6768
}
6869
return result;
6970
}
71+
72+
/**
73+
* Count the consecutive zero bits (trailing) on the right linearly
74+
*/
75+
static int ZerosR(unsigned int v) {
76+
int c; // output: c will count v's trailing zero bits,
77+
// so if v is 1101000 (base 2), then c will be 3
78+
if (v)
79+
{
80+
v = (v ^ (v - 1)) >> 1; // Set v's trailing 0s to 1s and zero rest
81+
for (c = 0; v; c++) {
82+
v >>= 1;
83+
}
84+
}
85+
else
86+
{
87+
c = CHAR_BIT * sizeof(v);
88+
}
89+
90+
return c;
91+
}
7092
}
7193

7294
#endif //

include/prime.h

Lines changed: 64 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,81 @@
88
* PRIME TEST FUNCTION
99
*
1010
* http://en.wikipedia.org/wiki/Primality_test
11+
* http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test
1112
*
1213
******************************************************************************/
1314
#ifndef __PRIME_H__
1415
#define __PRIME_H__
1516

17+
#include <stdlib.h>
18+
#include <math.h>
19+
#include "imath.h"
20+
1621
namespace alg
1722
{
1823
/**
1924
* check whether a given number is a prime number.
25+
* using naive method.
2026
*/
21-
static inline int is_prime(unsigned int n)
27+
static bool test_prime(unsigned int n)
2228
{
23-
unsigned int p;
24-
if (!(n & 1) || n < 2 ) return n == 2;
25-
26-
/* comparing p*p <= n can overflow */
27-
for (p = 3; p <= n/p; p += 2)
28-
if (!(n % p)) return 0;
29-
return 1;
29+
if (n <=1) {
30+
return false;
31+
}
32+
33+
if (n==2) {
34+
return true;
35+
}
36+
37+
unsigned sqrtn = sqrt(n);
38+
for (unsigned int i = 2; i <= sqrtn; ++i) {
39+
if (n % i == 0) {
40+
return false;
41+
}
42+
}
43+
return true;
44+
}
45+
46+
/**
47+
* http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test
48+
*/
49+
static bool miller_rabin_test(unsigned int n) {
50+
switch (n) {
51+
case 0:
52+
case 1:
53+
return false;
54+
}
55+
56+
unsigned s = ZerosR(n-1);
57+
unsigned d = (n-1) >> s;
58+
59+
// test 3-times
60+
for (int k=0;k<3;k++){
61+
unsigned a = rand()%(n-1) + 1;
62+
63+
unsigned x = Exp(a, d, n);
64+
if (x == 1 || x == n - 1) {
65+
continue;
66+
}
67+
68+
for (unsigned i=0;i<s;i++) {
69+
x = Exp(x, 2, n);
70+
if (x == 1) return false;
71+
if (x == n-1) break;
72+
}
73+
}
74+
75+
return true;
76+
}
77+
78+
/**
79+
* mixed implementation
80+
*/
81+
static bool is_prime(unsigned int n) {
82+
if (miller_rabin_test(n)) {
83+
return test_prime(n);
84+
}
85+
return false;
3086
}
3187
}
3288

src/imath_demo.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,7 @@ int main() {
88
printf("%d^%d mod %d = %d\n", i,j,997, alg::Exp(i, j, 997));
99
}
1010
}
11+
12+
unsigned int n = 104;
13+
printf("%x has %d zeros on the right side\n", n, alg::ZerosR(n));
1114
}

src/prime_test.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
#include <stdio.h>
22
#include <prime.h>
3+
#include <time.h>
34

45
using namespace alg;
56
int main()
67
{
7-
int i;
8-
for (i = 0; i<100; i++) {
9-
printf("number: %d, prime %d\n", i, is_prime(i));
8+
unsigned i;
9+
int count = 0;
10+
time_t t1 = time(NULL);
11+
for (i = 1000000000; i<1000100000; i++) {
12+
if (is_prime(i)) count++;
1013
}
14+
15+
time_t t2 = time(NULL);
16+
printf("found %d primes, cost %ld secs\n", count, t2-t1);
1117
return 0;
1218
}

0 commit comments

Comments
 (0)