gen-trialdivtab.c
上传用户:qaz666999
上传日期:2022-08-06
资源大小:2570k
文件大小:7k
源码类别:

数学计算

开发平台:

Unix_Linux

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