1 /* Generate data for combinatorics: fac_ui, bin_uiui, ...
3 Copyright 2002, 2011, 2012 Free Software Foundation, Inc.
5 This file is part of the GNU MP Library.
7 The GNU MP Library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
12 The GNU MP Library is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
23 #include "bootstrap.c"
26 mpz_remove_twos (mpz_t x)
29 for (;mpz_even_p (x);r++)
30 mpz_tdiv_q_2exp (x, x, 1);
34 /* returns 0 on success */
36 gen_consts (int numb, int nail, int limb)
38 mpz_t x, mask, y, last;
40 unsigned long ofl, ofe;
42 printf ("/* This file is automatically generated by gen-fac.c */\n\n");
43 printf ("#if GMP_NUMB_BITS != %d\n", numb);
44 printf ("Error , error this data is for %d GMP_NUMB_BITS only\n", numb);
47 printf ("#if GMP_LIMB_BITS != %d\n", limb);
48 printf ("Error , error this data is for %d GMP_LIMB_BITS only\n", limb);
53 ("/* This table is 0!,1!,2!,3!,...,n! where n! has <= GMP_NUMB_BITS bits */\n");
55 ("#define ONE_LIMB_FACTORIAL_TABLE CNST_LIMB(0x1),CNST_LIMB(0x1");
56 mpz_init_set_ui (x, 1);
60 mpz_mul_ui (x, x, b); /* so b!=a */
61 if (mpz_sizeinbase (x, 2) > numb)
63 printf ("),CNST_LIMB(0x");
64 mpz_out_str (stdout, 16, x);
69 ("\n/* This table is 0!,1!,2!/2,3!/2,...,n!/2^sn where n!/2^sn is an */\n");
71 ("/* odd integer for each n, and n!/2^sn has <= GMP_NUMB_BITS bits */\n");
73 ("#define ONE_LIMB_ODD_FACTORIAL_TABLE CNST_LIMB(0x1),CNST_LIMB(0x1),CNST_LIMB(0x1");
77 for (a = b; (a & 1) == 0; a >>= 1);
80 if (mpz_sizeinbase (x, 2) > numb)
82 printf ("),CNST_LIMB(0x");
83 mpz_out_str (stdout, 16, x);
87 ("#define ODD_FACTORIAL_TABLE_MAX CNST_LIMB(0x");
88 mpz_out_str (stdout, 16, last);
93 ("#define ODD_FACTORIAL_TABLE_LIMIT (%lu)\n", ofl);
95 mpz_setbit (mask, numb);
96 mpz_sub_ui (mask, mask, 1);
98 ("\n/* Previous table, continued, values modulo 2^GMP_NUMB_BITS */\n");
100 ("#define ONE_LIMB_ODD_FACTORIAL_EXTTABLE CNST_LIMB(0x");
101 mpz_and (x, x, mask);
102 mpz_out_str (stdout, 16, x);
104 mpz_bin_uiui (y, b, b/2);
108 for (a = b; (a & 1) == 0; a >>= 1);
110 mpz_divexact_ui (y, y, a/2+1);
111 mpz_mul_ui (y, y, a);
113 mpz_mul_2exp (y, y, 1);
114 if (mpz_sizeinbase (y, 2) > numb)
116 mpz_mul_ui (x, x, a);
117 mpz_and (x, x, mask);
118 printf ("),CNST_LIMB(0x");
119 mpz_out_str (stdout, 16, x);
124 ("#define ODD_FACTORIAL_EXTTABLE_LIMIT (%lu)\n", ofe);
127 ("\n/* This table is 1!!,3!!,...,(2n+1)!! where (2n+1)!! has <= GMP_NUMB_BITS bits */\n");
129 ("#define ONE_LIMB_ODD_DOUBLEFACTORIAL_TABLE CNST_LIMB(0x1");
134 mpz_mul_ui (x, x, b);
135 if (mpz_sizeinbase (x, 2) > numb)
137 printf ("),CNST_LIMB(0x");
138 mpz_out_str (stdout, 16, x);
142 ("#define ODD_DOUBLEFACTORIAL_TABLE_MAX CNST_LIMB(0x");
143 mpz_out_str (stdout, 16, last);
147 ("#define ODD_DOUBLEFACTORIAL_TABLE_LIMIT (%lu)\n", b - 2);
150 ("\n/* This table x_1, x_2,... contains values s.t. x_n^n has <= GMP_NUMB_BITS bits */\n");
152 ("#define NTH_ROOT_NUMB_MASK_TABLE (GMP_NUMB_MASK");
153 for (b = 2;b <= 8; b++)
155 mpz_root (x, mask, b);
156 printf ("),CNST_LIMB(0x");
157 mpz_out_str (stdout, 16, x);
161 mpz_add_ui (mask, mask, 1);
163 ("\n/* This table contains inverses of odd factorials, modulo 2^GMP_NUMB_BITS */\n");
165 ("\n/* It begins with (2!/2)^-1=1 */\n");
167 ("#define ONE_LIMB_ODD_FACTORIAL_INVERSES_TABLE CNST_LIMB(0x1");
169 for (b = 3;b <= ofe - 2; b++)
171 for (a = b; (a & 1) == 0; a >>= 1);
172 mpz_mul_ui (x, x, a);
173 mpz_invert (y, x, mask);
174 printf ("),CNST_LIMB(0x");
175 mpz_out_str (stdout, 16, y);
179 ofe = (ofe / 16 + 1) * 16;
182 ("\n/* This table contains 2n-popc(2n) for small n */\n");
184 ("\n/* It begins with 2-1=1 (n=1) */\n");
186 ("#define TABLE_2N_MINUS_POPC_2N 1");
187 for (b = 4; b <= ofe; b += 2)
190 printf (",%lu",b - mpz_popcount (x));
194 ("#define TABLE_LIMIT_2N_MINUS_POPC_2N %lu\n", ofe + 1);
199 ("#define ODD_CENTRAL_BINOMIAL_OFFSET (%lu)\n", ofl);
201 ("\n/* This table contains binomial(2k,k)/2^t */\n");
203 ("\n/* It begins with ODD_CENTRAL_BINOMIAL_TABLE_MIN */\n");
205 ("#define ONE_LIMB_ODD_CENTRAL_BINOMIAL_TABLE ");
208 mpz_bin_uiui (x, 2 * b, b);
210 if (mpz_sizeinbase (x, 2) > numb)
214 printf("CNST_LIMB(0x");
215 mpz_out_str (stdout, 16, x);
221 ("#define ODD_CENTRAL_BINOMIAL_TABLE_LIMIT (%lu)\n", ofe);
224 ("\n/* This table contains the inverses of elements in the previous table. */\n");
226 ("#define ONE_LIMB_ODD_CENTRAL_BINOMIAL_INVERSE_TABLE CNST_LIMB(0x");
227 for (b = ofl; b <= ofe; b++)
229 mpz_bin_uiui (x, 2 * b, b);
231 mpz_invert (x, x, mask);
232 mpz_out_str (stdout, 16, x);
234 printf ("),CNST_LIMB(0x");
239 ("\n/* This table contains the values t in the formula binomial(2k,k)/2^t */\n");
241 ("#define CENTRAL_BINOMIAL_2FAC_TABLE ");
242 for (b = ofl; b <= ofe; b++)
244 mpz_bin_uiui (x, 2 * b, b);
245 printf ("%d", mpz_remove_twos (x));
253 mpz_mul_2exp (x, x, limb + 1); /* x=2^(limb+1) */
255 mpz_set_ui (y, 10000);
256 mpz_mul (x, x, y); /* x=2^(limb+1)*10^4 */
257 mpz_set_ui (y, 27182); /* exp(1)*10^4 */
258 mpz_tdiv_q (x, x, y); /* x=2^(limb+1)/exp(1) */
259 printf ("\n/* is 2^(GMP_LIMB_BITS+1)/exp(1) */\n");
260 printf ("#define FAC2OVERE CNST_LIMB(0x");
261 mpz_out_str (stdout, 16, x);
266 ("\n/* FACMULn is largest odd x such that x*(x+2)*...*(x+2(n-1))<=2^GMP_NUMB_BITS-1 */\n\n");
269 for (a = 2; a <= 4; a++)
272 mpz_mul_2exp (x, x, numb);
274 /* so x is approx sol */
276 mpz_sub_ui (x, x, 1);
278 mpz_mul_2exp (y, y, numb);
279 mpz_sub_ui (y, y, 1);
280 /* decrement x until we are <= real sol */
283 mpz_sub_ui (x, x, 2);
284 odd_products (t, x, a);
285 if (mpz_cmp (t, y) <= 0)
289 /* increment x until > real sol */
292 mpz_add_ui (x, x, 2);
293 odd_products (t, x, a);
294 if (mpz_cmp (t, y) > 0)
298 /* dec once to get real sol */
299 mpz_sub_ui (x, x, 2);
300 printf ("#define FACMUL%lu CNST_LIMB(0x", a);
301 mpz_out_str (stdout, 16, x);
310 main (int argc, char *argv[])
312 int nail_bits, limb_bits, numb_bits;
316 fprintf (stderr, "Usage: gen-fac_ui limbbits nailbits\n");
319 limb_bits = atoi (argv[1]);
320 nail_bits = atoi (argv[2]);
321 numb_bits = limb_bits - nail_bits;
322 if (limb_bits < 2 || nail_bits < 0 || numb_bits < 1)
324 fprintf (stderr, "Invalid limb/nail bits %d,%d\n", limb_bits,
328 gen_consts (numb_bits, nail_bits, limb_bits);