Blame gen-fac.c

Packit 5c3484
/* Generate data for combinatorics: fac_ui, bin_uiui, ...
Packit 5c3484
Packit 5c3484
Copyright 2002, 2011-2015 Free Software Foundation, Inc.
Packit 5c3484
Packit 5c3484
This file is part of the GNU MP Library.
Packit 5c3484
Packit 5c3484
The GNU MP Library is free software; you can redistribute it and/or modify
Packit 5c3484
it under the terms of either:
Packit 5c3484
Packit 5c3484
  * the GNU Lesser General Public License as published by the Free
Packit 5c3484
    Software Foundation; either version 3 of the License, or (at your
Packit 5c3484
    option) any later version.
Packit 5c3484
Packit 5c3484
or
Packit 5c3484
Packit 5c3484
  * the GNU General Public License as published by the Free Software
Packit 5c3484
    Foundation; either version 2 of the License, or (at your option) any
Packit 5c3484
    later version.
Packit 5c3484
Packit 5c3484
or both in parallel, as here.
Packit 5c3484
Packit 5c3484
The GNU MP Library is distributed in the hope that it will be useful, but
Packit 5c3484
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
Packit 5c3484
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
Packit 5c3484
for more details.
Packit 5c3484
Packit 5c3484
You should have received copies of the GNU General Public License and the
Packit 5c3484
GNU Lesser General Public License along with the GNU MP Library.  If not,
Packit 5c3484
see https://www.gnu.org/licenses/.  */
Packit 5c3484
Packit 5c3484
#include <stdio.h>
Packit 5c3484
#include <stdlib.h>
Packit 5c3484
Packit 5c3484
#include "bootstrap.c"
Packit 5c3484
Packit 5c3484
int
Packit 5c3484
mpz_remove_twos (mpz_t x)
Packit 5c3484
{
Packit 5c3484
  mp_bitcnt_t r = mpz_scan1(x, 0);
Packit 5c3484
  mpz_tdiv_q_2exp (x, x, r);
Packit 5c3484
  return r;
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
/* returns 0 on success		*/
Packit 5c3484
int
Packit 5c3484
gen_consts (int numb, int nail, int limb)
Packit 5c3484
{
Packit 5c3484
  mpz_t x, mask, y, last;
Packit 5c3484
  unsigned long a, b;
Packit 5c3484
  unsigned long ofl, ofe;
Packit 5c3484
Packit 5c3484
  printf ("/* This file is automatically generated by gen-fac.c */\n\n");
Packit 5c3484
  printf ("#if GMP_NUMB_BITS != %d\n", numb);
Packit 5c3484
  printf ("Error , error this data is for %d GMP_NUMB_BITS only\n", numb);
Packit 5c3484
  printf ("#endif\n");
Packit 5c3484
#if 0
Packit 5c3484
  printf ("#if GMP_LIMB_BITS != %d\n", limb);
Packit 5c3484
  printf ("Error , error this data is for %d GMP_LIMB_BITS only\n", limb);
Packit 5c3484
  printf ("#endif\n");
Packit 5c3484
#endif
Packit 5c3484
Packit 5c3484
  printf
Packit 5c3484
    ("/* This table is 0!,1!,2!,3!,...,n! where n! has <= GMP_NUMB_BITS bits */\n");
Packit 5c3484
  printf
Packit 5c3484
    ("#define ONE_LIMB_FACTORIAL_TABLE CNST_LIMB(0x1),CNST_LIMB(0x1");
Packit 5c3484
  mpz_init_set_ui (x, 1);
Packit 5c3484
  mpz_init (last);
Packit 5c3484
  for (b = 2;; b++)
Packit 5c3484
    {
Packit 5c3484
      mpz_mul_ui (x, x, b);	/* so b!=a       */
Packit 5c3484
      if (mpz_sizeinbase (x, 2) > numb)
Packit 5c3484
	break;
Packit 5c3484
      printf ("),CNST_LIMB(0x");
Packit 5c3484
      mpz_out_str (stdout, 16, x);
Packit 5c3484
    }
Packit 5c3484
  printf (")\n");
Packit 5c3484
Packit 5c3484
  printf
Packit 5c3484
    ("\n/* This table is 0!,1!,2!/2,3!/2,...,n!/2^sn where n!/2^sn is an */\n");
Packit 5c3484
  printf
Packit 5c3484
    ("/* odd integer for each n, and n!/2^sn has <= GMP_NUMB_BITS bits */\n");
Packit 5c3484
  printf
Packit 5c3484
    ("#define ONE_LIMB_ODD_FACTORIAL_TABLE CNST_LIMB(0x1),CNST_LIMB(0x1),CNST_LIMB(0x1");
Packit 5c3484
  mpz_set_ui (x, 1);
Packit 5c3484
  for (b = 3;; b++)
Packit 5c3484
    {
Packit 5c3484
      for (a = b; (a & 1) == 0; a >>= 1);
Packit 5c3484
      mpz_swap (last, x);
Packit 5c3484
      mpz_mul_ui (x, last, a);
Packit 5c3484
      if (mpz_sizeinbase (x, 2) > numb)
Packit 5c3484
	break;
Packit 5c3484
      printf ("),CNST_LIMB(0x");
Packit 5c3484
      mpz_out_str (stdout, 16, x);
Packit 5c3484
    }
Packit 5c3484
  printf (")\n");
Packit 5c3484
  printf
Packit 5c3484
    ("#define ODD_FACTORIAL_TABLE_MAX CNST_LIMB(0x");
Packit 5c3484
  mpz_out_str (stdout, 16, last);
Packit 5c3484
  printf (")\n");
Packit 5c3484
Packit 5c3484
  ofl = b - 1;
Packit 5c3484
  printf
Packit 5c3484
    ("#define ODD_FACTORIAL_TABLE_LIMIT (%lu)\n", ofl);
Packit 5c3484
  mpz_init2 (mask, numb + 1);
Packit 5c3484
  mpz_setbit (mask, numb);
Packit 5c3484
  mpz_sub_ui (mask, mask, 1);
Packit 5c3484
  printf
Packit 5c3484
    ("\n/* Previous table, continued, values modulo 2^GMP_NUMB_BITS */\n");
Packit 5c3484
  printf
Packit 5c3484
    ("#define ONE_LIMB_ODD_FACTORIAL_EXTTABLE CNST_LIMB(0x");
Packit 5c3484
  mpz_and (x, x, mask);
Packit 5c3484
  mpz_out_str (stdout, 16, x);
Packit 5c3484
  mpz_init (y);
Packit 5c3484
  mpz_bin_uiui (y, b, b/2);
Packit 5c3484
  b++;
Packit 5c3484
  for (;; b++)
Packit 5c3484
    {
Packit 5c3484
      for (a = b; (a & 1) == 0; a >>= 1);
Packit 5c3484
      if (a == b) {
Packit 5c3484
	mpz_divexact_ui (y, y, a/2+1);
Packit 5c3484
	mpz_mul_ui (y, y, a);
Packit 5c3484
      } else
Packit 5c3484
	mpz_mul_2exp (y, y, 1);
Packit 5c3484
      if (mpz_sizeinbase (y, 2) > numb)
Packit 5c3484
	break;
Packit 5c3484
      mpz_mul_ui (x, x, a);
Packit 5c3484
      mpz_and (x, x, mask);
Packit 5c3484
      printf ("),CNST_LIMB(0x");
Packit 5c3484
      mpz_out_str (stdout, 16, x);
Packit 5c3484
    }
Packit 5c3484
  printf (")\n");
Packit 5c3484
  ofe = b - 1;
Packit 5c3484
  printf
Packit 5c3484
    ("#define ODD_FACTORIAL_EXTTABLE_LIMIT (%lu)\n", ofe);
Packit 5c3484
Packit 5c3484
  printf
Packit 5c3484
    ("\n/* This table is 1!!,3!!,...,(2n+1)!! where (2n+1)!! has <= GMP_NUMB_BITS bits */\n");
Packit 5c3484
  printf
Packit 5c3484
    ("#define ONE_LIMB_ODD_DOUBLEFACTORIAL_TABLE CNST_LIMB(0x1");
Packit 5c3484
  mpz_set_ui (x, 1);
Packit 5c3484
  for (b = 3;; b+=2)
Packit 5c3484
    {
Packit 5c3484
      mpz_swap (last, x);
Packit 5c3484
      mpz_mul_ui (x, last, b);
Packit 5c3484
      if (mpz_sizeinbase (x, 2) > numb)
Packit 5c3484
	break;
Packit 5c3484
      printf ("),CNST_LIMB(0x");
Packit 5c3484
      mpz_out_str (stdout, 16, x);
Packit 5c3484
    }
Packit 5c3484
  printf (")\n");
Packit 5c3484
  printf
Packit 5c3484
    ("#define ODD_DOUBLEFACTORIAL_TABLE_MAX CNST_LIMB(0x");
Packit 5c3484
  mpz_out_str (stdout, 16, last);
Packit 5c3484
  printf (")\n");
Packit 5c3484
Packit 5c3484
  printf
Packit 5c3484
    ("#define ODD_DOUBLEFACTORIAL_TABLE_LIMIT (%lu)\n", b - 2);
Packit 5c3484
Packit 5c3484
  printf
Packit 5c3484
    ("\n/* This table x_1, x_2,... contains values s.t. x_n^n has <= GMP_NUMB_BITS bits */\n");
Packit 5c3484
  printf
Packit 5c3484
    ("#define NTH_ROOT_NUMB_MASK_TABLE (GMP_NUMB_MASK");
Packit 5c3484
  for (b = 2;b <= 8; b++)
Packit 5c3484
    {
Packit 5c3484
      mpz_root (x, mask, b);
Packit 5c3484
      printf ("),CNST_LIMB(0x");
Packit 5c3484
      mpz_out_str (stdout, 16, x);
Packit 5c3484
    }
Packit 5c3484
  printf (")\n");
Packit 5c3484
Packit 5c3484
  mpz_add_ui (mask, mask, 1);
Packit 5c3484
  printf
Packit 5c3484
    ("\n/* This table contains inverses of odd factorials, modulo 2^GMP_NUMB_BITS */\n");
Packit 5c3484
  printf
Packit 5c3484
    ("\n/* It begins with (2!/2)^-1=1 */\n");
Packit 5c3484
  printf
Packit 5c3484
    ("#define ONE_LIMB_ODD_FACTORIAL_INVERSES_TABLE CNST_LIMB(0x1");
Packit 5c3484
  mpz_set_ui (x, 1);
Packit 5c3484
  for (b = 3;b <= ofe - 2; b++)
Packit 5c3484
    {
Packit 5c3484
      for (a = b; (a & 1) == 0; a >>= 1);
Packit 5c3484
      mpz_mul_ui (x, x, a);
Packit 5c3484
      mpz_invert (y, x, mask);
Packit 5c3484
      printf ("),CNST_LIMB(0x");
Packit 5c3484
      mpz_out_str (stdout, 16, y);
Packit 5c3484
    }
Packit 5c3484
  printf (")\n");
Packit 5c3484
Packit 5c3484
  ofe = (ofe / 16 + 1) * 16;
Packit 5c3484
Packit 5c3484
  printf
Packit 5c3484
    ("\n/* This table contains 2n-popc(2n) for small n */\n");
Packit 5c3484
  printf
Packit 5c3484
    ("\n/* It begins with 2-1=1 (n=1) */\n");
Packit 5c3484
  printf
Packit 5c3484
    ("#define TABLE_2N_MINUS_POPC_2N 1");
Packit 5c3484
  for (b = 4; b <= ofe; b += 2)
Packit 5c3484
    {
Packit 5c3484
      mpz_set_ui (x, b);
Packit 5c3484
      printf (",%lu",b - mpz_popcount (x));
Packit 5c3484
    }
Packit 5c3484
  printf ("\n");
Packit 5c3484
  printf
Packit 5c3484
    ("#define TABLE_LIMIT_2N_MINUS_POPC_2N %lu\n", ofe + 1);
Packit 5c3484
Packit 5c3484
Packit 5c3484
  ofl = (ofl + 1) / 2;
Packit 5c3484
  printf
Packit 5c3484
    ("#define ODD_CENTRAL_BINOMIAL_OFFSET (%lu)\n", ofl);
Packit 5c3484
  printf
Packit 5c3484
    ("\n/* This table contains binomial(2k,k)/2^t */\n");
Packit 5c3484
  printf
Packit 5c3484
    ("\n/* It begins with ODD_CENTRAL_BINOMIAL_TABLE_MIN */\n");
Packit 5c3484
  printf
Packit 5c3484
    ("#define ONE_LIMB_ODD_CENTRAL_BINOMIAL_TABLE ");
Packit 5c3484
  for (b = ofl;; b++)
Packit 5c3484
    {
Packit 5c3484
      mpz_bin_uiui (x, 2 * b, b);
Packit 5c3484
      mpz_remove_twos (x);
Packit 5c3484
      if (mpz_sizeinbase (x, 2) > numb)
Packit 5c3484
	break;
Packit 5c3484
      if (b != ofl)
Packit 5c3484
	printf ("),");
Packit 5c3484
      printf("CNST_LIMB(0x");
Packit 5c3484
      mpz_out_str (stdout, 16, x);
Packit 5c3484
    }
Packit 5c3484
  printf (")\n");
Packit 5c3484
Packit 5c3484
  ofe = b - 1;
Packit 5c3484
  printf
Packit 5c3484
    ("#define ODD_CENTRAL_BINOMIAL_TABLE_LIMIT (%lu)\n", ofe);
Packit 5c3484
Packit 5c3484
  printf
Packit 5c3484
    ("\n/* This table contains the inverses of elements in the previous table. */\n");
Packit 5c3484
  printf
Packit 5c3484
    ("#define ONE_LIMB_ODD_CENTRAL_BINOMIAL_INVERSE_TABLE CNST_LIMB(0x");
Packit 5c3484
  for (b = ofl; b <= ofe; b++)
Packit 5c3484
    {
Packit 5c3484
      mpz_bin_uiui (x, 2 * b, b);
Packit 5c3484
      mpz_remove_twos (x);
Packit 5c3484
      mpz_invert (x, x, mask);
Packit 5c3484
      mpz_out_str (stdout, 16, x);
Packit 5c3484
      if (b != ofe)
Packit 5c3484
	printf ("),CNST_LIMB(0x");
Packit 5c3484
    }
Packit 5c3484
  printf (")\n");
Packit 5c3484
Packit 5c3484
  printf
Packit 5c3484
    ("\n/* This table contains the values t in the formula binomial(2k,k)/2^t */\n");
Packit 5c3484
  printf
Packit 5c3484
    ("#define CENTRAL_BINOMIAL_2FAC_TABLE ");
Packit 5c3484
  for (b = ofl; b <= ofe; b++)
Packit 5c3484
    {
Packit 5c3484
      mpz_bin_uiui (x, 2 * b, b);
Packit 5c3484
      printf ("%d", mpz_remove_twos (x));
Packit 5c3484
      if (b != ofe)
Packit 5c3484
	printf (",");
Packit 5c3484
    }
Packit 5c3484
  printf ("\n");
Packit 5c3484
Packit 5c3484
  return 0;
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
int
Packit 5c3484
main (int argc, char *argv[])
Packit 5c3484
{
Packit 5c3484
  int nail_bits, limb_bits, numb_bits;
Packit 5c3484
Packit 5c3484
  if (argc != 3)
Packit 5c3484
    {
Packit 5c3484
      fprintf (stderr, "Usage: gen-fac limbbits nailbits\n");
Packit 5c3484
      exit (1);
Packit 5c3484
    }
Packit 5c3484
  limb_bits = atoi (argv[1]);
Packit 5c3484
  nail_bits = atoi (argv[2]);
Packit 5c3484
  numb_bits = limb_bits - nail_bits;
Packit 5c3484
  if (limb_bits < 2 || nail_bits < 0 || numb_bits < 1)
Packit 5c3484
    {
Packit 5c3484
      fprintf (stderr, "Invalid limb/nail bits %d,%d\n", limb_bits,
Packit 5c3484
	       nail_bits);
Packit 5c3484
      exit (1);
Packit 5c3484
    }
Packit 5c3484
  gen_consts (numb_bits, nail_bits, limb_bits);
Packit 5c3484
  return 0;
Packit 5c3484
}