xref: /dflybsd-src/contrib/gmp/mpz/nextprime.c (revision d365564473a20a528d07c59cad8ee2f4bea5546f)
14b6a78b7SSimon Schubert /* mpz_nextprime(p,t) - compute the next prime > t and store that in p.
24b6a78b7SSimon Schubert 
34b6a78b7SSimon Schubert Copyright 1999, 2000, 2001, 2008, 2009 Free Software Foundation, Inc.
44b6a78b7SSimon Schubert 
554028e53SJohn Marino Contributed to the GNU project by Niels M�ller and Torbjorn Granlund.
64b6a78b7SSimon Schubert 
74b6a78b7SSimon Schubert This file is part of the GNU MP Library.
84b6a78b7SSimon Schubert 
94b6a78b7SSimon Schubert The GNU MP Library is free software; you can redistribute it and/or modify
104b6a78b7SSimon Schubert it under the terms of the GNU Lesser General Public License as published by
114b6a78b7SSimon Schubert the Free Software Foundation; either version 3 of the License, or (at your
124b6a78b7SSimon Schubert option) any later version.
134b6a78b7SSimon Schubert 
144b6a78b7SSimon Schubert The GNU MP Library is distributed in the hope that it will be useful, but
154b6a78b7SSimon Schubert WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
164b6a78b7SSimon Schubert or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
174b6a78b7SSimon Schubert License for more details.
184b6a78b7SSimon Schubert 
194b6a78b7SSimon Schubert You should have received a copy of the GNU Lesser General Public License
204b6a78b7SSimon Schubert along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
214b6a78b7SSimon Schubert 
224b6a78b7SSimon Schubert #include "gmp.h"
234b6a78b7SSimon Schubert #include "gmp-impl.h"
244b6a78b7SSimon Schubert #include "longlong.h"
254b6a78b7SSimon Schubert 
264b6a78b7SSimon Schubert static const unsigned char primegap[] =
274b6a78b7SSimon Schubert {
284b6a78b7SSimon Schubert   2,2,4,2,4,2,4,6,2,6,4,2,4,6,6,2,6,4,2,6,4,6,8,4,2,4,2,4,14,4,6,
294b6a78b7SSimon Schubert   2,10,2,6,6,4,6,6,2,10,2,4,2,12,12,4,2,4,6,2,10,6,6,6,2,6,4,2,10,14,4,2,
304b6a78b7SSimon Schubert   4,14,6,10,2,4,6,8,6,6,4,6,8,4,8,10,2,10,2,6,4,6,8,4,2,4,12,8,4,8,4,6,
314b6a78b7SSimon Schubert   12,2,18,6,10,6,6,2,6,10,6,6,2,6,6,4,2,12,10,2,4,6,6,2,12,4,6,8,10,8,10,8,
324b6a78b7SSimon Schubert   6,6,4,8,6,4,8,4,14,10,12,2,10,2,4,2,10,14,4,2,4,14,4,2,4,20,4,8,10,8,4,6,
334b6a78b7SSimon Schubert   6,14,4,6,6,8,6,12
344b6a78b7SSimon Schubert };
354b6a78b7SSimon Schubert 
364b6a78b7SSimon Schubert #define NUMBER_OF_PRIMES 167
374b6a78b7SSimon Schubert 
384b6a78b7SSimon Schubert void
mpz_nextprime(mpz_ptr p,mpz_srcptr n)394b6a78b7SSimon Schubert mpz_nextprime (mpz_ptr p, mpz_srcptr n)
404b6a78b7SSimon Schubert {
414b6a78b7SSimon Schubert   unsigned short *moduli;
424b6a78b7SSimon Schubert   unsigned long difference;
434b6a78b7SSimon Schubert   int i;
444b6a78b7SSimon Schubert   unsigned prime_limit;
454b6a78b7SSimon Schubert   unsigned long prime;
464b6a78b7SSimon Schubert   int cnt;
474b6a78b7SSimon Schubert   mp_size_t pn;
4854028e53SJohn Marino   mp_bitcnt_t nbits;
494b6a78b7SSimon Schubert   unsigned incr;
504b6a78b7SSimon Schubert   TMP_SDECL;
514b6a78b7SSimon Schubert 
524b6a78b7SSimon Schubert   /* First handle tiny numbers */
534b6a78b7SSimon Schubert   if (mpz_cmp_ui (n, 2) < 0)
544b6a78b7SSimon Schubert     {
554b6a78b7SSimon Schubert       mpz_set_ui (p, 2);
564b6a78b7SSimon Schubert       return;
574b6a78b7SSimon Schubert     }
584b6a78b7SSimon Schubert   mpz_add_ui (p, n, 1);
594b6a78b7SSimon Schubert   mpz_setbit (p, 0);
604b6a78b7SSimon Schubert 
614b6a78b7SSimon Schubert   if (mpz_cmp_ui (p, 7) <= 0)
624b6a78b7SSimon Schubert     return;
634b6a78b7SSimon Schubert 
644b6a78b7SSimon Schubert   pn = SIZ(p);
654b6a78b7SSimon Schubert   count_leading_zeros (cnt, PTR(p)[pn - 1]);
664b6a78b7SSimon Schubert   nbits = pn * GMP_NUMB_BITS - (cnt - GMP_NAIL_BITS);
674b6a78b7SSimon Schubert   if (nbits / 2 >= NUMBER_OF_PRIMES)
684b6a78b7SSimon Schubert     prime_limit = NUMBER_OF_PRIMES - 1;
694b6a78b7SSimon Schubert   else
704b6a78b7SSimon Schubert     prime_limit = nbits / 2;
714b6a78b7SSimon Schubert 
724b6a78b7SSimon Schubert   TMP_SMARK;
734b6a78b7SSimon Schubert 
744b6a78b7SSimon Schubert   /* Compute residues modulo small odd primes */
754b6a78b7SSimon Schubert   moduli = TMP_SALLOC_TYPE (prime_limit * sizeof moduli[0], unsigned short);
764b6a78b7SSimon Schubert 
774b6a78b7SSimon Schubert   for (;;)
784b6a78b7SSimon Schubert     {
794b6a78b7SSimon Schubert       /* FIXME: Compute lazily? */
804b6a78b7SSimon Schubert       prime = 3;
814b6a78b7SSimon Schubert       for (i = 0; i < prime_limit; i++)
824b6a78b7SSimon Schubert 	{
834b6a78b7SSimon Schubert 	  moduli[i] = mpz_fdiv_ui (p, prime);
844b6a78b7SSimon Schubert 	  prime += primegap[i];
854b6a78b7SSimon Schubert 	}
864b6a78b7SSimon Schubert 
874b6a78b7SSimon Schubert #define INCR_LIMIT 0x10000	/* deep science */
884b6a78b7SSimon Schubert 
894b6a78b7SSimon Schubert       for (difference = incr = 0; incr < INCR_LIMIT; difference += 2)
904b6a78b7SSimon Schubert 	{
914b6a78b7SSimon Schubert 	  /* First check residues */
924b6a78b7SSimon Schubert 	  prime = 3;
934b6a78b7SSimon Schubert 	  for (i = 0; i < prime_limit; i++)
944b6a78b7SSimon Schubert 	    {
954b6a78b7SSimon Schubert 	      unsigned r;
964b6a78b7SSimon Schubert 	      /* FIXME: Reduce moduli + incr and store back, to allow for
974b6a78b7SSimon Schubert 		 division-free reductions.  Alternatively, table primes[]'s
984b6a78b7SSimon Schubert 		 inverses (mod 2^16).  */
994b6a78b7SSimon Schubert 	      r = (moduli[i] + incr) % prime;
1004b6a78b7SSimon Schubert 	      prime += primegap[i];
1014b6a78b7SSimon Schubert 
1024b6a78b7SSimon Schubert 	      if (r == 0)
1034b6a78b7SSimon Schubert 		goto next;
1044b6a78b7SSimon Schubert 	    }
1054b6a78b7SSimon Schubert 
1064b6a78b7SSimon Schubert 	  mpz_add_ui (p, p, difference);
1074b6a78b7SSimon Schubert 	  difference = 0;
1084b6a78b7SSimon Schubert 
1094b6a78b7SSimon Schubert 	  /* Miller-Rabin test */
110*d2d4b659SJohn Marino 	  if (mpz_millerrabin (p, 25))
1114b6a78b7SSimon Schubert 	    goto done;
1124b6a78b7SSimon Schubert 	next:;
1134b6a78b7SSimon Schubert 	  incr += 2;
1144b6a78b7SSimon Schubert 	}
1154b6a78b7SSimon Schubert       mpz_add_ui (p, p, difference);
1164b6a78b7SSimon Schubert       difference = 0;
1174b6a78b7SSimon Schubert     }
1184b6a78b7SSimon Schubert  done:
1194b6a78b7SSimon Schubert   TMP_SFREE;
1204b6a78b7SSimon Schubert }
121