2
* Copyright (C) 1997-2003 George Lebl
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
27
#include "calc.h" /* for evalnode_hook and i18n stuff */
31
extern gboolean interrupted;
33
/* The strong pseudoprime test code copied from GMP */
36
strongpseudoprimesub (mpz_srcptr n, mpz_srcptr nm1, mpz_srcptr x, mpz_ptr y,
37
mpz_srcptr q, unsigned long int k)
41
mpz_powm (y, x, q, n);
43
if (mpz_cmp_ui (y, 1L) == 0 || mpz_cmp (y, nm1) == 0)
46
for (i = 1; i < k; i++)
48
mpz_powm_ui (y, y, 2L, n);
49
if (mpz_cmp (y, nm1) == 0)
51
if (mpz_cmp_ui (y, 1L) == 0)
59
mympz_strong_pseudoprime_test (mpz_srcptr n, mpz_srcptr b)
64
unsigned long int size_n = mpz_size (n) * GMP_LIMB_BITS;
66
mpz_init2 (nm1, size_n + GMP_LIMB_BITS);
67
mpz_sub_ui (nm1, n, 1L);
69
mpz_init2 (y, 2 * size_n); /* mpz_powm_ui needs excessive memory!!! */
71
mpz_init2 (q, size_n);
73
/* Find q and k, where q is odd and n = 1 + 2**k * q. */
74
k = mpz_scan1 (nm1, 0L);
75
mpz_tdiv_q_2exp (q, nm1, k);
77
is_prime = strongpseudoprimesub (n, nm1, b, y, q, k);
86
/* return true only if strong pseudoprime to all of 2,3,5 and 7 */
88
mympz_strong_pseudoprime_test_2_3_5_7 (mpz_srcptr n)
93
unsigned long int size_n = mpz_size (n) * GMP_LIMB_BITS;
95
mpz_init2 (nm1, size_n + GMP_LIMB_BITS);
96
mpz_sub_ui (nm1, n, 1L);
98
mpz_init2 (y, 2 * size_n); /* mpz_powm_ui needs excessive memory!!! */
100
mpz_init2 (q, size_n);
102
/* Find q and k, where q is odd and n = 1 + 2**k * q. */
103
k = mpz_scan1 (nm1, 0L);
104
mpz_tdiv_q_2exp (q, nm1, k);
107
mpz_init_set_ui (b, 2);
108
if (strongpseudoprimesub (n, nm1, b, y, q, k)) {
110
if (strongpseudoprimesub (n, nm1, b, y, q, k)) {
112
if (strongpseudoprimesub (n, nm1, b, y, q, k)) {
114
if (strongpseudoprimesub (n, nm1, b, y, q, k)) {
129
/* assuming generalized riemman hypothesis, if we test for
130
every base from 2 to 2*lg(n)^2.
132
Neil Koblitz, A Course in Number Theory and Cryptography, Springer, 1987 */
134
mympz_miller_rabin_test_sure (mpz_srcptr n)
136
mpz_t nm1, y, q, b, m;
139
unsigned long int size_n = mpz_size (n) * GMP_LIMB_BITS;
141
mpz_init2 (nm1, size_n + GMP_LIMB_BITS);
142
mpz_sub_ui (nm1, n, 1L);
144
mpz_init2 (y, 2 * size_n); /* mpz_powm_ui needs excessive memory!!! */
146
mpz_init2 (q, size_n);
148
/* Find q and k, where q is odd and n = 1 + 2**k * q. */
149
k = mpz_scan1 (nm1, 0L);
150
mpz_tdiv_q_2exp (q, nm1, k);
152
/* compute 2*lg(n)^2 */
153
mpz_init_set_ui (m, mpz_sizeinbase (n, 2));
155
mpz_mul_ui (m, m, 2);
158
mpz_init_set_ui (b, 2);
160
if ( ! strongpseudoprimesub (n, nm1, b, y, q, k)) {
164
mpz_add_ui (b, b, 1L);
165
if (evalnode_hook != NULL) {
172
} while (mpz_cmp (b, m) <= 0);
183
/* we will really do 22+4 since we always test 2,3,5,7 as well,
184
so the probability that a wrong result is returned is
185
about 1/(4^26) which is about 8.9*10^-16. Knuth says
186
25 passes are reasonable (according to gmp source),
187
and Knuth is never wrong. */
188
long int mympz_is_prime_miller_rabin_reps = 22;
191
mympz_is_prime (mpz_srcptr n, int miller_rabin_reps)
195
static gboolean inited_test = FALSE;
205
ret = mympz_is_prime (nn, miller_rabin_reps);
210
if (miller_rabin_reps < 0)
211
miller_rabin_reps = mympz_is_prime_miller_rabin_reps;
213
/* Use the probab prime for trial divisions and stuff
214
and do one strong pseudoprime test for good meassure */
215
ret = mpz_probab_prime_p (n, 1);
222
if ( ! mympz_strong_pseudoprime_test_2_3_5_7 (n))
225
if ( ! inited_test) {
226
/* set test to 25*10^9 */
227
mpz_init_set_ui (test, 10);
228
mpz_pow_ui (test, test, 9);
229
mpz_mul_ui (test, test, 25);
232
/* if n < 25*10^9, we are now sure this
233
is a prime since the only n less than that
234
that is a composite and strong pseudoprime to 2,3,5,7
237
Neil Koblitz, A Course in Number Theory and Cryptography,
239
if (mpz_cmp (n, test) <= 0)
242
if (evalnode_hook != NULL)
247
return mpz_millerrabin (n, miller_rabin_reps-1);
251
append_factor (GArray *fact, mpz_srcptr num)
255
/* FIXME: implement faster search, this is sorted */
256
/* We start at 1 since the 0 entry is always -1 or 1 */
257
for (i = 1; i < fact->len; i++) {
258
int cmp = mpz_cmp (g_array_index (fact, GelFactor, i).num, num);
261
mpz_init_set (f.num, num);
263
g_array_insert_val (fact, i, f);
265
} else if (cmp == 0) {
266
/* already in the factorization */
267
g_array_index (fact, GelFactor, i).exp++;
271
/* not found, must add */
272
mpz_init_set (f.num, num);
274
g_array_append_val (fact, f);
278
append_factor_uint (GArray *fact, unsigned long num)
281
mpz_init_set_ui (znum, num);
282
append_factor (fact, znum);
286
/* Pollard-Rho factorization code snarfed from the gmp examples */
288
static unsigned add[] = {4, 2, 4, 2, 4, 6, 2, 6};
291
factor_using_division (GArray *fact, mpz_t t, unsigned int limit)
296
unsigned *addv = add;
297
unsigned int failures;
302
f = mpz_scan1 (t, 0);
303
mpz_div_2exp (t, t, f);
306
append_factor_uint (fact, 2);
312
mpz_tdiv_qr_ui (q, r, t, 3);
313
if (mpz_cmp_ui (r, 0) != 0)
316
append_factor_uint (fact, 3);
321
mpz_tdiv_qr_ui (q, r, t, 5);
322
if (mpz_cmp_ui (r, 0) != 0)
325
append_factor_uint (fact, 5);
331
while (mpz_cmp_ui (t, 1) != 0)
333
mpz_tdiv_qr_ui (q, r, t, f);
334
if (mpz_cmp_ui (r, 0) != 0)
337
if (mpz_cmp_ui (q, f) < 0)
341
if (failures > limit)
347
append_factor_uint (fact, f);
357
factor_using_pollard_rho (GArray *fact, mpz_t n, int a_int)
369
mpz_init_set_si (a, a_int);
370
mpz_init_set_si (y, 2);
371
mpz_init_set_si (x, 2);
372
mpz_init_set_si (x1, 2);
375
mpz_init_set_ui (P, 1);
378
while (mpz_cmp_ui (n, 1) != 0)
381
if (evalnode_hook != NULL) {
383
if G_UNLIKELY ((i++ & RUN_HOOK_EVERY_MASK) == RUN_HOOK_EVERY_MASK) {
392
mpz_mul (x, x, x); mpz_add (x, x, a); mpz_mod (x, x, n);
393
mpz_sub (t1, x1, x); mpz_mul (t2, P, t1); mpz_mod (P, t2, n);
399
if (mpz_cmp_ui (g, 1) != 0)
408
if (mpz_cmp_ui (g, 1) != 0)
414
for (i = 0; i < k; i++)
416
mpz_mul (x, x, x); mpz_add (x, x, a); mpz_mod (x, x, n);
424
mpz_mul (y, y, y); mpz_add (y, y, a); mpz_mod (y, y, n);
425
mpz_sub (t1, x1, y); mpz_gcd (g, t1, n);
427
while (mpz_cmp_ui (g, 1) == 0);
429
if (!mympz_is_prime (g, -1))
434
mpn_random (&a_limb, (mp_size_t) 1);
435
a_int = (int) a_limb;
437
while (a_int == -2 || a_int == 0);
439
factor_using_pollard_rho (fact, g, a_int);
444
append_factor (fact, g);
450
if (mympz_is_prime (n, -1))
452
append_factor (fact, n);
468
factor_number (GArray *fact, mpz_t t)
470
unsigned int division_limit;
472
/* Set the trial division limit according the size of t. */
473
division_limit = mpz_sizeinbase (t, 2);
474
if (division_limit > 1000)
475
division_limit = 1000 * 1000;
477
division_limit = division_limit * division_limit;
479
factor_using_division (fact, t, division_limit);
481
if (mpz_cmp_ui (t, 1) != 0)
483
if (mympz_is_prime (t, -1))
484
append_factor (fact, t);
486
factor_using_pollard_rho (fact, t, 1);
491
mympz_pollard_rho_factorize (mpz_srcptr t)
495
int sgn = mpz_sgn (t);
497
fact = g_array_new (FALSE /* zero_terminated */,
499
sizeof (GelFactor) /* element_size */);
504
append_factor_uint (fact, 0);
507
/* for negative numbers, add -1 to the factors
511
mpz_init_set_si (f.num, -1);
513
g_array_append_val (fact, f);
515
factor_number (fact, n);
517
append_factor_uint (fact, 1);
518
/* just factor the number */
519
factor_number (fact, n);
525
mympz_factorization_free (fact);
534
mympz_factorization_free (GArray *fact)
537
for (i = 0; i < fact->len; i++) {
538
mpz_clear (g_array_index (fact, GelFactor, i).num);
540
g_array_free (fact, TRUE /* free_segment */);