github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/gen-fac.c (about)

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