Home | History | Annotate | Line # | Download | only in dist
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