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