github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/gen-trialdivtab.c (about)

     1  /* gen-trialdivtab.c
     2  
     3     Contributed to the GNU project by Torbjorn Granlund.
     4  
     5  Copyright 2009, 2012, 2013 Free Software Foundation, Inc.
     6  
     7  This file is part of the GNU MP Library.
     8  
     9  The GNU MP Library is free software; you can redistribute it and/or modify
    10  it under the terms of either:
    11  
    12    * the GNU Lesser General Public License as published by the Free
    13      Software Foundation; either version 3 of the License, or (at your
    14      option) any later version.
    15  
    16  or
    17  
    18    * the GNU General Public License as published by the Free Software
    19      Foundation; either version 2 of the License, or (at your option) any
    20      later version.
    21  
    22  or both in parallel, as here.
    23  
    24  The GNU MP Library is distributed in the hope that it will be useful, but
    25  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    26  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    27  for more details.
    28  
    29  You should have received copies of the GNU General Public License and the
    30  GNU Lesser General Public License along with the GNU MP Library.  If not,
    31  see https://www.gnu.org/licenses/.  */
    32  
    33  /*
    34    Generate tables for fast, division-free trial division for GMP.
    35  
    36    There is one main table, ptab.  It contains primes, multiplied together, and
    37    several types of pre-computed inverses.  It refers to tables of the type
    38    dtab, via the last two indices.  That table contains the individual primes in
    39    the range, except that the primes are not actually included in the table (see
    40    the P macro; it sneakingly excludes the primes themselves).  Instead, the
    41    dtab tables contains tuples for each prime (modular-inverse, limit) used for
    42    divisibility checks.
    43  
    44    This interface is not intended for division of very many primes, since then
    45    other algorithms apply.
    46  */
    47  
    48  #include <stdlib.h>
    49  #include <stdio.h>
    50  #include "bootstrap.c"
    51  
    52  int sumspills (mpz_t, mpz_t *, int);
    53  void mpn_mod_1s_4p_cps (mpz_t [7], mpz_t);
    54  
    55  int limb_bits;
    56  
    57  mpz_t B;
    58  
    59  int
    60  main (int argc, char *argv[])
    61  {
    62    unsigned long t, p;
    63    mpz_t ppp, acc, inv, gmp_numb_max, tmp, Bhalf;
    64    mpz_t pre[7];
    65    int i;
    66    int start_p, end_p, interval_start, interval_end, omitted_p;
    67    const char *endtok;
    68    int stop;
    69    int np, start_idx;
    70  
    71    if (argc < 2)
    72      {
    73        fprintf (stderr, "usage: %s bits endprime\n", argv[0]);
    74        exit (1);
    75      }
    76  
    77    limb_bits = atoi (argv[1]);
    78  
    79    end_p = 1290;			/* default end prime */
    80    if (argc == 3)
    81      end_p = atoi (argv[2]);
    82  
    83    printf ("#if GMP_LIMB_BITS != %d\n", limb_bits);
    84    printf ("#error This table is for GMP_LIMB_BITS = %d\n", limb_bits);
    85    printf ("#endif\n\n");
    86  
    87    printf ("#if GMP_NAIL_BITS != 0\n");
    88    printf ("#error This table does not support nails\n");
    89    printf ("#endif\n\n");
    90  
    91    for (i = 0; i < 7; i++)
    92      mpz_init (pre[i]);
    93  
    94    mpz_init_set_ui (gmp_numb_max, 1);
    95    mpz_mul_2exp (gmp_numb_max, gmp_numb_max, limb_bits);
    96    mpz_sub_ui (gmp_numb_max, gmp_numb_max, 1);
    97  
    98    mpz_init (tmp);
    99    mpz_init (inv);
   100  
   101    mpz_init_set_ui (B, 1);  mpz_mul_2exp (B, B, limb_bits);
   102    mpz_init_set_ui (Bhalf, 1);  mpz_mul_2exp (Bhalf, Bhalf, limb_bits - 1);
   103  
   104    start_p = 3;
   105  
   106    mpz_init_set_ui (ppp, 1);
   107    mpz_init (acc);
   108    interval_start = start_p;
   109    omitted_p = 3;
   110    interval_end = 0;
   111  
   112  /*  printf ("static struct gmp_primes_dtab gmp_primes_dtab[] = {\n"); */
   113  
   114    printf ("#ifdef WANT_dtab\n");
   115  
   116    for (t = start_p; t <= end_p; t += 2)
   117      {
   118        if (! isprime (t))
   119  	continue;
   120  
   121        mpz_mul_ui (acc, ppp, t);
   122        stop = mpz_cmp (acc, Bhalf) >= 0;
   123        if (!stop)
   124  	{
   125  	  mpn_mod_1s_4p_cps (pre, acc);
   126  	  stop = sumspills (acc, pre + 2, 5);
   127  	}
   128  
   129        if (stop)
   130  	{
   131  	  for (p = interval_start; p <= interval_end; p += 2)
   132  	    {
   133  	      if (! isprime (p))
   134  		continue;
   135  
   136  	      printf ("  P(%d,", (int) p);
   137  	      mpz_invert_ui_2exp (inv, p, limb_bits);
   138  	      printf ("CNST_LIMB(0x");  mpz_out_str (stdout, 16, inv);  printf ("),");
   139  
   140  	      mpz_tdiv_q_ui (tmp, gmp_numb_max, p);
   141  	      printf ("CNST_LIMB(0x");  mpz_out_str (stdout, 16, tmp);
   142  	      printf (")),\n");
   143  	    }
   144  	  mpz_set_ui (ppp, t);
   145  	  interval_start = t;
   146  	  omitted_p = t;
   147  	}
   148        else
   149  	{
   150  	  mpz_set (ppp, acc);
   151  	}
   152        interval_end = t;
   153      }
   154    printf ("#define SMALLEST_OMITTED_PRIME %d\n", (int) omitted_p);
   155    printf ("#endif\n");
   156  
   157    printf ("#ifdef WANT_ptab\n");
   158  
   159  /*  printf ("static struct gmp_primes_ptab gmp_primes_ptab[] = {\n"); */
   160  
   161    endtok = "";
   162  
   163    mpz_set_ui (ppp, 1);
   164    interval_start = start_p;
   165    interval_end = 0;
   166    np = 0;
   167    start_idx = 0;
   168    for (t = start_p; t <= end_p; t += 2)
   169      {
   170        if (! isprime (t))
   171  	continue;
   172  
   173        mpz_mul_ui (acc, ppp, t);
   174  
   175        stop = mpz_cmp (acc, Bhalf) >= 0;
   176        if (!stop)
   177  	{
   178  	  mpn_mod_1s_4p_cps (pre, acc);
   179  	  stop = sumspills (acc, pre + 2, 5);
   180  	}
   181  
   182        if (stop)
   183  	{
   184  	  mpn_mod_1s_4p_cps (pre, ppp);
   185  	  printf ("%s", endtok);
   186  	  printf ("  {CNST_LIMB(0x");  mpz_out_str (stdout, 16, ppp);
   187  	  printf ("),{CNST_LIMB(0x");  mpz_out_str (stdout, 16, pre[0]);
   188  	  printf ("),%d", (int) PTR(pre[1])[0]);
   189  	  for (i = 0; i < 5; i++)
   190  	    {
   191  	      printf (",");
   192  	      printf ("CNST_LIMB(0x");  mpz_out_str (stdout, 16, pre[2 + i]);
   193  	      printf (")");
   194  	    }
   195  	  printf ("},");
   196  	  printf ("%d,", start_idx);
   197  	  printf ("%d}", np - start_idx);
   198  
   199  	  endtok = ",\n";
   200  	  mpz_set_ui (ppp, t);
   201  	  interval_start = t;
   202  	  start_idx = np;
   203  	}
   204        else
   205  	{
   206  	  mpz_set (ppp, acc);
   207  	}
   208        interval_end = t;
   209        np++;
   210      }
   211  
   212    printf ("\n");
   213    printf ("#endif\n");
   214  
   215    return 0;
   216  }
   217  
   218  unsigned long
   219  mpz_log2 (mpz_t x)
   220  {
   221    return mpz_sgn (x) ? mpz_sizeinbase (x, 2) : 0;
   222  }
   223  
   224  void
   225  mpn_mod_1s_4p_cps (mpz_t cps[7], mpz_t bparm)
   226  {
   227    mpz_t b, bi;
   228    mpz_t B1modb, B2modb, B3modb, B4modb, B5modb;
   229    mpz_t t;
   230    int cnt;
   231  
   232    mpz_init_set (b, bparm);
   233  
   234    cnt = limb_bits - mpz_log2 (b);
   235  
   236    mpz_init (bi);
   237    mpz_init (t);
   238    mpz_init (B1modb);
   239    mpz_init (B2modb);
   240    mpz_init (B3modb);
   241    mpz_init (B4modb);
   242    mpz_init (B5modb);
   243  
   244    mpz_set_ui (t, 1);
   245    mpz_mul_2exp (t, t, limb_bits - cnt);
   246    mpz_sub (t, t, b);
   247    mpz_mul_2exp (t, t, limb_bits);
   248    mpz_tdiv_q (bi, t, b);		/* bi = B^2/b, except msb */
   249  
   250    mpz_set_ui (t, 1);
   251    mpz_mul_2exp (t, t, limb_bits);	/* t = B */
   252    mpz_tdiv_r (B1modb, t, b);
   253  
   254    mpz_mul_2exp (t, B1modb, limb_bits);
   255    mpz_tdiv_r (B2modb, t, b);
   256  
   257    mpz_mul_2exp (t, B2modb, limb_bits);
   258    mpz_tdiv_r (B3modb, t, b);
   259  
   260    mpz_mul_2exp (t, B3modb, limb_bits);
   261    mpz_tdiv_r (B4modb, t, b);
   262  
   263    mpz_mul_2exp (t, B4modb, limb_bits);
   264    mpz_tdiv_r (B5modb, t, b);
   265  
   266    mpz_set (cps[0], bi);
   267    mpz_set_ui (cps[1], cnt);
   268    mpz_tdiv_q_2exp (cps[2], B1modb, 0);
   269    mpz_tdiv_q_2exp (cps[3], B2modb, 0);
   270    mpz_tdiv_q_2exp (cps[4], B3modb, 0);
   271    mpz_tdiv_q_2exp (cps[5], B4modb, 0);
   272    mpz_tdiv_q_2exp (cps[6], B5modb, 0);
   273  
   274    mpz_clear (b);
   275    mpz_clear (bi);
   276    mpz_clear (t);
   277    mpz_clear (B1modb);
   278    mpz_clear (B2modb);
   279    mpz_clear (B3modb);
   280    mpz_clear (B4modb);
   281    mpz_clear (B5modb);
   282  }
   283  
   284  int
   285  sumspills (mpz_t ppp, mpz_t *a, int n)
   286  {
   287    mpz_t s;
   288    int i, ret;
   289  
   290    mpz_init_set (s, a[0]);
   291  
   292    for (i = 1; i < n; i++)
   293      {
   294        mpz_add (s, s, a[i]);
   295      }
   296    ret = mpz_cmp (s, B) >= 0;
   297    mpz_clear (s);
   298  
   299    return ret;
   300  }