Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it

563680 views
1
/* Factoring with Pollard's rho method.
2
3
Copyright 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005 Free Software
4
Foundation, Inc.
5
6
This program is free software; you can redistribute it and/or modify it under
7
the terms of the GNU General Public License as published by the Free Software
8
Foundation; either version 2, or (at your option) any later version.
9
10
This program is distributed in the hope that it will be useful, but WITHOUT ANY
11
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
12
PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
14
You should have received a copy of the GNU General Public License along with
15
this program; see the file COPYING. If not, write to the Free Software
16
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17
18
#include <stdlib.h>
19
#include <stdio.h>
20
#include <string.h>
21
22
#include "gmp.h"
23
24
int flag_verbose = 0;
25
26
static unsigned add[] = {4, 2, 4, 2, 4, 6, 2, 6};
27
28
void
29
factor_using_division (mpz_t t, unsigned int limit)
30
{
31
mpz_t q, r;
32
unsigned long int f;
33
int ai;
34
unsigned *addv = add;
35
unsigned int failures;
36
37
if (flag_verbose)
38
{
39
printf ("[trial division (%u)] ", limit);
40
fflush (stdout);
41
}
42
43
mpz_init (q);
44
mpz_init (r);
45
46
f = mpz_scan1 (t, 0);
47
mpz_div_2exp (t, t, f);
48
while (f)
49
{
50
printf ("2 ");
51
fflush (stdout);
52
--f;
53
}
54
55
for (;;)
56
{
57
mpz_tdiv_qr_ui (q, r, t, 3);
58
if (mpz_cmp_ui (r, 0) != 0)
59
break;
60
mpz_set (t, q);
61
printf ("3 ");
62
fflush (stdout);
63
}
64
65
for (;;)
66
{
67
mpz_tdiv_qr_ui (q, r, t, 5);
68
if (mpz_cmp_ui (r, 0) != 0)
69
break;
70
mpz_set (t, q);
71
printf ("5 ");
72
fflush (stdout);
73
}
74
75
failures = 0;
76
f = 7;
77
ai = 0;
78
while (mpz_cmp_ui (t, 1) != 0)
79
{
80
mpz_tdiv_qr_ui (q, r, t, f);
81
if (mpz_cmp_ui (r, 0) != 0)
82
{
83
f += addv[ai];
84
if (mpz_cmp_ui (q, f) < 0)
85
break;
86
ai = (ai + 1) & 7;
87
failures++;
88
if (failures > limit)
89
break;
90
}
91
else
92
{
93
mpz_swap (t, q);
94
printf ("%lu ", f);
95
fflush (stdout);
96
failures = 0;
97
}
98
}
99
100
mpz_clear (q);
101
mpz_clear (r);
102
}
103
104
void
105
factor_using_division_2kp (mpz_t t, unsigned int limit, unsigned long p)
106
{
107
mpz_t r;
108
mpz_t f;
109
unsigned int k;
110
111
if (flag_verbose)
112
{
113
printf ("[trial division (%u)] ", limit);
114
fflush (stdout);
115
}
116
117
mpz_init (r);
118
mpz_init_set_ui (f, 2 * p);
119
mpz_add_ui (f, f, 1);
120
for (k = 1; k < limit; k++)
121
{
122
mpz_tdiv_r (r, t, f);
123
while (mpz_cmp_ui (r, 0) == 0)
124
{
125
mpz_tdiv_q (t, t, f);
126
mpz_tdiv_r (r, t, f);
127
mpz_out_str (stdout, 10, f);
128
fflush (stdout);
129
fputc (' ', stdout);
130
}
131
mpz_add_ui (f, f, 2 * p);
132
}
133
134
mpz_clear (f);
135
mpz_clear (r);
136
}
137
138
void
139
factor_using_pollard_rho (mpz_t n, int a_int, unsigned long p)
140
{
141
mpz_t x, x1, y, P;
142
mpz_t a;
143
mpz_t g;
144
mpz_t t1, t2;
145
int k, l, c, i;
146
147
if (flag_verbose)
148
{
149
printf ("[pollard-rho (%d)] ", a_int);
150
fflush (stdout);
151
}
152
153
mpz_init (g);
154
mpz_init (t1);
155
mpz_init (t2);
156
157
mpz_init_set_si (a, a_int);
158
mpz_init_set_si (y, 2);
159
mpz_init_set_si (x, 2);
160
mpz_init_set_si (x1, 2);
161
k = 1;
162
l = 1;
163
mpz_init_set_ui (P, 1);
164
c = 0;
165
166
while (mpz_cmp_ui (n, 1) != 0)
167
{
168
S2:
169
if (p != 0)
170
{
171
mpz_powm_ui (x, x, p, n); mpz_add (x, x, a);
172
}
173
else
174
{
175
mpz_mul (x, x, x); mpz_add (x, x, a); mpz_mod (x, x, n);
176
}
177
mpz_sub (t1, x1, x); mpz_mul (t2, P, t1); mpz_mod (P, t2, n);
178
c++;
179
if (c == 20)
180
{
181
c = 0;
182
mpz_gcd (g, P, n);
183
if (mpz_cmp_ui (g, 1) != 0)
184
goto S4;
185
mpz_set (y, x);
186
}
187
S3:
188
k--;
189
if (k > 0)
190
goto S2;
191
192
mpz_gcd (g, P, n);
193
if (mpz_cmp_ui (g, 1) != 0)
194
goto S4;
195
196
mpz_set (x1, x);
197
k = l;
198
l = 2 * l;
199
for (i = 0; i < k; i++)
200
{
201
if (p != 0)
202
{
203
mpz_powm_ui (x, x, p, n); mpz_add (x, x, a);
204
}
205
else
206
{
207
mpz_mul (x, x, x); mpz_add (x, x, a); mpz_mod (x, x, n);
208
}
209
}
210
mpz_set (y, x);
211
c = 0;
212
goto S2;
213
S4:
214
do
215
{
216
if (p != 0)
217
{
218
mpz_powm_ui (y, y, p, n); mpz_add (y, y, a);
219
}
220
else
221
{
222
mpz_mul (y, y, y); mpz_add (y, y, a); mpz_mod (y, y, n);
223
}
224
mpz_sub (t1, x1, y); mpz_gcd (g, t1, n);
225
}
226
while (mpz_cmp_ui (g, 1) == 0);
227
228
mpz_div (n, n, g); /* divide by g, before g is overwritten */
229
230
if (!mpz_probab_prime_p (g, 3))
231
{
232
do
233
{
234
mp_limb_t a_limb;
235
mpn_random (&a_limb, (mp_size_t) 1);
236
a_int = (int) a_limb;
237
}
238
while (a_int == -2 || a_int == 0);
239
240
if (flag_verbose)
241
{
242
printf ("[composite factor--restarting pollard-rho] ");
243
fflush (stdout);
244
}
245
factor_using_pollard_rho (g, a_int, p);
246
}
247
else
248
{
249
mpz_out_str (stdout, 10, g);
250
fflush (stdout);
251
fputc (' ', stdout);
252
}
253
mpz_mod (x, x, n);
254
mpz_mod (x1, x1, n);
255
mpz_mod (y, y, n);
256
if (mpz_probab_prime_p (n, 3))
257
{
258
mpz_out_str (stdout, 10, n);
259
fflush (stdout);
260
fputc (' ', stdout);
261
break;
262
}
263
}
264
265
mpz_clear (g);
266
mpz_clear (P);
267
mpz_clear (t2);
268
mpz_clear (t1);
269
mpz_clear (a);
270
mpz_clear (x1);
271
mpz_clear (x);
272
mpz_clear (y);
273
}
274
275
void
276
factor (mpz_t t, unsigned long p)
277
{
278
unsigned int division_limit;
279
280
if (mpz_sgn (t) == 0)
281
return;
282
283
/* Set the trial division limit according the size of t. */
284
division_limit = mpz_sizeinbase (t, 2);
285
if (division_limit > 1000)
286
division_limit = 1000 * 1000;
287
else
288
division_limit = division_limit * division_limit;
289
290
if (p != 0)
291
factor_using_division_2kp (t, division_limit / 10, p);
292
else
293
factor_using_division (t, division_limit);
294
295
if (mpz_cmp_ui (t, 1) != 0)
296
{
297
if (flag_verbose)
298
{
299
printf ("[is number prime?] ");
300
fflush (stdout);
301
}
302
if (mpz_probab_prime_p (t, 3))
303
mpz_out_str (stdout, 10, t);
304
else
305
factor_using_pollard_rho (t, 1, p);
306
}
307
}
308
309
main (int argc, char *argv[])
310
{
311
mpz_t t;
312
unsigned long p;
313
int i;
314
315
if (argc > 1 && !strcmp (argv[1], "-v"))
316
{
317
flag_verbose = 1;
318
argv++;
319
argc--;
320
}
321
322
mpz_init (t);
323
if (argc > 1)
324
{
325
p = 0;
326
for (i = 1; i < argc; i++)
327
{
328
if (!strncmp (argv[i], "-Mp", 3))
329
{
330
p = atoi (argv[i] + 3);
331
mpz_set_ui (t, 1);
332
mpz_mul_2exp (t, t, p);
333
mpz_sub_ui (t, t, 1);
334
}
335
else if (!strncmp (argv[i], "-2kp", 4))
336
{
337
p = atoi (argv[i] + 4);
338
continue;
339
}
340
else
341
{
342
mpz_set_str (t, argv[i], 0);
343
}
344
345
if (mpz_cmp_ui (t, 0) == 0)
346
puts ("-");
347
else
348
{
349
factor (t, p);
350
puts ("");
351
}
352
}
353
}
354
else
355
{
356
for (;;)
357
{
358
mpz_inp_str (t, stdin, 0);
359
if (feof (stdin))
360
break;
361
mpz_out_str (stdout, 10, t); printf (" = ");
362
factor (t, 0);
363
puts ("");
364
}
365
}
366
367
exit (0);
368
}
369
370