ubuntu-buildroot/output/build/host-gmp-6.2.1/tests/mpz/t-pprime_p.c

232 lines
4.8 KiB
C

/* Exercise mpz_probab_prime_p.
Copyright 2002, 2018-2019 Free Software Foundation, Inc.
This file is part of the GNU MP Library test suite.
The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.
The GNU MP Library test suite is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.
You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
#include <stdio.h>
#include <stdlib.h>
#include "gmp-impl.h"
#include "tests.h"
/* Enhancements:
- Test some big primes don't come back claimed to be composite.
- Test some big composites don't come back claimed to be certainly prime.
- Test some big composites with small factors are identified as certainly
composite. */
/* return 1 if prime, 0 if composite */
int
isprime (long n)
{
long i;
n = ABS(n);
if (n < 2)
return 0;
if (n < 4)
return 1;
if ((n & 1) == 0)
return 0;
for (i = 3; i*i <= n; i+=2)
if ((n % i) == 0)
return 0;
return 1;
}
void
check_one (mpz_srcptr n, int want)
{
int got;
got = mpz_probab_prime_p (n, 25);
/* "definitely prime" is fine if we only wanted "probably prime" */
if (got == 2 && want == 1)
want = 2;
if (got != want)
{
printf ("mpz_probab_prime_p\n");
mpz_trace (" n ", n);
printf (" got =%d", got);
printf (" want=%d", want);
abort ();
}
}
void
check_pn (mpz_ptr n, int want)
{
check_one (n, want);
mpz_neg (n, n);
check_one (n, want);
}
/* expect certainty for small n */
void
check_small (void)
{
mpz_t n;
long i;
mpz_init (n);
for (i = 0; i < 300; i++)
{
mpz_set_si (n, i);
check_pn (n, isprime (i));
}
mpz_clear (n);
}
void
check_composites (int count)
{
int i;
mpz_t a, b, n, bs;
unsigned long size_range, size;
gmp_randstate_ptr rands = RANDS;
mpz_init (a);
mpz_init (b);
mpz_init (n);
mpz_init (bs);
for (i = 0; i < count; i++)
{
mpz_urandomb (bs, rands, 32);
size_range = mpz_get_ui (bs) % 13 + 1; /* 0..8192 bit operands */
mpz_urandomb (bs, rands, size_range);
size = mpz_get_ui (bs);
mpz_rrandomb (a, rands, size);
mpz_urandomb (bs, rands, 32);
size_range = mpz_get_ui (bs) % 13 + 1; /* 0..8192 bit operands */
mpz_rrandomb (b, rands, size);
/* Exclude trivial factors */
if (mpz_cmp_ui (a, 1) == 0)
mpz_set_ui (a, 2);
if (mpz_cmp_ui (b, 1) == 0)
mpz_set_ui (b, 2);
mpz_mul (n, a, b);
check_pn (n, 0);
}
mpz_clear (a);
mpz_clear (b);
mpz_clear (n);
mpz_clear (bs);
}
static void
check_primes (void)
{
static const char * const primes[] = {
"2", "53", "1234567891",
"2055693949", "1125899906842597", "16412292043871650369",
/* diffie-hellman-group1-sha1, also "Well known group 2" in RFC
2412, 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 } */
"0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381"
"FFFFFFFFFFFFFFFF",
NULL
};
mpz_t n;
int i;
mpz_init (n);
for (i = 0; primes[i]; i++)
{
mpz_set_str_or_abort (n, primes[i], 0);
check_one (n, 1);
}
mpz_clear (n);
}
static void
check_fermat_mersenne (int count)
{
int fermat_exponents [] = {1, 2, 4, 8, 16};
int mersenne_exponents [] = {2, 3, 5, 7, 13, 17, 19, 31, 61, 89,
107, 127, 521, 607, 1279, 2203, 2281,
3217, 4253, 4423, 9689, 9941, 11213,
19937, 21701, 23209, 44497, 86243};
mpz_t pp;
int i, j, want;
mpz_init (pp);
count = MIN (110000, count);
for (i=1; i<count; ++i)
{
mpz_set_ui (pp, 1);
mpz_setbit (pp, i); /* 2^i + 1 */
want = 0;
for (j = 0; j < numberof (fermat_exponents); j++)
if (fermat_exponents[j] == i)
{
want = 1;
break;
}
check_one (pp, want);
mpz_sub_ui (pp, pp, 2); /* 2^i - 1 */
want = 0;
for (j = 0; j < numberof (mersenne_exponents); j++)
if (mersenne_exponents[j] == i)
{
want = 1;
break;
}
check_one (pp, want);
}
mpz_clear (pp);
}
int
main (int argc, char **argv)
{
int count = 1000;
TESTS_REPS (count, argv, argc);
tests_start ();
check_small ();
check_fermat_mersenne (count >> 3);
check_composites (count);
check_primes ();
tests_end ();
exit (0);
}