/* mpz_next_prime_candidate(p,t,rnd) - compute the next likely prime > t and store that in p.

Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
Copyright 2009 Jason Moxham, Brian Gladman

This file is part of the MPIR Library.

The MPIR Library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2.1 of the License, or (at
your option) any later version.

The MPIR Library 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 Lesser General Public
License for more details.

You should have received a copy of the GNU Lesser General Public License
along with the MPIR Library; see the file COPYING.LIB.  If not, write
to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/

#include "mpir.h"
#include "gmp-impl.h"

#if 0

void 
mpz_next_prime_candidate (mpz_ptr p, mpz_srcptr t, gmp_randstate_t rnd)
{
  mpz_add_ui (p, t, 1L);
  while (! mpz_likely_prime_p (p, rnd,0))
    mpz_add_ui (p, p, 1L);
}

#else

/* This code is not yet tested.  Will be enabled some time. */

static unsigned short primes[] =
{
3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,
101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,
191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,
281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,
389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,
491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,
607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,
719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,
829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,
953,967,971,977,983,991,997
};

#define NUMBER_OF_PRIMES (sizeof(primes) / sizeof(primes[0]))

void
mpz_next_prime_candidate (mpz_ptr p, mpz_srcptr n, gmp_randstate_t rnd)
{
  unsigned short *moduli;
  unsigned long difference;
  int i, prime_limit;
  int composite;
  TMP_DECL;

  /* First handle tiny numbers */
  if (mpz_cmp_ui (n, 2) < 0)
  {
      mpz_set_ui (p, 2);
      return;
  }
  mpz_add_ui (p, n, 1);
  mpz_setbit (p, 0);

  if (mpz_cmp_ui (p, 7) <= 0)
    return;

  prime_limit = NUMBER_OF_PRIMES - 1;
  if (mpz_cmp_ui (p, primes[prime_limit]) <= 0)
  {
      int lo = 0, hi = NUMBER_OF_PRIMES - 1, mid;

      i = mpz_get_ui(p);  
      while(lo <= hi)
      {
          mid = lo + (hi - lo) / 2;
          if (i > primes[mid])
             lo = mid + 1;
          else if (i < primes[mid])
             hi = mid - 1;
          else
          {
             lo = mid;
             break;
          }
      }
      mpz_set_ui(p, primes[lo]);
      return;
  }

  TMP_MARK;
  /* Compute residues modulo small odd primes */
  moduli = (unsigned short *) TMP_ALLOC (prime_limit * sizeof moduli[0]);
  for (i = 0; i < prime_limit; i++)
    moduli[i] = mpz_fdiv_ui (p, primes[i]);
  for (difference = 0; ; difference += 2)
  {
    composite = 0;

    /* First check residues */
    for (i = 0; i < prime_limit; i++)
	{
	  int acc, pr;
	  composite |= (moduli[i] == 0);
	  acc = moduli[i] + 2;
	  pr = primes[i];
	  moduli[i] = acc >= pr ? acc - pr : acc;
	}
    if (composite)
	  continue;

    mpz_add_ui (p, p, difference);
    difference = 0;

    /* Miller-Rabin test */
    if (mpz_miller_rabin (p, 2, rnd))
	  break;
  }
  TMP_FREE;
}

#endif
