//
// LiDIA - a library for computational number theory
//   Copyright (c) 1994, 1995 by the LiDIA Group
//
// File        : next_prime.c 
// Author      : Andreas M"uller (AM)
// Last change : AM, Feb 7 1995, initial version
//               TP, Feb 7 1995, added condition for x < 2
//

#include <LiDIA/bigint.h>

bigint next_prime(const bigint & x)
{
   long zmod3, zmod5, zmod7, zmod11, zmod13, zmod17, zmod19;
   bigint prim;

   if (x.is_one() || x.is_le_zero())
   {
     prim.assign(2);
     return prim;
   }
 
   long sx;

   if (!x.longify(sx))     // convert x to long
      {
      if (sx <= 19)
	 {
         if (sx < 3)  return bigint(3);
	 if (sx < 5)  return bigint(5);
	 if (sx < 7)  return bigint(7);
	 if (sx < 11)  return bigint(11);
	 if (sx < 13)  return bigint(13);
	 if (sx < 17)  return bigint(17);
	 if (sx < 19)  return bigint(19);
	 return bigint(23);
         }
      }

   // prim = x; make prim odd
   prim.assign(x);
   inc(prim);
   if ( prim.is_even() )   
     inc(prim);
   
   // initialize modular counters
   zmod3 = remainder(prim, 3);
   zmod5 = remainder(prim, 5);
   zmod7 = remainder(prim, 7);
   zmod11 = remainder(prim, 11);
   zmod13 = remainder(prim, 13);
   zmod17 = remainder(prim, 17);  
   zmod19 = remainder(prim, 19);
   
   // while not a prime number
   while ( !is_prime(prim, 4) )
   {
      do
      {
	 // increase prim by 2
	 add(prim, prim, 2);
	 
	 zmod3 = (zmod3 + 2)%3; 
	 zmod5 = (zmod5 + 2)%5; 
	 zmod7 = (zmod7 + 2)%7; 
	 zmod11 = (zmod11 + 2)%11; 
	 zmod13 = (zmod13 + 2)%13;
	 zmod17 = (zmod17 + 2)%17;
	 zmod19 = (zmod19 + 2)%19;
      }
      // until it is not divisible by small primes
      while ( !(zmod3 && zmod5 && 
		zmod7 && zmod11 && 
		zmod13 && zmod17 && 
		zmod19) );  
   }
   return prim;
}
