Example #1
0
void
mpz_nextprime (mpz_ptr p, mpz_srcptr n)
{
  mpz_t tmp;
  unsigned short *moduli;
  unsigned long difference;
  int i;
  int composite;

  /* 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)
    /* Just use first three entries (3,5,7) of table for small numbers */
    prime_limit = 3;
  if (prime_limit)
    {
      /* 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_millerrabin (p, 2))
	break;
    }
}
Example #2
0
int
mpz_probab_prime_p (mpz_srcptr n, int reps)
{
  mp_limb_t r;
  mpz_t n2;

  /* Handle small and negative n.  */
  if (mpz_cmp_ui (n, 1000000L) <= 0)
    {
      if (mpz_cmpabs_ui (n, 1000000L) <= 0)
	{
	  int is_prime;
	  unsigned long n0;
	  n0 = mpz_get_ui (n);
	  is_prime = n0 & (n0 > 1) ? isprime (n0) : n0 == 2;
	  return is_prime ? 2 : 0;
	}
      /* Negative number.  Negate and fall out.  */
      PTR(n2) = PTR(n);
      SIZ(n2) = -SIZ(n);
      n = n2;
    }

  /* If n is now even, it is not a prime.  */
  if (mpz_even_p (n))
    return 0;

#if defined (PP)
  /* Check if n has small factors.  */
#if defined (PP_INVERTED)
  r = MPN_MOD_OR_PREINV_MOD_1 (PTR(n), (mp_size_t) SIZ(n), (mp_limb_t) PP,
			       (mp_limb_t) PP_INVERTED);
#else
  r = mpn_mod_1 (PTR(n), (mp_size_t) SIZ(n), (mp_limb_t) PP);
#endif
  if (r % 3 == 0
#if GMP_LIMB_BITS >= 4
      || r % 5 == 0
#endif
#if GMP_LIMB_BITS >= 8
      || r % 7 == 0
#endif
#if GMP_LIMB_BITS >= 16
      || r % 11 == 0 || r % 13 == 0
#endif
#if GMP_LIMB_BITS >= 32
      || r % 17 == 0 || r % 19 == 0 || r % 23 == 0 || r % 29 == 0
#endif
#if GMP_LIMB_BITS >= 64
      || r % 31 == 0 || r % 37 == 0 || r % 41 == 0 || r % 43 == 0
      || r % 47 == 0 || r % 53 == 0
#endif
      )
    {
      return 0;
    }
#endif /* PP */

  /* Do more dividing.  We collect small primes, using umul_ppmm, until we
     overflow a single limb.  We divide our number by the small primes product,
     and look for factors in the remainder.  */
  {
    unsigned long int ln2;
    unsigned long int q;
    mp_limb_t p1, p0, p;
    unsigned int primes[15];
    int nprimes;

    nprimes = 0;
    p = 1;
    ln2 = mpz_sizeinbase (n, 2);	/* FIXME: tune this limit */
    for (q = PP_FIRST_OMITTED; q < ln2; q += 2)
      {
	if (isprime (q))
	  {
	    umul_ppmm (p1, p0, p, q);
	    if (p1 != 0)
	      {
		r = MPN_MOD_OR_MODEXACT_1_ODD (PTR(n), (mp_size_t) SIZ(n), p);
		while (--nprimes >= 0)
		  if (r % primes[nprimes] == 0)
		    {
		      ASSERT_ALWAYS (mpn_mod_1 (PTR(n), (mp_size_t) SIZ(n), (mp_limb_t) primes[nprimes]) == 0);
		      return 0;
		    }
		p = q;
		nprimes = 0;
	      }
	    else
	      {
		p = p0;
	      }
	    primes[nprimes++] = q;
	  }
      }
  }

  /* Perform a number of Miller-Rabin tests.  */
  return mpz_millerrabin (n, reps);
}
Example #3
0
int main() {
  constexpr size_t iterations = 1000;
  constexpr size_t width = 2048;
  constexpr size_t seed = 254148ul;

  std::cout
      << "This test shows speed comparison with GMP, it uses `miller_rabin` "
         "functions" << std::endl;

  std::cout << "Setup:" << std::endl;
  std::cout << "Iterations: " << iterations << std::endl;
  std::cout << "Number width: " << width << std::endl;
  std::cout << "Random seed: " << seed << std::endl;
  std::cout << std::endl;

  typedef std::chrono::nanoseconds duration_t;

  std::chrono::high_resolution_clock clock;
  std::chrono::time_point<std::chrono::high_resolution_clock> start, end;
  std::minstd_rand rnd(seed);

  {
    std::cout << "--- Testing pure `miller_rabin` tests (composite "
                 "probability "
                 "2^(-50))---" << std::endl;

    duration_t gmp_duration(0);
    duration_t primegen_duration(0);
    mpz_class j;

    for (size_t i = 0; i < iterations; ++i) {
      j = PrimeGen::Utils::independent_bits_generator<
          mpz_class, std::minstd_rand, 2048>(rnd);

      start = clock.now();
      mpz_millerrabin(j.get_mpz_t(), 25);
      end = clock.now();
      gmp_duration += std::chrono::duration_cast<duration_t>(end - start);

      start = clock.now();
      PrimeGen::Tests::miller_rabin<mpz_class, 25>(j);
      end = clock.now();
      primegen_duration += std::chrono::duration_cast<duration_t>(end - start);
    }
    std::cout << "Primegen test took: "
              << std::chrono::duration_cast<std::chrono::milliseconds>(
                     primegen_duration).count() /
                     1000.0 << " seconds" << std::endl;
    std::cout << "GMP test took: "
              << std::chrono::duration_cast<std::chrono::milliseconds>(
                     gmp_duration).count() /
                     1000.0 << " seconds" << std::endl;
    std::cout << std::endl << std::endl;
  }

  {
    std::cout << "--- Testing `miller_rabin` + trivial divisions (composite "
                 "probability "
                 "2^(-50))---" << std::endl;

    duration_t gmp_duration(0);
    duration_t primegen_duration(0);
    mpz_class j;

    for (size_t i = 0; i < iterations; ++i) {
      j = PrimeGen::Utils::independent_bits_generator<
          mpz_class, std::minstd_rand, 2048>(rnd);

      start = clock.now();
      mpz_probab_prime_p(j.get_mpz_t(), 25);
      end = clock.now();
      gmp_duration += std::chrono::duration_cast<duration_t>(end - start);

      start = clock.now();
      PrimeGen::Tests::f1000_prime_factors(j) &&
          PrimeGen::Tests::miller_rabin<mpz_class, 25>(j);
      end = clock.now();
      primegen_duration += std::chrono::duration_cast<duration_t>(end - start);
    }
    std::cout << "Primegen test took: "
              << std::chrono::duration_cast<std::chrono::milliseconds>(
                     primegen_duration).count() /
                     1000.0 << " seconds" << std::endl;
    std::cout << "GMP test took: "
              << std::chrono::duration_cast<std::chrono::milliseconds>(
                     gmp_duration).count() /
                     1000.0 << " seconds" << std::endl;
    std::cout << std::endl << std::endl;
  }

  return 0;
}
Example #4
0
int
mpz_probab_prime_p (mpz_srcptr n, int reps)
{
  mp_limb_t r;

  /* Handle small and negative n.  */
  if (mpz_cmp_ui (n, 1000000L) <= 0)
    {
      int is_prime;
      if (mpz_sgn (n) < 0)
	{
	  /* Negative number.  Negate and call ourselves.  */
	  mpz_t n2;
	  mpz_init (n2);
	  mpz_neg (n2, n);
	  is_prime = mpz_probab_prime_p (n2, reps);
	  mpz_clear (n2);
	  return is_prime;
	}
      is_prime = isprime (mpz_get_ui (n));
      return is_prime ? 2 : 0;
    }

  /* If n is now even, it is not a prime.  */
  if ((mpz_get_ui (n) & 1) == 0)
    return 0;

#if defined (PP)
  /* Check if n has small factors.  */
#if defined (PP_INVERTED)
  r = MPN_MOD_OR_PREINV_MOD_1 (PTR(n), SIZ(n), (mp_limb_t) PP,
                               (mp_limb_t) PP_INVERTED);
#else
  r = mpn_mod_1 (PTR(n), SIZ(n), (mp_limb_t) PP);
#endif
  if (r % 3 == 0
#if BITS_PER_MP_LIMB >= 4
      || r % 5 == 0
#endif
#if BITS_PER_MP_LIMB >= 8
      || r % 7 == 0
#endif
#if BITS_PER_MP_LIMB >= 16
      || r % 11 == 0 || r % 13 == 0
#endif
#if BITS_PER_MP_LIMB >= 32
      || r % 17 == 0 || r % 19 == 0 || r % 23 == 0 || r % 29 == 0
#endif
#if BITS_PER_MP_LIMB >= 64
      || r % 31 == 0 || r % 37 == 0 || r % 41 == 0 || r % 43 == 0
      || r % 47 == 0 || r % 53 == 0
#endif
      )
    {
      return 0;
    }
#endif /* PP */

  /* Do more dividing.  We collect small primes, using umul_ppmm, until we
     overflow a single limb.  We divide our number by the small primes product,
     and look for factors in the remainder.  */
  {
    unsigned long int ln2;
    unsigned long int q;
    mp_limb_t p1, p0, p;
    unsigned int primes[15];
    int nprimes;

    nprimes = 0;
    p = 1;
    ln2 = mpz_sizeinbase (n, 2) / 30; ln2 = ln2 * ln2;
    for (q = PP_FIRST_OMITTED; q < ln2; q += 2)
      {
	if (isprime (q))
	  {
	    umul_ppmm (p1, p0, p, q);
	    if (p1 != 0)
	      {
		r = mpn_mod_1 (PTR(n), SIZ(n), p);
		while (--nprimes >= 0)
		  if (r % primes[nprimes] == 0)
		    {
		      ASSERT_ALWAYS (mpn_mod_1 (PTR(n), SIZ(n), (mp_limb_t) primes[nprimes]) == 0);
		      return 0;
		    }
		p = q;
		nprimes = 0;
	      }
	    else
	      {
		p = p0;
	      }
	    primes[nprimes++] = q;
	  }
      }
  }

  /* Perform a number of Miller-Rabin tests.  */
  return mpz_millerrabin (n, reps);
}