Blame gen-trialdivtab.c

Packit 15dc08
/* gen-trialdivtab.c
Packit 15dc08
Packit 15dc08
   Contributed to the GNU project by Torbjorn Granlund.
Packit 15dc08
Packit 15dc08
Copyright 2009, 2012, 2013 Free Software Foundation, Inc.
Packit 15dc08
Packit 15dc08
This file is part of the GNU MP Library.
Packit 15dc08
Packit 15dc08
The GNU MP Library is free software; you can redistribute it and/or modify
Packit 15dc08
it under the terms of either:
Packit 15dc08
Packit 15dc08
  * the GNU Lesser General Public License as published by the Free
Packit 15dc08
    Software Foundation; either version 3 of the License, or (at your
Packit 15dc08
    option) any later version.
Packit 15dc08
Packit 15dc08
or
Packit 15dc08
Packit 15dc08
  * the GNU General Public License as published by the Free Software
Packit 15dc08
    Foundation; either version 2 of the License, or (at your option) any
Packit 15dc08
    later version.
Packit 15dc08
Packit 15dc08
or both in parallel, as here.
Packit 15dc08
Packit 15dc08
The GNU MP Library is distributed in the hope that it will be useful, but
Packit 15dc08
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
Packit 15dc08
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
Packit 15dc08
for more details.
Packit 15dc08
Packit 15dc08
You should have received copies of the GNU General Public License and the
Packit 15dc08
GNU Lesser General Public License along with the GNU MP Library.  If not,
Packit 15dc08
see https://www.gnu.org/licenses/.  */
Packit 15dc08
Packit 15dc08
/*
Packit 15dc08
  Generate tables for fast, division-free trial division for GMP.
Packit 15dc08
Packit 15dc08
  There is one main table, ptab.  It contains primes, multiplied together, and
Packit 15dc08
  several types of pre-computed inverses.  It refers to tables of the type
Packit 15dc08
  dtab, via the last two indices.  That table contains the individual primes in
Packit 15dc08
  the range, except that the primes are not actually included in the table (see
Packit 15dc08
  the P macro; it sneakingly excludes the primes themselves).  Instead, the
Packit 15dc08
  dtab tables contains tuples for each prime (modular-inverse, limit) used for
Packit 15dc08
  divisibility checks.
Packit 15dc08
Packit 15dc08
  This interface is not intended for division of very many primes, since then
Packit 15dc08
  other algorithms apply.
Packit 15dc08
*/
Packit 15dc08
Packit 15dc08
#include <stdlib.h>
Packit 15dc08
#include <stdio.h>
Packit 15dc08
#include "bootstrap.c"
Packit 15dc08
Packit 15dc08
int sumspills (mpz_t, mpz_t *, int);
Packit 15dc08
void mpn_mod_1s_4p_cps (mpz_t [7], mpz_t);
Packit 15dc08
Packit 15dc08
int limb_bits;
Packit 15dc08
Packit 15dc08
mpz_t B;
Packit 15dc08
Packit 15dc08
int
Packit 15dc08
main (int argc, char *argv[])
Packit 15dc08
{
Packit 15dc08
  unsigned long t, p;
Packit 15dc08
  mpz_t ppp, acc, inv, gmp_numb_max, tmp, Bhalf;
Packit 15dc08
  mpz_t pre[7];
Packit 15dc08
  int i;
Packit 15dc08
  int start_p, end_p, interval_start, interval_end, omitted_p;
Packit 15dc08
  const char *endtok;
Packit 15dc08
  int stop;
Packit 15dc08
  int np, start_idx;
Packit 15dc08
Packit 15dc08
  if (argc < 2)
Packit 15dc08
    {
Packit 15dc08
      fprintf (stderr, "usage: %s bits endprime\n", argv[0]);
Packit 15dc08
      exit (1);
Packit 15dc08
    }
Packit 15dc08
Packit 15dc08
  limb_bits = atoi (argv[1]);
Packit 15dc08
Packit 15dc08
  end_p = 1290;			/* default end prime */
Packit 15dc08
  if (argc == 3)
Packit 15dc08
    end_p = atoi (argv[2]);
Packit 15dc08
Packit 15dc08
  printf ("#if GMP_LIMB_BITS != %d\n", limb_bits);
Packit 15dc08
  printf ("#error This table is for GMP_LIMB_BITS = %d\n", limb_bits);
Packit 15dc08
  printf ("#endif\n\n");
Packit 15dc08
Packit 15dc08
  printf ("#if GMP_NAIL_BITS != 0\n");
Packit 15dc08
  printf ("#error This table does not support nails\n");
Packit 15dc08
  printf ("#endif\n\n");
Packit 15dc08
Packit 15dc08
  for (i = 0; i < 7; i++)
Packit 15dc08
    mpz_init (pre[i]);
Packit 15dc08
Packit 15dc08
  mpz_init_set_ui (gmp_numb_max, 1);
Packit 15dc08
  mpz_mul_2exp (gmp_numb_max, gmp_numb_max, limb_bits);
Packit 15dc08
  mpz_sub_ui (gmp_numb_max, gmp_numb_max, 1);
Packit 15dc08
Packit 15dc08
  mpz_init (tmp);
Packit 15dc08
  mpz_init (inv);
Packit 15dc08
Packit 15dc08
  mpz_init_set_ui (B, 1);  mpz_mul_2exp (B, B, limb_bits);
Packit 15dc08
  mpz_init_set_ui (Bhalf, 1);  mpz_mul_2exp (Bhalf, Bhalf, limb_bits - 1);
Packit 15dc08
Packit 15dc08
  start_p = 3;
Packit 15dc08
Packit 15dc08
  mpz_init_set_ui (ppp, 1);
Packit 15dc08
  mpz_init (acc);
Packit 15dc08
  interval_start = start_p;
Packit 15dc08
  omitted_p = 3;
Packit 15dc08
  interval_end = 0;
Packit 15dc08
Packit 15dc08
/*  printf ("static struct gmp_primes_dtab gmp_primes_dtab[] = {\n"); */
Packit 15dc08
Packit 15dc08
  printf ("#ifdef WANT_dtab\n");
Packit 15dc08
Packit 15dc08
  for (t = start_p; t <= end_p; t += 2)
Packit 15dc08
    {
Packit 15dc08
      if (! isprime (t))
Packit 15dc08
	continue;
Packit 15dc08
Packit 15dc08
      mpz_mul_ui (acc, ppp, t);
Packit 15dc08
      stop = mpz_cmp (acc, Bhalf) >= 0;
Packit 15dc08
      if (!stop)
Packit 15dc08
	{
Packit 15dc08
	  mpn_mod_1s_4p_cps (pre, acc);
Packit 15dc08
	  stop = sumspills (acc, pre + 2, 5);
Packit 15dc08
	}
Packit 15dc08
Packit 15dc08
      if (stop)
Packit 15dc08
	{
Packit 15dc08
	  for (p = interval_start; p <= interval_end; p += 2)
Packit 15dc08
	    {
Packit 15dc08
	      if (! isprime (p))
Packit 15dc08
		continue;
Packit 15dc08
Packit 15dc08
	      printf ("  P(%d,", (int) p);
Packit 15dc08
	      mpz_invert_ui_2exp (inv, p, limb_bits);
Packit 15dc08
	      printf ("CNST_LIMB(0x");  mpz_out_str (stdout, 16, inv);  printf ("),");
Packit 15dc08
Packit 15dc08
	      mpz_tdiv_q_ui (tmp, gmp_numb_max, p);
Packit 15dc08
	      printf ("CNST_LIMB(0x");  mpz_out_str (stdout, 16, tmp);
Packit 15dc08
	      printf (")),\n");
Packit 15dc08
	    }
Packit 15dc08
	  mpz_set_ui (ppp, t);
Packit 15dc08
	  interval_start = t;
Packit 15dc08
	  omitted_p = t;
Packit 15dc08
	}
Packit 15dc08
      else
Packit 15dc08
	{
Packit 15dc08
	  mpz_set (ppp, acc);
Packit 15dc08
	}
Packit 15dc08
      interval_end = t;
Packit 15dc08
    }
Packit 15dc08
  printf ("#define SMALLEST_OMITTED_PRIME %d\n", (int) omitted_p);
Packit 15dc08
  printf ("#endif\n");
Packit 15dc08
Packit 15dc08
  printf ("#ifdef WANT_ptab\n");
Packit 15dc08
Packit 15dc08
/*  printf ("static struct gmp_primes_ptab gmp_primes_ptab[] = {\n"); */
Packit 15dc08
Packit 15dc08
  endtok = "";
Packit 15dc08
Packit 15dc08
  mpz_set_ui (ppp, 1);
Packit 15dc08
  interval_start = start_p;
Packit 15dc08
  interval_end = 0;
Packit 15dc08
  np = 0;
Packit 15dc08
  start_idx = 0;
Packit 15dc08
  for (t = start_p; t <= end_p; t += 2)
Packit 15dc08
    {
Packit 15dc08
      if (! isprime (t))
Packit 15dc08
	continue;
Packit 15dc08
Packit 15dc08
      mpz_mul_ui (acc, ppp, t);
Packit 15dc08
Packit 15dc08
      stop = mpz_cmp (acc, Bhalf) >= 0;
Packit 15dc08
      if (!stop)
Packit 15dc08
	{
Packit 15dc08
	  mpn_mod_1s_4p_cps (pre, acc);
Packit 15dc08
	  stop = sumspills (acc, pre + 2, 5);
Packit 15dc08
	}
Packit 15dc08
Packit 15dc08
      if (stop)
Packit 15dc08
	{
Packit 15dc08
	  mpn_mod_1s_4p_cps (pre, ppp);
Packit 15dc08
	  printf ("%s", endtok);
Packit 15dc08
	  printf ("  {CNST_LIMB(0x");  mpz_out_str (stdout, 16, ppp);
Packit 15dc08
	  printf ("),{CNST_LIMB(0x");  mpz_out_str (stdout, 16, pre[0]);
Packit 15dc08
	  printf ("),%d", (int) PTR(pre[1])[0]);
Packit 15dc08
	  for (i = 0; i < 5; i++)
Packit 15dc08
	    {
Packit 15dc08
	      printf (",");
Packit 15dc08
	      printf ("CNST_LIMB(0x");  mpz_out_str (stdout, 16, pre[2 + i]);
Packit 15dc08
	      printf (")");
Packit 15dc08
	    }
Packit 15dc08
	  printf ("},");
Packit 15dc08
	  printf ("%d,", start_idx);
Packit 15dc08
	  printf ("%d}", np - start_idx);
Packit 15dc08
Packit 15dc08
	  endtok = ",\n";
Packit 15dc08
	  mpz_set_ui (ppp, t);
Packit 15dc08
	  interval_start = t;
Packit 15dc08
	  start_idx = np;
Packit 15dc08
	}
Packit 15dc08
      else
Packit 15dc08
	{
Packit 15dc08
	  mpz_set (ppp, acc);
Packit 15dc08
	}
Packit 15dc08
      interval_end = t;
Packit 15dc08
      np++;
Packit 15dc08
    }
Packit 15dc08
Packit 15dc08
  printf ("\n");
Packit 15dc08
  printf ("#endif\n");
Packit 15dc08
Packit 15dc08
  return 0;
Packit 15dc08
}
Packit 15dc08
Packit 15dc08
unsigned long
Packit 15dc08
mpz_log2 (mpz_t x)
Packit 15dc08
{
Packit 15dc08
  return mpz_sgn (x) ? mpz_sizeinbase (x, 2) : 0;
Packit 15dc08
}
Packit 15dc08
Packit 15dc08
void
Packit 15dc08
mpn_mod_1s_4p_cps (mpz_t cps[7], mpz_t bparm)
Packit 15dc08
{
Packit 15dc08
  mpz_t b, bi;
Packit 15dc08
  mpz_t B1modb, B2modb, B3modb, B4modb, B5modb;
Packit 15dc08
  mpz_t t;
Packit 15dc08
  int cnt;
Packit 15dc08
Packit 15dc08
  mpz_init_set (b, bparm);
Packit 15dc08
Packit 15dc08
  cnt = limb_bits - mpz_log2 (b);
Packit 15dc08
Packit 15dc08
  mpz_init (bi);
Packit 15dc08
  mpz_init (t);
Packit 15dc08
  mpz_init (B1modb);
Packit 15dc08
  mpz_init (B2modb);
Packit 15dc08
  mpz_init (B3modb);
Packit 15dc08
  mpz_init (B4modb);
Packit 15dc08
  mpz_init (B5modb);
Packit 15dc08
Packit 15dc08
  mpz_set_ui (t, 1);
Packit 15dc08
  mpz_mul_2exp (t, t, limb_bits - cnt);
Packit 15dc08
  mpz_sub (t, t, b);
Packit 15dc08
  mpz_mul_2exp (t, t, limb_bits);
Packit 15dc08
  mpz_tdiv_q (bi, t, b);		/* bi = B^2/b, except msb */
Packit 15dc08
Packit 15dc08
  mpz_set_ui (t, 1);
Packit 15dc08
  mpz_mul_2exp (t, t, limb_bits);	/* t = B */
Packit 15dc08
  mpz_tdiv_r (B1modb, t, b);
Packit 15dc08
Packit 15dc08
  mpz_mul_2exp (t, B1modb, limb_bits);
Packit 15dc08
  mpz_tdiv_r (B2modb, t, b);
Packit 15dc08
Packit 15dc08
  mpz_mul_2exp (t, B2modb, limb_bits);
Packit 15dc08
  mpz_tdiv_r (B3modb, t, b);
Packit 15dc08
Packit 15dc08
  mpz_mul_2exp (t, B3modb, limb_bits);
Packit 15dc08
  mpz_tdiv_r (B4modb, t, b);
Packit 15dc08
Packit 15dc08
  mpz_mul_2exp (t, B4modb, limb_bits);
Packit 15dc08
  mpz_tdiv_r (B5modb, t, b);
Packit 15dc08
Packit 15dc08
  mpz_set (cps[0], bi);
Packit 15dc08
  mpz_set_ui (cps[1], cnt);
Packit 15dc08
  mpz_tdiv_q_2exp (cps[2], B1modb, 0);
Packit 15dc08
  mpz_tdiv_q_2exp (cps[3], B2modb, 0);
Packit 15dc08
  mpz_tdiv_q_2exp (cps[4], B3modb, 0);
Packit 15dc08
  mpz_tdiv_q_2exp (cps[5], B4modb, 0);
Packit 15dc08
  mpz_tdiv_q_2exp (cps[6], B5modb, 0);
Packit 15dc08
Packit 15dc08
  mpz_clear (b);
Packit 15dc08
  mpz_clear (bi);
Packit 15dc08
  mpz_clear (t);
Packit 15dc08
  mpz_clear (B1modb);
Packit 15dc08
  mpz_clear (B2modb);
Packit 15dc08
  mpz_clear (B3modb);
Packit 15dc08
  mpz_clear (B4modb);
Packit 15dc08
  mpz_clear (B5modb);
Packit 15dc08
}
Packit 15dc08
Packit 15dc08
int
Packit 15dc08
sumspills (mpz_t ppp, mpz_t *a, int n)
Packit 15dc08
{
Packit 15dc08
  mpz_t s;
Packit 15dc08
  int i, ret;
Packit 15dc08
Packit 15dc08
  mpz_init_set (s, a[0]);
Packit 15dc08
Packit 15dc08
  for (i = 1; i < n; i++)
Packit 15dc08
    {
Packit 15dc08
      mpz_add (s, s, a[i]);
Packit 15dc08
    }
Packit 15dc08
  ret = mpz_cmp (s, B) >= 0;
Packit 15dc08
  mpz_clear (s);
Packit 15dc08
Packit 15dc08
  return ret;
Packit 15dc08
}