Home | History | Annotate | Line # | Download | only in devel
      1  1.1  mrg /*
      2  1.1  mrg Copyright 2018-2019 Free Software Foundation, Inc.
      3  1.1  mrg 
      4  1.1  mrg This file is part of the GNU MP Library test suite.
      5  1.1  mrg 
      6  1.1  mrg The GNU MP Library test suite is free software; you can redistribute it
      7  1.1  mrg and/or modify it under the terms of the GNU General Public License as
      8  1.1  mrg published by the Free Software Foundation; either version 3 of the License,
      9  1.1  mrg or (at your option) any later version.
     10  1.1  mrg 
     11  1.1  mrg The GNU MP Library test suite is distributed in the hope that it will be
     12  1.1  mrg useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  1.1  mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
     14  1.1  mrg Public License for more details.
     15  1.1  mrg 
     16  1.1  mrg You should have received a copy of the GNU General Public License along with
     17  1.1  mrg the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
     18  1.1  mrg 
     19  1.1  mrg /* Usage:
     20  1.1  mrg 
     21  1.1  mrg    ./primes [p|c] [n0] <nMax>
     22  1.1  mrg 
     23  1.1  mrg      Checks mpz_probab_prime_p(n, r) exhaustively, starting from n=n0
     24  1.1  mrg      up to nMax.
     25  1.1  mrg      If n0 * n0 > nMax, the intervall is sieved piecewise, else the
     26  1.1  mrg      full intervall [0..nMax] is sieved at once.
     27  1.1  mrg      With the parameter "p" (or nothing), tests all numbers. With "c"
     28  1.1  mrg      only composites are tested.
     29  1.1  mrg 
     30  1.1  mrg    ./primes n [n0] <nMax>
     31  1.1  mrg 
     32  1.1  mrg      Checks mpz_nextprime() exhaustively, starting from n=n0 up to
     33  1.1  mrg      nMax.
     34  1.1  mrg 
     35  1.1  mrg      WARNING: The full intervall [0..nMax] is sieved at once, even if
     36  1.1  mrg      only a piece is needed. This may require a lot of memory!
     37  1.1  mrg 
     38  1.1  mrg  */
     39  1.1  mrg 
     40  1.1  mrg #include <stdlib.h>
     41  1.1  mrg #include <stdio.h>
     42  1.1  mrg #include "gmp-impl.h"
     43  1.1  mrg #include "longlong.h"
     44  1.1  mrg #include "tests.h"
     45  1.1  mrg #define STOP(x) return (x)
     46  1.1  mrg /* #define STOP(x) x */
     47  1.1  mrg #define REPS 10
     48  1.1  mrg /* #define TRACE(x,n) if ((n)>1) {x;} */
     49  1.1  mrg #define TRACE(x,n)
     50  1.1  mrg 
     51  1.1  mrg /* The full primesieve.c is included, just for block_resieve, that
     52  1.1  mrg    is not exported ... */
     53  1.1  mrg #undef gmp_primesieve
     54  1.1  mrg #include "../../primesieve.c"
     55  1.1  mrg 
     56  1.1  mrg #ifndef BLOCK_SIZE
     57  1.1  mrg #define BLOCK_SIZE 2048
     58  1.1  mrg #endif
     59  1.1  mrg 
     60  1.1  mrg /*********************************************************/
     61  1.1  mrg /* Section sieve: sieving functions and tools for primes */
     62  1.1  mrg /*********************************************************/
     63  1.1  mrg 
     64  1.1  mrg static mp_size_t
     65  1.1  mrg primesieve_size (mp_limb_t n) { return n_to_bit(n) / GMP_LIMB_BITS + 1; }
     66  1.1  mrg 
     67  1.1  mrg /*************************************************************/
     68  1.1  mrg /* Section macros: common macros, for swing/fac/bin (&sieve) */
     69  1.1  mrg /*************************************************************/
     70  1.1  mrg 
     71  1.1  mrg #define LOOP_ON_SIEVE_CONTINUE(prime,end,sieve)			\
     72  1.1  mrg     __max_i = (end);						\
     73  1.1  mrg 								\
     74  1.1  mrg     do {							\
     75  1.1  mrg       ++__i;							\
     76  1.1  mrg       if (((sieve)[__index] & __mask) == 0)			\
     77  1.1  mrg 	{							\
     78  1.1  mrg           mp_limb_t prime;					\
     79  1.1  mrg 	  prime = id_to_n(__i)
     80  1.1  mrg 
     81  1.1  mrg #define LOOP_ON_SIEVE_BEGIN(prime,start,end,off,sieve)		\
     82  1.1  mrg   do {								\
     83  1.1  mrg     mp_limb_t __mask, __index, __max_i, __i;			\
     84  1.1  mrg 								\
     85  1.1  mrg     __i = (start)-(off);					\
     86  1.1  mrg     __index = __i / GMP_LIMB_BITS;				\
     87  1.1  mrg     __mask = CNST_LIMB(1) << (__i % GMP_LIMB_BITS);		\
     88  1.1  mrg     __i += (off);						\
     89  1.1  mrg 								\
     90  1.1  mrg     LOOP_ON_SIEVE_CONTINUE(prime,end,sieve)
     91  1.1  mrg 
     92  1.1  mrg #define LOOP_ON_SIEVE_STOP					\
     93  1.1  mrg 	}							\
     94  1.1  mrg       __mask = __mask << 1 | __mask >> (GMP_LIMB_BITS-1);	\
     95  1.1  mrg       __index += __mask & 1;					\
     96  1.1  mrg     }  while (__i <= __max_i)
     97  1.1  mrg 
     98  1.1  mrg #define LOOP_ON_SIEVE_END					\
     99  1.1  mrg     LOOP_ON_SIEVE_STOP;						\
    100  1.1  mrg   } while (0)
    101  1.1  mrg 
    102  1.1  mrg mpz_t g;
    103  1.1  mrg 
    104  1.1  mrg int something_wrong (mpz_t er, int exp)
    105  1.1  mrg {
    106  1.1  mrg   fprintf (stderr, "value = %lu , expected = %i\n", mpz_get_ui (er), exp);
    107  1.1  mrg   return -1;
    108  1.1  mrg }
    109  1.1  mrg 
    110  1.1  mrg int
    111  1.1  mrg check_pprime (unsigned long begin, unsigned long end, int composites)
    112  1.1  mrg {
    113  1.1  mrg   begin = (begin / 6U) * 6U;
    114  1.1  mrg   for (;(begin < 2) & (begin <= end); ++begin)
    115  1.1  mrg     {
    116  1.1  mrg       *(g->_mp_d) = begin;
    117  1.1  mrg       TRACE(printf ("-%li ", begin),1);
    118  1.1  mrg       if (mpz_probab_prime_p (g, REPS))
    119  1.1  mrg 	STOP (something_wrong (g, 0));
    120  1.1  mrg     }
    121  1.1  mrg   for (;(begin < 4) & (begin <= end); ++begin)
    122  1.1  mrg     {
    123  1.1  mrg       *(g->_mp_d) = begin;
    124  1.1  mrg       TRACE(printf ("+%li ", begin),2);
    125  1.1  mrg       if (!composites && !mpz_probab_prime_p (g, REPS))
    126  1.1  mrg 	STOP (something_wrong (g, 1));
    127  1.1  mrg     }
    128  1.1  mrg   if (end > 4) {
    129  1.1  mrg     if ((end > 10000) && (begin > end / begin))
    130  1.1  mrg       {
    131  1.1  mrg 	mp_limb_t *sieve, *primes;
    132  1.1  mrg 	mp_size_t size_s, size_p, off;
    133  1.1  mrg 	unsigned long start;
    134  1.1  mrg 
    135  1.1  mrg 	mpz_set_ui (g, end);
    136  1.1  mrg 	mpz_sqrt (g, g);
    137  1.1  mrg 	start = mpz_get_ui (g) + GMP_LIMB_BITS;
    138  1.1  mrg 	size_p = primesieve_size (start);
    139  1.1  mrg 
    140  1.1  mrg 	primes = __GMP_ALLOCATE_FUNC_LIMBS (size_p);
    141  1.1  mrg 	gmp_primesieve (primes, start);
    142  1.1  mrg 
    143  1.1  mrg 	size_s = BLOCK_SIZE * 2;
    144  1.1  mrg 	sieve = __GMP_ALLOCATE_FUNC_LIMBS (size_s);
    145  1.1  mrg 	off = n_to_bit(begin) + (begin % 3 == 0);
    146  1.1  mrg 
    147  1.1  mrg 	do {
    148  1.1  mrg 	  TRACE (printf ("off =%li\n", off),3);
    149  1.1  mrg 	  block_resieve (sieve, BLOCK_SIZE, off, primes);
    150  1.1  mrg 	  TRACE (printf ("LOOP =%li - %li\n", id_to_n (off+1), id_to_n (off + BLOCK_SIZE * GMP_LIMB_BITS)),3);
    151  1.1  mrg 	  LOOP_ON_SIEVE_BEGIN (prime, off, off + BLOCK_SIZE * GMP_LIMB_BITS - 1,
    152  1.1  mrg 			       off, sieve);
    153  1.1  mrg 
    154  1.1  mrg 	  do {
    155  1.1  mrg 	    *(g->_mp_d) = begin;
    156  1.1  mrg 	    TRACE(printf ("-%li ", begin),1);
    157  1.1  mrg 	    if (mpz_probab_prime_p (g, REPS))
    158  1.1  mrg 	      STOP (something_wrong (g, 0));
    159  1.1  mrg 	    if ((begin & 0xff) == 0)
    160  1.1  mrg 	      {
    161  1.1  mrg 		spinner();
    162  1.1  mrg 		if ((begin & 0xfffffff) == 0)
    163  1.1  mrg 		  printf ("%li (0x%lx)\n", begin, begin);
    164  1.1  mrg 	      }
    165  1.1  mrg 	  } while (++begin < prime);
    166  1.1  mrg 
    167  1.1  mrg 	  *(g->_mp_d) = begin;
    168  1.1  mrg 	  TRACE(printf ("+%li ", begin),2);
    169  1.1  mrg 	  if (!composites && ! mpz_probab_prime_p (g, REPS))
    170  1.1  mrg 	    STOP (something_wrong (g, 1));
    171  1.1  mrg 	  ++begin;
    172  1.1  mrg 
    173  1.1  mrg 	  LOOP_ON_SIEVE_END;
    174  1.1  mrg 	  off += BLOCK_SIZE * GMP_LIMB_BITS;
    175  1.1  mrg 	} while (begin < end);
    176  1.1  mrg 
    177  1.1  mrg 	__GMP_FREE_FUNC_LIMBS (sieve, size_s);
    178  1.1  mrg 	__GMP_FREE_FUNC_LIMBS (primes, size_p);
    179  1.1  mrg       }
    180  1.1  mrg     else
    181  1.1  mrg       {
    182  1.1  mrg 	mp_limb_t *sieve;
    183  1.1  mrg 	mp_size_t size;
    184  1.1  mrg 	unsigned long start;
    185  1.1  mrg 
    186  1.1  mrg 	size = primesieve_size (end);
    187  1.1  mrg 
    188  1.1  mrg 	sieve = __GMP_ALLOCATE_FUNC_LIMBS (size);
    189  1.1  mrg 	gmp_primesieve (sieve, end);
    190  1.1  mrg 	start = MAX (begin, 5) | 1;
    191  1.1  mrg 	LOOP_ON_SIEVE_BEGIN (prime, n_to_bit(start) + (start % 3 == 0),
    192  1.1  mrg 			     n_to_bit (end), 0, sieve);
    193  1.1  mrg 
    194  1.1  mrg 	do {
    195  1.1  mrg 	  *(g->_mp_d) = begin;
    196  1.1  mrg 	  TRACE(printf ("-%li ", begin),1);
    197  1.1  mrg 	  if (mpz_probab_prime_p (g, REPS))
    198  1.1  mrg 	    STOP (something_wrong (g, 0));
    199  1.1  mrg 	  if ((begin & 0xff) == 0)
    200  1.1  mrg 	    {
    201  1.1  mrg 	      spinner();
    202  1.1  mrg 	      if ((begin & 0xfffffff) == 0)
    203  1.1  mrg 		printf ("%li (0x%lx)\n", begin, begin);
    204  1.1  mrg 	    }
    205  1.1  mrg 	} while (++begin < prime);
    206  1.1  mrg 
    207  1.1  mrg 	*(g->_mp_d) = begin;
    208  1.1  mrg 	TRACE(printf ("+%li ", begin),2);
    209  1.1  mrg 	if (!composites && ! mpz_probab_prime_p (g, REPS))
    210  1.1  mrg 	  STOP (something_wrong (g, 1));
    211  1.1  mrg 	++begin;
    212  1.1  mrg 
    213  1.1  mrg 	LOOP_ON_SIEVE_END;
    214  1.1  mrg 
    215  1.1  mrg 	__GMP_FREE_FUNC_LIMBS (sieve, size);
    216  1.1  mrg       }
    217  1.1  mrg   }
    218  1.1  mrg 
    219  1.1  mrg   for (;begin < end; ++begin)
    220  1.1  mrg     {
    221  1.1  mrg       *(g->_mp_d) = begin;
    222  1.1  mrg       TRACE(printf ("-%li ", begin),1);
    223  1.1  mrg       if (mpz_probab_prime_p (g, REPS))
    224  1.1  mrg 	STOP (something_wrong (g, 0));
    225  1.1  mrg     }
    226  1.1  mrg 
    227  1.1  mrg   gmp_printf ("%Zd\n", g);
    228  1.1  mrg   return 0;
    229  1.1  mrg }
    230  1.1  mrg 
    231  1.1  mrg int
    232  1.1  mrg check_nprime (unsigned long begin, unsigned long end)
    233  1.1  mrg {
    234  1.1  mrg   if (begin < 2)
    235  1.1  mrg     {
    236  1.1  mrg       *(g->_mp_d) = begin;
    237  1.1  mrg       TRACE(printf ("%li ", begin),1);
    238  1.1  mrg       mpz_nextprime (g, g);
    239  1.1  mrg       if (mpz_cmp_ui (g, 2) != 0)
    240  1.1  mrg 	STOP (something_wrong (g, -1));
    241  1.1  mrg       begin = mpz_get_ui (g);
    242  1.1  mrg     }
    243  1.1  mrg   if (begin < 3)
    244  1.1  mrg     {
    245  1.1  mrg       *(g->_mp_d) = begin;
    246  1.1  mrg       TRACE(printf ("%li ", begin),1);
    247  1.1  mrg       mpz_nextprime (g, g);
    248  1.1  mrg       if (mpz_cmp_ui (g, 3) != 0)
    249  1.1  mrg 	STOP (something_wrong (g, -1));
    250  1.1  mrg       begin = mpz_get_ui (g);
    251  1.1  mrg     }
    252  1.1  mrg   if (end > 4)
    253  1.1  mrg       {
    254  1.1  mrg 	mp_limb_t *sieve;
    255  1.1  mrg 	mp_size_t size;
    256  1.1  mrg 	unsigned long start;
    257  1.1  mrg 
    258  1.1  mrg 	size = primesieve_size (end);
    259  1.1  mrg 
    260  1.1  mrg 	sieve = __GMP_ALLOCATE_FUNC_LIMBS (size);
    261  1.1  mrg 	gmp_primesieve (sieve, end);
    262  1.1  mrg 	start = MAX (begin, 5) | 1;
    263  1.1  mrg 	*(g->_mp_d) = begin;
    264  1.1  mrg 	LOOP_ON_SIEVE_BEGIN (prime, n_to_bit(start) + (start % 3 == 0),
    265  1.1  mrg 			     n_to_bit (end), 0, sieve);
    266  1.1  mrg 
    267  1.1  mrg 	mpz_nextprime (g, g);
    268  1.1  mrg 	if (mpz_cmp_ui (g, prime) != 0)
    269  1.1  mrg 	  STOP (something_wrong (g, -1));
    270  1.1  mrg 
    271  1.1  mrg 	if (prime - start > 200)
    272  1.1  mrg 	  {
    273  1.1  mrg 	    start = prime;
    274  1.1  mrg 	    spinner();
    275  1.1  mrg 	    if (prime - begin > 0xfffffff)
    276  1.1  mrg 	      {
    277  1.1  mrg 		begin = prime;
    278  1.1  mrg 		printf ("%li (0x%lx)\n", begin, begin);
    279  1.1  mrg 	      }
    280  1.1  mrg 	  }
    281  1.1  mrg 
    282  1.1  mrg 	LOOP_ON_SIEVE_END;
    283  1.1  mrg 
    284  1.1  mrg 	__GMP_FREE_FUNC_LIMBS (sieve, size);
    285  1.1  mrg       }
    286  1.1  mrg 
    287  1.1  mrg   if (mpz_cmp_ui (g, end) < 0)
    288  1.1  mrg     {
    289  1.1  mrg       mpz_nextprime (g, g);
    290  1.1  mrg       if (mpz_cmp_ui (g, end) <= 0)
    291  1.1  mrg 	STOP (something_wrong (g, -1));
    292  1.1  mrg     }
    293  1.1  mrg 
    294  1.1  mrg   gmp_printf ("%Zd\n", g);
    295  1.1  mrg   return 0;
    296  1.1  mrg }
    297  1.1  mrg 
    298  1.1  mrg int
    299  1.1  mrg main (int argc, char **argv)
    300  1.1  mrg {
    301  1.1  mrg   int ret, mode = 0;
    302  1.1  mrg   unsigned long begin = 0, end = 0;
    303  1.1  mrg 
    304  1.1  mrg   for (;argc > 1;--argc,++argv)
    305  1.1  mrg     switch (*argv[1]) {
    306  1.1  mrg     case 'p':
    307  1.1  mrg       mode = 0;
    308  1.1  mrg       break;
    309  1.1  mrg     case 'c':
    310  1.1  mrg       mode = 2;
    311  1.1  mrg       break;
    312  1.1  mrg     case 'n':
    313  1.1  mrg       mode = 1;
    314  1.1  mrg       break;
    315  1.1  mrg     default:
    316  1.1  mrg       begin = end;
    317  1.1  mrg       end = atol (argv[1]);
    318  1.1  mrg     }
    319  1.1  mrg 
    320  1.1  mrg   if (begin >= end)
    321  1.1  mrg     {
    322  1.1  mrg       fprintf (stderr, "usage: primes [n|p|c] [n0] <nMax>\n");
    323  1.1  mrg       exit (1);
    324  1.1  mrg     }
    325  1.1  mrg 
    326  1.1  mrg   mpz_init_set_ui (g, ULONG_MAX);
    327  1.1  mrg 
    328  1.1  mrg   switch (mode) {
    329  1.1  mrg   case 1:
    330  1.1  mrg     ret = check_nprime (begin, end);
    331  1.1  mrg     break;
    332  1.1  mrg   default:
    333  1.1  mrg     ret = check_pprime (begin, end, mode);
    334  1.1  mrg   }
    335  1.1  mrg 
    336  1.1  mrg   mpz_clear (g);
    337  1.1  mrg 
    338  1.1  mrg   if (ret == 0)
    339  1.1  mrg     printf ("Prime tests checked in [%lu - %lu] [0x%lx - 0x%lx].\n", begin, end, begin, end);
    340  1.1  mrg   return ret;
    341  1.1  mrg }
    342