Annotation of OpenXM_contrib/gmp/mpz/pprime_p.c, Revision 1.1.1.2
1.1 maekawa 1: /* mpz_probab_prime_p --
2: An implementation of the probabilistic primality test found in Knuth's
3: Seminumerical Algorithms book. If the function mpz_probab_prime_p()
4: returns 0 then n is not prime. If it returns 1, then n is 'probably'
1.1.1.2 ! maekawa 5: prime. If it returns 2, n is surely prime. The probability of a false
! 6: positive is (1/4)**reps, where reps is the number of internal passes of the
! 7: probabilistic algorithm. Knuth indicates that 25 passes are reasonable.
1.1 maekawa 8:
1.1.1.2 ! maekawa 9: Copyright (C) 1991, 1993, 1994, 1996, 1997, 1998, 1999, 2000 Free Software
! 10: Foundation, Inc. Miller-Rabin code contributed by John Amanatides.
1.1 maekawa 11:
12: This file is part of the GNU MP Library.
13:
14: The GNU MP Library is free software; you can redistribute it and/or modify
1.1.1.2 ! maekawa 15: it under the terms of the GNU Lesser General Public License as published by
! 16: the Free Software Foundation; either version 2.1 of the License, or (at your
1.1 maekawa 17: option) any later version.
18:
19: The GNU MP Library is distributed in the hope that it will be useful, but
20: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1.1.1.2 ! maekawa 21: or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
1.1 maekawa 22: License for more details.
23:
1.1.1.2 ! maekawa 24: You should have received a copy of the GNU Lesser General Public License
1.1 maekawa 25: along with the GNU MP Library; see the file COPYING.LIB. If not, write to
26: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
27: MA 02111-1307, USA. */
28:
29: #include "gmp.h"
1.1.1.2 ! maekawa 30: #include "gmp-impl.h"
! 31: #include "longlong.h"
1.1 maekawa 32:
1.1.1.2 ! maekawa 33: static int isprime _PROTO ((unsigned long int t));
! 34: static int mpz_millerrabin _PROTO ((mpz_srcptr n, int reps));
! 35:
! 36: int
! 37: #if __STDC__
! 38: mpz_probab_prime_p (mpz_srcptr n, int reps)
! 39: #else
! 40: mpz_probab_prime_p (n, reps)
1.1 maekawa 41: mpz_srcptr n;
1.1.1.2 ! maekawa 42: int reps;
! 43: #endif
1.1 maekawa 44: {
1.1.1.2 ! maekawa 45: mp_limb_t r;
1.1 maekawa 46:
1.1.1.2 ! maekawa 47: /* Handle small and negative n. */
! 48: if (mpz_cmp_ui (n, 1000000L) <= 0)
1.1 maekawa 49: {
1.1.1.2 ! maekawa 50: int is_prime;
! 51: if (mpz_sgn (n) < 0)
! 52: {
! 53: /* Negative number. Negate and call ourselves. */
! 54: mpz_t n2;
! 55: mpz_init (n2);
! 56: mpz_neg (n2, n);
! 57: is_prime = mpz_probab_prime_p (n2, reps);
! 58: mpz_clear (n2);
! 59: return is_prime;
! 60: }
! 61: is_prime = isprime (mpz_get_ui (n));
! 62: return is_prime ? 2 : 0;
1.1 maekawa 63: }
64:
1.1.1.2 ! maekawa 65: /* If n is now even, it is not a prime. */
! 66: if ((mpz_get_ui (n) & 1) == 0)
! 67: return 0;
1.1 maekawa 68:
1.1.1.2 ! maekawa 69: /* Check if n has small factors. */
! 70: if (UDIV_TIME > (2 * UMUL_TIME + 6))
! 71: r = mpn_preinv_mod_1 (PTR(n), SIZ(n), (mp_limb_t) PP, (mp_limb_t) PP_INVERTED);
! 72: else
! 73: r = mpn_mod_1 (PTR(n), SIZ(n), (mp_limb_t) PP);
! 74: if (r % 3 == 0 || r % 5 == 0 || r % 7 == 0 || r % 11 == 0 || r % 13 == 0
! 75: || r % 17 == 0 || r % 19 == 0 || r % 23 == 0 || r % 29 == 0
! 76: #if BITS_PER_MP_LIMB == 64
! 77: || r % 31 == 0 || r % 37 == 0 || r % 41 == 0 || r % 43 == 0
! 78: || r % 47 == 0 || r % 53 == 0
! 79: #endif
! 80: )
! 81: {
! 82: return 0;
! 83: }
1.1 maekawa 84:
1.1.1.2 ! maekawa 85: /* Do more dividing. We collect small primes, using umul_ppmm, until we
! 86: overflow a single limb. We divide our number by the small primes product,
! 87: and look for factors in the remainder. */
! 88: {
! 89: unsigned long int ln2;
! 90: unsigned long int q;
! 91: mp_limb_t p1, p0, p;
! 92: unsigned int primes[15];
! 93: int nprimes;
! 94:
! 95: nprimes = 0;
! 96: p = 1;
! 97: ln2 = mpz_sizeinbase (n, 2) / 30; ln2 = ln2 * ln2;
! 98: for (q = BITS_PER_MP_LIMB == 64 ? 59 : 31; q < ln2; q += 2)
! 99: {
! 100: if (isprime (q))
! 101: {
! 102: umul_ppmm (p1, p0, p, q);
! 103: if (p1 != 0)
! 104: {
! 105: r = mpn_mod_1 (PTR(n), SIZ(n), p);
! 106: while (--nprimes >= 0)
! 107: if (r % primes[nprimes] == 0)
! 108: {
! 109: if (mpn_mod_1 (PTR(n), SIZ(n), (mp_limb_t) primes[nprimes]) != 0)
! 110: abort ();
! 111: return 0;
! 112: }
! 113: p = q;
! 114: nprimes = 0;
! 115: }
! 116: else
! 117: {
! 118: p = p0;
! 119: }
! 120: primes[nprimes++] = q;
! 121: }
! 122: }
! 123: }
! 124:
! 125: /* Perform a number of Miller-Rabin tests. */
! 126: return mpz_millerrabin (n, reps);
! 127: }
! 128:
! 129: static int
! 130: #if __STDC__
! 131: isprime (unsigned long int t)
! 132: #else
! 133: isprime (t)
! 134: unsigned long int t;
! 135: #endif
! 136: {
! 137: unsigned long int q, r, d;
! 138:
! 139: if (t < 3 || (t & 1) == 0)
! 140: return t == 2;
! 141:
! 142: for (d = 3, r = 1; r != 0; d += 2)
1.1 maekawa 143: {
1.1.1.2 ! maekawa 144: q = t / d;
! 145: r = t - q * d;
! 146: if (q < d)
1.1 maekawa 147: return 1;
148: }
149: return 0;
150: }
151:
1.1.1.2 ! maekawa 152: static int millerrabin _PROTO ((mpz_srcptr n, mpz_srcptr nm1,
! 153: mpz_ptr x, mpz_ptr y,
! 154: mpz_srcptr q, unsigned long int k));
! 155:
! 156: static int
1.1 maekawa 157: #if __STDC__
1.1.1.2 ! maekawa 158: mpz_millerrabin (mpz_srcptr n, int reps)
1.1 maekawa 159: #else
1.1.1.2 ! maekawa 160: mpz_millerrabin (n, reps)
! 161: mpz_srcptr n;
1.1 maekawa 162: int reps;
163: #endif
164: {
1.1.1.2 ! maekawa 165: int r;
! 166: mpz_t nm1, x, y, q;
1.1 maekawa 167: unsigned long int k;
1.1.1.2 ! maekawa 168: gmp_randstate_t rstate;
! 169: int is_prime;
! 170: TMP_DECL (marker);
! 171: TMP_MARK (marker);
! 172:
! 173: MPZ_TMP_INIT (nm1, SIZ (n) + 1);
! 174: mpz_sub_ui (nm1, n, 1L);
! 175:
! 176: MPZ_TMP_INIT (x, SIZ (n));
! 177: MPZ_TMP_INIT (y, 2 * SIZ (n)); /* mpz_powm_ui needs excessive memory!!! */
! 178:
! 179: /* Perform a Fermat test. */
! 180: mpz_set_ui (x, 210L);
! 181: mpz_powm (y, x, nm1, n);
! 182: if (mpz_cmp_ui (y, 1L) != 0)
1.1 maekawa 183: {
1.1.1.2 ! maekawa 184: return 0;
! 185: TMP_FREE (marker);
1.1 maekawa 186: }
187:
1.1.1.2 ! maekawa 188: MPZ_TMP_INIT (q, SIZ (n));
1.1 maekawa 189:
1.1.1.2 ! maekawa 190: /* Find q and k, where q is odd and n = 1 + 2**k * q. */
! 191: k = mpz_scan1 (nm1, 0L);
! 192: mpz_tdiv_q_2exp (q, nm1, k);
! 193:
! 194: gmp_randinit (rstate, GMP_RAND_ALG_DEFAULT, 32L);
1.1 maekawa 195:
196: is_prime = 1;
1.1.1.2 ! maekawa 197: for (r = 0; r < reps && is_prime; r++)
! 198: {
! 199: do
! 200: mpz_urandomb (x, rstate, mpz_sizeinbase (n, 2) - 1);
! 201: while (mpz_cmp_ui (x, 1L) <= 0);
! 202:
! 203: is_prime = millerrabin (n, nm1, x, y, q, k);
! 204: }
1.1 maekawa 205:
1.1.1.2 ! maekawa 206: gmp_randclear (rstate);
! 207:
! 208: TMP_FREE (marker);
1.1 maekawa 209: return is_prime;
1.1.1.2 ! maekawa 210: }
! 211:
! 212: static int
! 213: #if __STDC__
! 214: millerrabin (mpz_srcptr n, mpz_srcptr nm1, mpz_ptr x, mpz_ptr y,
! 215: mpz_srcptr q, unsigned long int k)
! 216: #else
! 217: millerrabin (n, nm1, x, y, q, k)
! 218: mpz_srcptr n;
! 219: mpz_srcptr nm1;
! 220: mpz_ptr x;
! 221: mpz_ptr y;
! 222: mpz_srcptr q;
! 223: unsigned long int k;
! 224: #endif
! 225: {
! 226: unsigned long int i;
! 227:
! 228: mpz_powm (y, x, q, n);
! 229:
! 230: if (mpz_cmp_ui (y, 1L) == 0 || mpz_cmp (y, nm1) == 0)
! 231: return 1;
! 232:
! 233: for (i = 1; i < k; i++)
! 234: {
! 235: mpz_powm_ui (y, y, 2L, n);
! 236: if (mpz_cmp (y, nm1) == 0)
! 237: return 1;
! 238: if (mpz_cmp_ui (y, 1L) == 0)
! 239: return 0;
! 240: }
! 241: return 0;
1.1 maekawa 242: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>