Fredrik Holmqvist 4389066602 Redo Update GMP to 6.2.0
GCC had a horrible .gitignore, untracked files were not applied
2020-07-22 10:10:16 +02:00

342 lines
8.2 KiB
C

/*
Copyright 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/. */
/* Usage:
./primes [p|c] [n0] <nMax>
Checks mpz_probab_prime_p(n, r) exhaustively, starting from n=n0
up to nMax.
If n0 * n0 > nMax, the intervall is sieved piecewise, else the
full intervall [0..nMax] is sieved at once.
With the parameter "p" (or nothing), tests all numbers. With "c"
only composites are tested.
./primes n [n0] <nMax>
Checks mpz_nextprime() exhaustively, starting from n=n0 up to
nMax.
WARNING: The full intervall [0..nMax] is sieved at once, even if
only a piece is needed. This may require a lot of memory!
*/
#include <stdlib.h>
#include <stdio.h>
#include "gmp-impl.h"
#include "longlong.h"
#include "tests.h"
#define STOP(x) return (x)
/* #define STOP(x) x */
#define REPS 10
/* #define TRACE(x,n) if ((n)>1) {x;} */
#define TRACE(x,n)
/* The full primesieve.c is included, just for block_resieve, that
is not exported ... */
#undef gmp_primesieve
#include "../../primesieve.c"
#ifndef BLOCK_SIZE
#define BLOCK_SIZE 2048
#endif
/*********************************************************/
/* Section sieve: sieving functions and tools for primes */
/*********************************************************/
static mp_size_t
primesieve_size (mp_limb_t n) { return n_to_bit(n) / GMP_LIMB_BITS + 1; }
/*************************************************************/
/* Section macros: common macros, for swing/fac/bin (&sieve) */
/*************************************************************/
#define LOOP_ON_SIEVE_CONTINUE(prime,end,sieve) \
__max_i = (end); \
\
do { \
++__i; \
if (((sieve)[__index] & __mask) == 0) \
{ \
mp_limb_t prime; \
prime = id_to_n(__i)
#define LOOP_ON_SIEVE_BEGIN(prime,start,end,off,sieve) \
do { \
mp_limb_t __mask, __index, __max_i, __i; \
\
__i = (start)-(off); \
__index = __i / GMP_LIMB_BITS; \
__mask = CNST_LIMB(1) << (__i % GMP_LIMB_BITS); \
__i += (off); \
\
LOOP_ON_SIEVE_CONTINUE(prime,end,sieve)
#define LOOP_ON_SIEVE_STOP \
} \
__mask = __mask << 1 | __mask >> (GMP_LIMB_BITS-1); \
__index += __mask & 1; \
} while (__i <= __max_i)
#define LOOP_ON_SIEVE_END \
LOOP_ON_SIEVE_STOP; \
} while (0)
mpz_t g;
int something_wrong (mpz_t er, int exp)
{
fprintf (stderr, "value = %lu , expected = %i\n", mpz_get_ui (er), exp);
return -1;
}
int
check_pprime (unsigned long begin, unsigned long end, int composites)
{
begin = (begin / 6U) * 6U;
for (;(begin < 2) & (begin <= end); ++begin)
{
*(g->_mp_d) = begin;
TRACE(printf ("-%li ", begin),1);
if (mpz_probab_prime_p (g, REPS))
STOP (something_wrong (g, 0));
}
for (;(begin < 4) & (begin <= end); ++begin)
{
*(g->_mp_d) = begin;
TRACE(printf ("+%li ", begin),2);
if (!composites && !mpz_probab_prime_p (g, REPS))
STOP (something_wrong (g, 1));
}
if (end > 4) {
if ((end > 10000) && (begin > end / begin))
{
mp_limb_t *sieve, *primes;
mp_size_t size_s, size_p, off;
unsigned long start;
mpz_set_ui (g, end);
mpz_sqrt (g, g);
start = mpz_get_ui (g) + GMP_LIMB_BITS;
size_p = primesieve_size (start);
primes = __GMP_ALLOCATE_FUNC_LIMBS (size_p);
gmp_primesieve (primes, start);
size_s = BLOCK_SIZE * 2;
sieve = __GMP_ALLOCATE_FUNC_LIMBS (size_s);
off = n_to_bit(begin) + (begin % 3 == 0);
do {
TRACE (printf ("off =%li\n", off),3);
block_resieve (sieve, BLOCK_SIZE, off, primes);
TRACE (printf ("LOOP =%li - %li\n", id_to_n (off+1), id_to_n (off + BLOCK_SIZE * GMP_LIMB_BITS)),3);
LOOP_ON_SIEVE_BEGIN (prime, off, off + BLOCK_SIZE * GMP_LIMB_BITS - 1,
off, sieve);
do {
*(g->_mp_d) = begin;
TRACE(printf ("-%li ", begin),1);
if (mpz_probab_prime_p (g, REPS))
STOP (something_wrong (g, 0));
if ((begin & 0xff) == 0)
{
spinner();
if ((begin & 0xfffffff) == 0)
printf ("%li (0x%lx)\n", begin, begin);
}
} while (++begin < prime);
*(g->_mp_d) = begin;
TRACE(printf ("+%li ", begin),2);
if (!composites && ! mpz_probab_prime_p (g, REPS))
STOP (something_wrong (g, 1));
++begin;
LOOP_ON_SIEVE_END;
off += BLOCK_SIZE * GMP_LIMB_BITS;
} while (begin < end);
__GMP_FREE_FUNC_LIMBS (sieve, size_s);
__GMP_FREE_FUNC_LIMBS (primes, size_p);
}
else
{
mp_limb_t *sieve;
mp_size_t size;
unsigned long start;
size = primesieve_size (end);
sieve = __GMP_ALLOCATE_FUNC_LIMBS (size);
gmp_primesieve (sieve, end);
start = MAX (begin, 5) | 1;
LOOP_ON_SIEVE_BEGIN (prime, n_to_bit(start) + (start % 3 == 0),
n_to_bit (end), 0, sieve);
do {
*(g->_mp_d) = begin;
TRACE(printf ("-%li ", begin),1);
if (mpz_probab_prime_p (g, REPS))
STOP (something_wrong (g, 0));
if ((begin & 0xff) == 0)
{
spinner();
if ((begin & 0xfffffff) == 0)
printf ("%li (0x%lx)\n", begin, begin);
}
} while (++begin < prime);
*(g->_mp_d) = begin;
TRACE(printf ("+%li ", begin),2);
if (!composites && ! mpz_probab_prime_p (g, REPS))
STOP (something_wrong (g, 1));
++begin;
LOOP_ON_SIEVE_END;
__GMP_FREE_FUNC_LIMBS (sieve, size);
}
}
for (;begin < end; ++begin)
{
*(g->_mp_d) = begin;
TRACE(printf ("-%li ", begin),1);
if (mpz_probab_prime_p (g, REPS))
STOP (something_wrong (g, 0));
}
gmp_printf ("%Zd\n", g);
return 0;
}
int
check_nprime (unsigned long begin, unsigned long end)
{
if (begin < 2)
{
*(g->_mp_d) = begin;
TRACE(printf ("%li ", begin),1);
mpz_nextprime (g, g);
if (mpz_cmp_ui (g, 2) != 0)
STOP (something_wrong (g, -1));
begin = mpz_get_ui (g);
}
if (begin < 3)
{
*(g->_mp_d) = begin;
TRACE(printf ("%li ", begin),1);
mpz_nextprime (g, g);
if (mpz_cmp_ui (g, 3) != 0)
STOP (something_wrong (g, -1));
begin = mpz_get_ui (g);
}
if (end > 4)
{
mp_limb_t *sieve;
mp_size_t size;
unsigned long start;
size = primesieve_size (end);
sieve = __GMP_ALLOCATE_FUNC_LIMBS (size);
gmp_primesieve (sieve, end);
start = MAX (begin, 5) | 1;
*(g->_mp_d) = begin;
LOOP_ON_SIEVE_BEGIN (prime, n_to_bit(start) + (start % 3 == 0),
n_to_bit (end), 0, sieve);
mpz_nextprime (g, g);
if (mpz_cmp_ui (g, prime) != 0)
STOP (something_wrong (g, -1));
if (prime - start > 200)
{
start = prime;
spinner();
if (prime - begin > 0xfffffff)
{
begin = prime;
printf ("%li (0x%lx)\n", begin, begin);
}
}
LOOP_ON_SIEVE_END;
__GMP_FREE_FUNC_LIMBS (sieve, size);
}
if (mpz_cmp_ui (g, end) < 0)
{
mpz_nextprime (g, g);
if (mpz_cmp_ui (g, end) <= 0)
STOP (something_wrong (g, -1));
}
gmp_printf ("%Zd\n", g);
return 0;
}
int
main (int argc, char **argv)
{
int ret, mode = 0;
unsigned long begin = 0, end = 0;
for (;argc > 1;--argc,++argv)
switch (*argv[1]) {
case 'p':
mode = 0;
break;
case 'c':
mode = 2;
break;
case 'n':
mode = 1;
break;
default:
begin = end;
end = atol (argv[1]);
}
if (begin >= end)
{
fprintf (stderr, "usage: primes [n|p|c] [n0] <nMax>\n");
exit (1);
}
mpz_init_set_ui (g, ULONG_MAX);
switch (mode) {
case 1:
ret = check_nprime (begin, end);
break;
default:
ret = check_pprime (begin, end, mode);
}
mpz_clear (g);
if (ret == 0)
printf ("Prime tests checked in [%lu - %lu] [0x%lx - 0x%lx].\n", begin, end, begin, end);
return ret;
}