gen-fac.c revision 1.1 1 1.1 mrg /* Generate data for combinatorics: fac_ui, bin_uiui, ...
2 1.1 mrg
3 1.1 mrg Copyright 2002, 2011, 2012 Free Software Foundation, Inc.
4 1.1 mrg
5 1.1 mrg This file is part of the GNU MP Library.
6 1.1 mrg
7 1.1 mrg The GNU MP Library is free software; you can redistribute it and/or modify
8 1.1 mrg it under the terms of the GNU Lesser General Public License as published by
9 1.1 mrg the Free Software Foundation; either version 3 of the License, or (at your
10 1.1 mrg option) any later version.
11 1.1 mrg
12 1.1 mrg The GNU MP Library is distributed in the hope that it will be useful, but
13 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 1.1 mrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 1.1 mrg License for more details.
16 1.1 mrg
17 1.1 mrg You should have received a copy of the GNU Lesser General Public License
18 1.1 mrg along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
19 1.1 mrg
20 1.1 mrg #include <stdio.h>
21 1.1 mrg #include <stdlib.h>
22 1.1 mrg
23 1.1 mrg #include "bootstrap.c"
24 1.1 mrg
25 1.1 mrg int
26 1.1 mrg mpz_remove_twos (mpz_t x)
27 1.1 mrg {
28 1.1 mrg int r = 0;
29 1.1 mrg for (;mpz_even_p (x);r++)
30 1.1 mrg mpz_tdiv_q_2exp (x, x, 1);
31 1.1 mrg return r;
32 1.1 mrg }
33 1.1 mrg
34 1.1 mrg /* returns 0 on success */
35 1.1 mrg int
36 1.1 mrg gen_consts (int numb, int nail, int limb)
37 1.1 mrg {
38 1.1 mrg mpz_t x, mask, y, last;
39 1.1 mrg unsigned long a, b;
40 1.1 mrg unsigned long ofl, ofe;
41 1.1 mrg
42 1.1 mrg printf ("/* This file is automatically generated by gen-fac.c */\n\n");
43 1.1 mrg printf ("#if GMP_NUMB_BITS != %d\n", numb);
44 1.1 mrg printf ("Error , error this data is for %d GMP_NUMB_BITS only\n", numb);
45 1.1 mrg printf ("#endif\n");
46 1.1 mrg #if 0
47 1.1 mrg printf ("#if GMP_LIMB_BITS != %d\n", limb);
48 1.1 mrg printf ("Error , error this data is for %d GMP_LIMB_BITS only\n", limb);
49 1.1 mrg printf ("#endif\n");
50 1.1 mrg #endif
51 1.1 mrg
52 1.1 mrg printf
53 1.1 mrg ("/* This table is 0!,1!,2!,3!,...,n! where n! has <= GMP_NUMB_BITS bits */\n");
54 1.1 mrg printf
55 1.1 mrg ("#define ONE_LIMB_FACTORIAL_TABLE CNST_LIMB(0x1),CNST_LIMB(0x1");
56 1.1 mrg mpz_init_set_ui (x, 1);
57 1.1 mrg mpz_init (last);
58 1.1 mrg for (b = 2;; b++)
59 1.1 mrg {
60 1.1 mrg mpz_mul_ui (x, x, b); /* so b!=a */
61 1.1 mrg if (mpz_sizeinbase (x, 2) > numb)
62 1.1 mrg break;
63 1.1 mrg printf ("),CNST_LIMB(0x");
64 1.1 mrg mpz_out_str (stdout, 16, x);
65 1.1 mrg }
66 1.1 mrg printf (")\n");
67 1.1 mrg
68 1.1 mrg printf
69 1.1 mrg ("\n/* This table is 0!,1!,2!/2,3!/2,...,n!/2^sn where n!/2^sn is an */\n");
70 1.1 mrg printf
71 1.1 mrg ("/* odd integer for each n, and n!/2^sn has <= GMP_NUMB_BITS bits */\n");
72 1.1 mrg printf
73 1.1 mrg ("#define ONE_LIMB_ODD_FACTORIAL_TABLE CNST_LIMB(0x1),CNST_LIMB(0x1),CNST_LIMB(0x1");
74 1.1 mrg mpz_set_ui (x, 1);
75 1.1 mrg for (b = 3;; b++)
76 1.1 mrg {
77 1.1 mrg for (a = b; (a & 1) == 0; a >>= 1);
78 1.1 mrg mpz_set (last, x);
79 1.1 mrg mpz_mul_ui (x, x, a);
80 1.1 mrg if (mpz_sizeinbase (x, 2) > numb)
81 1.1 mrg break;
82 1.1 mrg printf ("),CNST_LIMB(0x");
83 1.1 mrg mpz_out_str (stdout, 16, x);
84 1.1 mrg }
85 1.1 mrg printf (")\n");
86 1.1 mrg printf
87 1.1 mrg ("#define ODD_FACTORIAL_TABLE_MAX CNST_LIMB(0x");
88 1.1 mrg mpz_out_str (stdout, 16, last);
89 1.1 mrg printf (")\n");
90 1.1 mrg
91 1.1 mrg ofl = b - 1;
92 1.1 mrg printf
93 1.1 mrg ("#define ODD_FACTORIAL_TABLE_LIMIT (%lu)\n", ofl);
94 1.1 mrg mpz_init (mask);
95 1.1 mrg mpz_setbit (mask, numb);
96 1.1 mrg mpz_sub_ui (mask, mask, 1);
97 1.1 mrg printf
98 1.1 mrg ("\n/* Previous table, continued, values modulo 2^GMP_NUMB_BITS */\n");
99 1.1 mrg printf
100 1.1 mrg ("#define ONE_LIMB_ODD_FACTORIAL_EXTTABLE CNST_LIMB(0x");
101 1.1 mrg mpz_and (x, x, mask);
102 1.1 mrg mpz_out_str (stdout, 16, x);
103 1.1 mrg mpz_init (y);
104 1.1 mrg mpz_bin_uiui (y, b, b/2);
105 1.1 mrg b++;
106 1.1 mrg for (;; b++)
107 1.1 mrg {
108 1.1 mrg for (a = b; (a & 1) == 0; a >>= 1);
109 1.1 mrg if (a == b) {
110 1.1 mrg mpz_divexact_ui (y, y, a/2+1);
111 1.1 mrg mpz_mul_ui (y, y, a);
112 1.1 mrg } else
113 1.1 mrg mpz_mul_2exp (y, y, 1);
114 1.1 mrg if (mpz_sizeinbase (y, 2) > numb)
115 1.1 mrg break;
116 1.1 mrg mpz_mul_ui (x, x, a);
117 1.1 mrg mpz_and (x, x, mask);
118 1.1 mrg printf ("),CNST_LIMB(0x");
119 1.1 mrg mpz_out_str (stdout, 16, x);
120 1.1 mrg }
121 1.1 mrg printf (")\n");
122 1.1 mrg ofe = b - 1;
123 1.1 mrg printf
124 1.1 mrg ("#define ODD_FACTORIAL_EXTTABLE_LIMIT (%lu)\n", ofe);
125 1.1 mrg
126 1.1 mrg printf
127 1.1 mrg ("\n/* This table is 1!!,3!!,...,(2n+1)!! where (2n+1)!! has <= GMP_NUMB_BITS bits */\n");
128 1.1 mrg printf
129 1.1 mrg ("#define ONE_LIMB_ODD_DOUBLEFACTORIAL_TABLE CNST_LIMB(0x1");
130 1.1 mrg mpz_set_ui (x, 1);
131 1.1 mrg for (b = 3;; b+=2)
132 1.1 mrg {
133 1.1 mrg mpz_set (last, x);
134 1.1 mrg mpz_mul_ui (x, x, b);
135 1.1 mrg if (mpz_sizeinbase (x, 2) > numb)
136 1.1 mrg break;
137 1.1 mrg printf ("),CNST_LIMB(0x");
138 1.1 mrg mpz_out_str (stdout, 16, x);
139 1.1 mrg }
140 1.1 mrg printf (")\n");
141 1.1 mrg printf
142 1.1 mrg ("#define ODD_DOUBLEFACTORIAL_TABLE_MAX CNST_LIMB(0x");
143 1.1 mrg mpz_out_str (stdout, 16, last);
144 1.1 mrg printf (")\n");
145 1.1 mrg
146 1.1 mrg printf
147 1.1 mrg ("#define ODD_DOUBLEFACTORIAL_TABLE_LIMIT (%lu)\n", b - 2);
148 1.1 mrg
149 1.1 mrg printf
150 1.1 mrg ("\n/* This table x_1, x_2,... contains values s.t. x_n^n has <= GMP_NUMB_BITS bits */\n");
151 1.1 mrg printf
152 1.1 mrg ("#define NTH_ROOT_NUMB_MASK_TABLE (GMP_NUMB_MASK");
153 1.1 mrg for (b = 2;b <= 8; b++)
154 1.1 mrg {
155 1.1 mrg mpz_root (x, mask, b);
156 1.1 mrg printf ("),CNST_LIMB(0x");
157 1.1 mrg mpz_out_str (stdout, 16, x);
158 1.1 mrg }
159 1.1 mrg printf (")\n");
160 1.1 mrg
161 1.1 mrg mpz_add_ui (mask, mask, 1);
162 1.1 mrg printf
163 1.1 mrg ("\n/* This table contains inverses of odd factorials, modulo 2^GMP_NUMB_BITS */\n");
164 1.1 mrg printf
165 1.1 mrg ("\n/* It begins with (2!/2)^-1=1 */\n");
166 1.1 mrg printf
167 1.1 mrg ("#define ONE_LIMB_ODD_FACTORIAL_INVERSES_TABLE CNST_LIMB(0x1");
168 1.1 mrg mpz_set_ui (x, 1);
169 1.1 mrg for (b = 3;b <= ofe - 2; b++)
170 1.1 mrg {
171 1.1 mrg for (a = b; (a & 1) == 0; a >>= 1);
172 1.1 mrg mpz_mul_ui (x, x, a);
173 1.1 mrg mpz_invert (y, x, mask);
174 1.1 mrg printf ("),CNST_LIMB(0x");
175 1.1 mrg mpz_out_str (stdout, 16, y);
176 1.1 mrg }
177 1.1 mrg printf (")\n");
178 1.1 mrg
179 1.1 mrg ofe = (ofe / 16 + 1) * 16;
180 1.1 mrg
181 1.1 mrg printf
182 1.1 mrg ("\n/* This table contains 2n-popc(2n) for small n */\n");
183 1.1 mrg printf
184 1.1 mrg ("\n/* It begins with 2-1=1 (n=1) */\n");
185 1.1 mrg printf
186 1.1 mrg ("#define TABLE_2N_MINUS_POPC_2N 1");
187 1.1 mrg for (b = 4; b <= ofe; b += 2)
188 1.1 mrg {
189 1.1 mrg mpz_set_ui (x, b);
190 1.1 mrg printf (",%lu",b - mpz_popcount (x));
191 1.1 mrg }
192 1.1 mrg printf ("\n");
193 1.1 mrg printf
194 1.1 mrg ("#define TABLE_LIMIT_2N_MINUS_POPC_2N %lu\n", ofe + 1);
195 1.1 mrg
196 1.1 mrg
197 1.1 mrg ofl = (ofl + 1) / 2;
198 1.1 mrg printf
199 1.1 mrg ("#define ODD_CENTRAL_BINOMIAL_OFFSET (%lu)\n", ofl);
200 1.1 mrg printf
201 1.1 mrg ("\n/* This table contains binomial(2k,k)/2^t */\n");
202 1.1 mrg printf
203 1.1 mrg ("\n/* It begins with ODD_CENTRAL_BINOMIAL_TABLE_MIN */\n");
204 1.1 mrg printf
205 1.1 mrg ("#define ONE_LIMB_ODD_CENTRAL_BINOMIAL_TABLE ");
206 1.1 mrg for (b = ofl;; b++)
207 1.1 mrg {
208 1.1 mrg mpz_bin_uiui (x, 2 * b, b);
209 1.1 mrg mpz_remove_twos (x);
210 1.1 mrg if (mpz_sizeinbase (x, 2) > numb)
211 1.1 mrg break;
212 1.1 mrg if (b != ofl)
213 1.1 mrg printf ("),");
214 1.1 mrg printf("CNST_LIMB(0x");
215 1.1 mrg mpz_out_str (stdout, 16, x);
216 1.1 mrg }
217 1.1 mrg printf (")\n");
218 1.1 mrg
219 1.1 mrg ofe = b - 1;
220 1.1 mrg printf
221 1.1 mrg ("#define ODD_CENTRAL_BINOMIAL_TABLE_LIMIT (%lu)\n", ofe);
222 1.1 mrg
223 1.1 mrg printf
224 1.1 mrg ("\n/* This table contains the inverses of elements in the previous table. */\n");
225 1.1 mrg printf
226 1.1 mrg ("#define ONE_LIMB_ODD_CENTRAL_BINOMIAL_INVERSE_TABLE CNST_LIMB(0x");
227 1.1 mrg for (b = ofl; b <= ofe; b++)
228 1.1 mrg {
229 1.1 mrg mpz_bin_uiui (x, 2 * b, b);
230 1.1 mrg mpz_remove_twos (x);
231 1.1 mrg mpz_invert (x, x, mask);
232 1.1 mrg mpz_out_str (stdout, 16, x);
233 1.1 mrg if (b != ofe)
234 1.1 mrg printf ("),CNST_LIMB(0x");
235 1.1 mrg }
236 1.1 mrg printf (")\n");
237 1.1 mrg
238 1.1 mrg printf
239 1.1 mrg ("\n/* This table contains the values t in the formula binomial(2k,k)/2^t */\n");
240 1.1 mrg printf
241 1.1 mrg ("#define CENTRAL_BINOMIAL_2FAC_TABLE ");
242 1.1 mrg for (b = ofl; b <= ofe; b++)
243 1.1 mrg {
244 1.1 mrg mpz_bin_uiui (x, 2 * b, b);
245 1.1 mrg printf ("%d", mpz_remove_twos (x));
246 1.1 mrg if (b != ofe)
247 1.1 mrg printf (",");
248 1.1 mrg }
249 1.1 mrg printf ("\n");
250 1.1 mrg
251 1.1 mrg #if 0
252 1.1 mrg mpz_set_ui (x, 1);
253 1.1 mrg mpz_mul_2exp (x, x, limb + 1); /* x=2^(limb+1) */
254 1.1 mrg mpz_init (y);
255 1.1 mrg mpz_set_ui (y, 10000);
256 1.1 mrg mpz_mul (x, x, y); /* x=2^(limb+1)*10^4 */
257 1.1 mrg mpz_set_ui (y, 27182); /* exp(1)*10^4 */
258 1.1 mrg mpz_tdiv_q (x, x, y); /* x=2^(limb+1)/exp(1) */
259 1.1 mrg printf ("\n/* is 2^(GMP_LIMB_BITS+1)/exp(1) */\n");
260 1.1 mrg printf ("#define FAC2OVERE CNST_LIMB(0x");
261 1.1 mrg mpz_out_str (stdout, 16, x);
262 1.1 mrg printf (")\n");
263 1.1 mrg
264 1.1 mrg
265 1.1 mrg printf
266 1.1 mrg ("\n/* FACMULn is largest odd x such that x*(x+2)*...*(x+2(n-1))<=2^GMP_NUMB_BITS-1 */\n\n");
267 1.1 mrg mpz_init (z);
268 1.1 mrg mpz_init (t);
269 1.1 mrg for (a = 2; a <= 4; a++)
270 1.1 mrg {
271 1.1 mrg mpz_set_ui (x, 1);
272 1.1 mrg mpz_mul_2exp (x, x, numb);
273 1.1 mrg mpz_root (x, x, a);
274 1.1 mrg /* so x is approx sol */
275 1.1 mrg if (mpz_even_p (x))
276 1.1 mrg mpz_sub_ui (x, x, 1);
277 1.1 mrg mpz_set_ui (y, 1);
278 1.1 mrg mpz_mul_2exp (y, y, numb);
279 1.1 mrg mpz_sub_ui (y, y, 1);
280 1.1 mrg /* decrement x until we are <= real sol */
281 1.1 mrg do
282 1.1 mrg {
283 1.1 mrg mpz_sub_ui (x, x, 2);
284 1.1 mrg odd_products (t, x, a);
285 1.1 mrg if (mpz_cmp (t, y) <= 0)
286 1.1 mrg break;
287 1.1 mrg }
288 1.1 mrg while (1);
289 1.1 mrg /* increment x until > real sol */
290 1.1 mrg do
291 1.1 mrg {
292 1.1 mrg mpz_add_ui (x, x, 2);
293 1.1 mrg odd_products (t, x, a);
294 1.1 mrg if (mpz_cmp (t, y) > 0)
295 1.1 mrg break;
296 1.1 mrg }
297 1.1 mrg while (1);
298 1.1 mrg /* dec once to get real sol */
299 1.1 mrg mpz_sub_ui (x, x, 2);
300 1.1 mrg printf ("#define FACMUL%lu CNST_LIMB(0x", a);
301 1.1 mrg mpz_out_str (stdout, 16, x);
302 1.1 mrg printf (")\n");
303 1.1 mrg }
304 1.1 mrg #endif
305 1.1 mrg
306 1.1 mrg return 0;
307 1.1 mrg }
308 1.1 mrg
309 1.1 mrg int
310 1.1 mrg main (int argc, char *argv[])
311 1.1 mrg {
312 1.1 mrg int nail_bits, limb_bits, numb_bits;
313 1.1 mrg
314 1.1 mrg if (argc != 3)
315 1.1 mrg {
316 1.1 mrg fprintf (stderr, "Usage: gen-fac_ui limbbits nailbits\n");
317 1.1 mrg exit (1);
318 1.1 mrg }
319 1.1 mrg limb_bits = atoi (argv[1]);
320 1.1 mrg nail_bits = atoi (argv[2]);
321 1.1 mrg numb_bits = limb_bits - nail_bits;
322 1.1 mrg if (limb_bits < 2 || nail_bits < 0 || numb_bits < 1)
323 1.1 mrg {
324 1.1 mrg fprintf (stderr, "Invalid limb/nail bits %d,%d\n", limb_bits,
325 1.1 mrg nail_bits);
326 1.1 mrg exit (1);
327 1.1 mrg }
328 1.1 mrg gen_consts (numb_bits, nail_bits, limb_bits);
329 1.1 mrg return 0;
330 1.1 mrg }
331