CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

| Download

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

Views: 418346
1
/* Factoring with Pollard's rho method.
2
3
Copyright 1995, 1997-2003, 2005, 2009, 2012 Free Software Foundation, Inc.
4
5
This program is free software; you can redistribute it and/or modify it under
6
the terms of the GNU General Public License as published by the Free Software
7
Foundation; either version 3 of the License, or (at your option) any later
8
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. If not, see https://www.gnu.org/licenses/. */
16
17
18
#include <stdlib.h>
19
#include <stdio.h>
20
#include <string.h>
21
#include <inttypes.h>
22
23
#include "gmp.h"
24
25
static unsigned char primes_diff[] = {
26
#define P(a,b,c) a,
27
#include "primes.h"
28
#undef P
29
};
30
#define PRIMES_PTAB_ENTRIES (sizeof(primes_diff) / sizeof(primes_diff[0]))
31
32
int flag_verbose = 0;
33
34
/* Prove primality or run probabilistic tests. */
35
int flag_prove_primality = 1;
36
37
/* Number of Miller-Rabin tests to run when not proving primality. */
38
#define MR_REPS 25
39
40
struct factors
41
{
42
mpz_t *p;
43
unsigned long *e;
44
long nfactors;
45
};
46
47
void factor (mpz_t, struct factors *);
48
49
void
50
factor_init (struct factors *factors)
51
{
52
factors->p = malloc (1);
53
factors->e = malloc (1);
54
factors->nfactors = 0;
55
}
56
57
void
58
factor_clear (struct factors *factors)
59
{
60
int i;
61
62
for (i = 0; i < factors->nfactors; i++)
63
mpz_clear (factors->p[i]);
64
65
free (factors->p);
66
free (factors->e);
67
}
68
69
void
70
factor_insert (struct factors *factors, mpz_t prime)
71
{
72
long nfactors = factors->nfactors;
73
mpz_t *p = factors->p;
74
unsigned long *e = factors->e;
75
long i, j;
76
77
/* Locate position for insert new or increment e. */
78
for (i = nfactors - 1; i >= 0; i--)
79
{
80
if (mpz_cmp (p[i], prime) <= 0)
81
break;
82
}
83
84
if (i < 0 || mpz_cmp (p[i], prime) != 0)
85
{
86
p = realloc (p, (nfactors + 1) * sizeof p[0]);
87
e = realloc (e, (nfactors + 1) * sizeof e[0]);
88
89
mpz_init (p[nfactors]);
90
for (j = nfactors - 1; j > i; j--)
91
{
92
mpz_set (p[j + 1], p[j]);
93
e[j + 1] = e[j];
94
}
95
mpz_set (p[i + 1], prime);
96
e[i + 1] = 1;
97
98
factors->p = p;
99
factors->e = e;
100
factors->nfactors = nfactors + 1;
101
}
102
else
103
{
104
e[i] += 1;
105
}
106
}
107
108
void
109
factor_insert_ui (struct factors *factors, unsigned long prime)
110
{
111
mpz_t pz;
112
113
mpz_init_set_ui (pz, prime);
114
factor_insert (factors, pz);
115
mpz_clear (pz);
116
}
117
118
119
void
120
factor_using_division (mpz_t t, struct factors *factors)
121
{
122
mpz_t q;
123
unsigned long int p;
124
int i;
125
126
if (flag_verbose > 0)
127
{
128
printf ("[trial division] ");
129
}
130
131
mpz_init (q);
132
133
p = mpz_scan1 (t, 0);
134
mpz_div_2exp (t, t, p);
135
while (p)
136
{
137
factor_insert_ui (factors, 2);
138
--p;
139
}
140
141
p = 3;
142
for (i = 1; i <= PRIMES_PTAB_ENTRIES;)
143
{
144
if (! mpz_divisible_ui_p (t, p))
145
{
146
p += primes_diff[i++];
147
if (mpz_cmp_ui (t, p * p) < 0)
148
break;
149
}
150
else
151
{
152
mpz_tdiv_q_ui (t, t, p);
153
factor_insert_ui (factors, p);
154
}
155
}
156
157
mpz_clear (q);
158
}
159
160
static int
161
mp_millerrabin (mpz_srcptr n, mpz_srcptr nm1, mpz_ptr x, mpz_ptr y,
162
mpz_srcptr q, unsigned long int k)
163
{
164
unsigned long int i;
165
166
mpz_powm (y, x, q, n);
167
168
if (mpz_cmp_ui (y, 1) == 0 || mpz_cmp (y, nm1) == 0)
169
return 1;
170
171
for (i = 1; i < k; i++)
172
{
173
mpz_powm_ui (y, y, 2, n);
174
if (mpz_cmp (y, nm1) == 0)
175
return 1;
176
if (mpz_cmp_ui (y, 1) == 0)
177
return 0;
178
}
179
return 0;
180
}
181
182
int
183
mp_prime_p (mpz_t n)
184
{
185
int k, r, is_prime;
186
mpz_t q, a, nm1, tmp;
187
struct factors factors;
188
189
if (mpz_cmp_ui (n, 1) <= 0)
190
return 0;
191
192
/* We have already casted out small primes. */
193
if (mpz_cmp_ui (n, (long) FIRST_OMITTED_PRIME * FIRST_OMITTED_PRIME) < 0)
194
return 1;
195
196
mpz_inits (q, a, nm1, tmp, NULL);
197
198
/* Precomputation for Miller-Rabin. */
199
mpz_sub_ui (nm1, n, 1);
200
201
/* Find q and k, where q is odd and n = 1 + 2**k * q. */
202
k = mpz_scan1 (nm1, 0);
203
mpz_tdiv_q_2exp (q, nm1, k);
204
205
mpz_set_ui (a, 2);
206
207
/* Perform a Miller-Rabin test, finds most composites quickly. */
208
if (!mp_millerrabin (n, nm1, a, tmp, q, k))
209
{
210
is_prime = 0;
211
goto ret2;
212
}
213
214
if (flag_prove_primality)
215
{
216
/* Factor n-1 for Lucas. */
217
mpz_set (tmp, nm1);
218
factor (tmp, &factors);
219
}
220
221
/* Loop until Lucas proves our number prime, or Miller-Rabin proves our
222
number composite. */
223
for (r = 0; r < PRIMES_PTAB_ENTRIES; r++)
224
{
225
int i;
226
227
if (flag_prove_primality)
228
{
229
is_prime = 1;
230
for (i = 0; i < factors.nfactors && is_prime; i++)
231
{
232
mpz_divexact (tmp, nm1, factors.p[i]);
233
mpz_powm (tmp, a, tmp, n);
234
is_prime = mpz_cmp_ui (tmp, 1) != 0;
235
}
236
}
237
else
238
{
239
/* After enough Miller-Rabin runs, be content. */
240
is_prime = (r == MR_REPS - 1);
241
}
242
243
if (is_prime)
244
goto ret1;
245
246
mpz_add_ui (a, a, primes_diff[r]); /* Establish new base. */
247
248
if (!mp_millerrabin (n, nm1, a, tmp, q, k))
249
{
250
is_prime = 0;
251
goto ret1;
252
}
253
}
254
255
fprintf (stderr, "Lucas prime test failure. This should not happen\n");
256
abort ();
257
258
ret1:
259
if (flag_prove_primality)
260
factor_clear (&factors);
261
ret2:
262
mpz_clears (q, a, nm1, tmp, NULL);
263
264
return is_prime;
265
}
266
267
void
268
factor_using_pollard_rho (mpz_t n, unsigned long a, struct factors *factors)
269
{
270
mpz_t x, z, y, P;
271
mpz_t t, t2;
272
unsigned long long k, l, i;
273
274
if (flag_verbose > 0)
275
{
276
printf ("[pollard-rho (%lu)] ", a);
277
}
278
279
mpz_inits (t, t2, NULL);
280
mpz_init_set_si (y, 2);
281
mpz_init_set_si (x, 2);
282
mpz_init_set_si (z, 2);
283
mpz_init_set_ui (P, 1);
284
k = 1;
285
l = 1;
286
287
while (mpz_cmp_ui (n, 1) != 0)
288
{
289
for (;;)
290
{
291
do
292
{
293
mpz_mul (t, x, x);
294
mpz_mod (x, t, n);
295
mpz_add_ui (x, x, a);
296
297
mpz_sub (t, z, x);
298
mpz_mul (t2, P, t);
299
mpz_mod (P, t2, n);
300
301
if (k % 32 == 1)
302
{
303
mpz_gcd (t, P, n);
304
if (mpz_cmp_ui (t, 1) != 0)
305
goto factor_found;
306
mpz_set (y, x);
307
}
308
}
309
while (--k != 0);
310
311
mpz_set (z, x);
312
k = l;
313
l = 2 * l;
314
for (i = 0; i < k; i++)
315
{
316
mpz_mul (t, x, x);
317
mpz_mod (x, t, n);
318
mpz_add_ui (x, x, a);
319
}
320
mpz_set (y, x);
321
}
322
323
factor_found:
324
do
325
{
326
mpz_mul (t, y, y);
327
mpz_mod (y, t, n);
328
mpz_add_ui (y, y, a);
329
330
mpz_sub (t, z, y);
331
mpz_gcd (t, t, n);
332
}
333
while (mpz_cmp_ui (t, 1) == 0);
334
335
mpz_divexact (n, n, t); /* divide by t, before t is overwritten */
336
337
if (!mp_prime_p (t))
338
{
339
if (flag_verbose > 0)
340
{
341
printf ("[composite factor--restarting pollard-rho] ");
342
}
343
factor_using_pollard_rho (t, a + 1, factors);
344
}
345
else
346
{
347
factor_insert (factors, t);
348
}
349
350
if (mp_prime_p (n))
351
{
352
factor_insert (factors, n);
353
break;
354
}
355
356
mpz_mod (x, x, n);
357
mpz_mod (z, z, n);
358
mpz_mod (y, y, n);
359
}
360
361
mpz_clears (P, t2, t, z, x, y, NULL);
362
}
363
364
void
365
factor (mpz_t t, struct factors *factors)
366
{
367
factor_init (factors);
368
369
if (mpz_sgn (t) != 0)
370
{
371
factor_using_division (t, factors);
372
373
if (mpz_cmp_ui (t, 1) != 0)
374
{
375
if (flag_verbose > 0)
376
{
377
printf ("[is number prime?] ");
378
}
379
if (mp_prime_p (t))
380
factor_insert (factors, t);
381
else
382
factor_using_pollard_rho (t, 1, factors);
383
}
384
}
385
}
386
387
int
388
main (int argc, char *argv[])
389
{
390
mpz_t t;
391
int i, j, k;
392
struct factors factors;
393
394
while (argc > 1)
395
{
396
if (!strcmp (argv[1], "-v"))
397
flag_verbose = 1;
398
else if (!strcmp (argv[1], "-w"))
399
flag_prove_primality = 0;
400
else
401
break;
402
403
argv++;
404
argc--;
405
}
406
407
mpz_init (t);
408
if (argc > 1)
409
{
410
for (i = 1; i < argc; i++)
411
{
412
mpz_set_str (t, argv[i], 0);
413
414
gmp_printf ("%Zd:", t);
415
factor (t, &factors);
416
417
for (j = 0; j < factors.nfactors; j++)
418
for (k = 0; k < factors.e[j]; k++)
419
gmp_printf (" %Zd", factors.p[j]);
420
421
puts ("");
422
factor_clear (&factors);
423
}
424
}
425
else
426
{
427
for (;;)
428
{
429
mpz_inp_str (t, stdin, 0);
430
if (feof (stdin))
431
break;
432
433
gmp_printf ("%Zd:", t);
434
factor (t, &factors);
435
436
for (j = 0; j < factors.nfactors; j++)
437
for (k = 0; k < factors.e[j]; k++)
438
gmp_printf (" %Zd", factors.p[j]);
439
440
puts ("");
441
factor_clear (&factors);
442
}
443
}
444
445
exit (0);
446
}
447
448