Skip to content

Commit 36df926

Browse files
committed
Implemented arbitrary-sized Pollard Rho function and added test program.
1 parent 1f0ebae commit 36df926

File tree

6 files changed

+106
-7
lines changed

6 files changed

+106
-7
lines changed

src/Common.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#include "Common.h"
44

55
namespace Math {
6-
bool isPropPrime(mpz_t n) {
6+
bool isPropPrime(const mpz_t n) {
77
return mpz_probab_prime_p(n, 10) > 0;
88
}
99

src/Common.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#include <string>
66

77
namespace Math {
8-
bool isPropPrime(mpz_t n);
8+
bool isPropPrime(const mpz_t n);
99
bool isPropPrime(int n);
1010
void dump(mpz_t n, std::string msg = "", bool newline = true);
1111
}

src/PollardRho.cpp

+52-4
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,61 @@
77
namespace Math {
88
namespace Fac {
99
namespace {
10-
int fI(int x, int a, int n) {
10+
void func(mpz_t r, const mpz_t x, const mpz_t a, const mpz_t n) {
11+
mpz_mul(r, x, x);
12+
mpz_add(r, r, a);
13+
mpz_mod(r, r, n);
14+
}
15+
16+
int funcI(int x, int a, int n) {
1117
return mod(x * x + a, n);
1218
}
1319
}
20+
21+
void pollardRho(const mpz_t n, mpz_t f) {
22+
// Return n as the factor if it's a probable-prime.
23+
if (isPropPrime(n)) {
24+
mpz_set(f, n);
25+
return;
26+
}
27+
28+
mpz_t a, s, g, u, v, one, zero, tmp;
29+
mpz_inits(a, s, g, u, v, one, zero, tmp, NULL);
30+
mpz_set_ui(zero, 0);
31+
mpz_set_ui(one, 1);
32+
mpz_sub_ui(tmp, n, 3);
33+
randRange(a, one, tmp); // a in [1, n - 3]
34+
35+
mpz_sub_ui(tmp, n, 1);
36+
randRange(s, zero, tmp); // s in [0, n - 1]
37+
38+
// u = v = s
39+
mpz_set(u, s);
40+
mpz_set(v, s);
41+
42+
do {
43+
func(u, u, a, n);
44+
func(v, v, a, n);
45+
func(v, v, a, n);
46+
47+
// g = gcd((u - v) mod n, n)
48+
mpz_sub(tmp, u, v);
49+
mpz_mod(tmp, tmp, n);
50+
mpz_gcd(g, tmp, n);
51+
} while (mpz_cmp(g, one) == 0);
52+
53+
// Failed: g == n
54+
if (mpz_cmp(g, n) == 0) {
55+
mpz_clears(a, s, g, u, v, one, zero, tmp, NULL);
56+
pollardRho(n, f);
57+
}
58+
59+
// Found factor.
60+
mpz_set(f, g);
61+
mpz_clears(a, s, g, u, v, one, zero, tmp, NULL);
62+
}
1463

1564
int pollardRhoI(int n) {
16-
// Return n if n is a probable-prime.
1765
if (isPropPrime(n)) return n;
1866

1967
Random rnd;
@@ -24,8 +72,8 @@ namespace Math {
2472
u = v = s;
2573

2674
do {
27-
u = fI(u, a, n);
28-
v = fI(fI(v, a, n), a, n);
75+
u = funcI(u, a, n);
76+
v = funcI(funcI(v, a, n), a, n);
2977
g = gcd(mod(u - v, n), n);
3078
} while (g == 1);
3179

src/PollardRho.h

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
11
#ifndef MATH_POLLARD_RHO_H
22
#define MATH_POLLARD_RHO_H
33

4+
#include <gmp.h>
5+
46
namespace Math {
57
namespace Fac {
68
namespace {
7-
int fI(int x, int a, int n);
9+
void func(mpz_t r, const mpz_t x, const mpz_t a, const mpz_t n);
10+
int funcI(int x, int a, int n);
811
}
912

13+
/**
14+
* Finds a nontrivial factor of composite number n of arbitrary
15+
* size and writes the result to f.
16+
*/
17+
void pollardRho(const mpz_t n, mpz_t f);
18+
1019
/**
1120
* Finds a nontrivial factor of composite number n.
1221
*/

test/CMakeLists.txt

+3
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,6 @@ INCLUDE_DIRECTORIES( ${PROJECT_SOURCE_DIR}/src )
99
ADD_EXECUTABLE( PollardRhoI PollardRhoI.cpp )
1010
TARGET_LINK_LIBRARIES( PollardRhoI ${CORELIBS} )
1111

12+
ADD_EXECUTABLE( PollardRho PollardRho.cpp )
13+
TARGET_LINK_LIBRARIES( PollardRho ${CORELIBS} )
14+

test/PollardRho.cpp

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#include <gmp.h>
2+
#include <sstream>
3+
#include <iostream>
4+
using namespace std;
5+
6+
#include "Common.h"
7+
#include "PollardRho.h"
8+
using namespace Math;
9+
using namespace Math::Fac;
10+
11+
#include "TestCommon.h"
12+
13+
void usage(char **argv) {
14+
cout << "Usage: " << argv[0] << " <num>" << endl
15+
<< "Find a nontrivial prime factor of <num>." << endl;
16+
}
17+
18+
int main(int argc, char **argv) {
19+
if (argc != 2) {
20+
usage(argv);
21+
return -1;
22+
}
23+
24+
mpz_t num, g;
25+
mpz_init(num);
26+
if (mpz_set_str(num, argv[1], 10) == -1) {
27+
mpz_clear(num);
28+
usage(argv);
29+
return -1;
30+
}
31+
32+
mpz_init(g);
33+
pollardRho(num, g);
34+
dump(num, "A factor of", false);
35+
dump(g, " is");
36+
37+
mpz_clears(num, g, NULL);
38+
return 0;
39+
}

0 commit comments

Comments
 (0)