1 /* Generate mp_bases data. 2 3 Copyright 1991, 1993, 1994, 1996, 2000, 2002, 2004 Free Software Foundation, 4 Inc. 5 6 This file is part of the GNU MP Library. 7 8 The GNU MP Library is free software; you can redistribute it and/or modify 9 it under the terms of the GNU Lesser General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or (at your 11 option) any later version. 12 13 The GNU MP Library is distributed in the hope that it will be useful, but 14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16 License for more details. 17 18 You should have received a copy of the GNU Lesser General Public License 19 along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ 20 21 #include <math.h> 22 23 #include "dumbmp.c" 24 25 26 int chars_per_limb; 27 double chars_per_bit_exactly; 28 mpz_t big_base; 29 int normalization_steps; 30 mpz_t big_base_inverted; 31 32 mpz_t t; 33 34 #define POW2_P(n) (((n) & ((n) - 1)) == 0) 35 36 unsigned int 37 ulog2 (unsigned int x) 38 { 39 unsigned int i; 40 for (i = 0; x != 0; i++) 41 x >>= 1; 42 return i; 43 } 44 45 void 46 generate (int limb_bits, int nail_bits, int base) 47 { 48 int numb_bits = limb_bits - nail_bits; 49 50 mpz_set_ui (t, 1L); 51 mpz_mul_2exp (t, t, numb_bits); 52 mpz_set_ui (big_base, 1L); 53 chars_per_limb = 0; 54 for (;;) 55 { 56 mpz_mul_ui (big_base, big_base, (long) base); 57 if (mpz_cmp (big_base, t) > 0) 58 break; 59 chars_per_limb++; 60 } 61 62 chars_per_bit_exactly = 0.69314718055994530942 / log ((double) base); 63 64 mpz_ui_pow_ui (big_base, (long) base, (long) chars_per_limb); 65 66 normalization_steps = limb_bits - mpz_sizeinbase (big_base, 2); 67 68 mpz_set_ui (t, 1L); 69 mpz_mul_2exp (t, t, 2*limb_bits - normalization_steps); 70 mpz_tdiv_q (big_base_inverted, t, big_base); 71 mpz_set_ui (t, 1L); 72 mpz_mul_2exp (t, t, limb_bits); 73 mpz_sub (big_base_inverted, big_base_inverted, t); 74 } 75 76 void 77 header (int limb_bits, int nail_bits) 78 { 79 int numb_bits = limb_bits - nail_bits; 80 81 generate (limb_bits, nail_bits, 10); 82 83 printf ("/* This file generated by gen-bases.c - DO NOT EDIT. */\n"); 84 printf ("\n"); 85 printf ("#if GMP_NUMB_BITS != %d\n", numb_bits); 86 printf ("Error, error, this data is for %d bits\n", numb_bits); 87 printf ("#endif\n"); 88 printf ("\n"); 89 printf ("/* mp_bases[10] data, as literal values */\n"); 90 printf ("#define MP_BASES_CHARS_PER_LIMB_10 %d\n", chars_per_limb); 91 printf ("#define MP_BASES_BIG_BASE_10 CNST_LIMB(0x"); 92 mpz_out_str (stdout, 16, big_base); 93 printf (")\n"); 94 printf ("#define MP_BASES_BIG_BASE_INVERTED_10 CNST_LIMB(0x"); 95 mpz_out_str (stdout, 16, big_base_inverted); 96 printf (")\n"); 97 printf ("#define MP_BASES_NORMALIZATION_STEPS_10 %d\n", normalization_steps); 98 } 99 100 void 101 table (int limb_bits, int nail_bits) 102 { 103 int numb_bits = limb_bits - nail_bits; 104 int base; 105 106 printf ("/* This file generated by gen-bases.c - DO NOT EDIT. */\n"); 107 printf ("\n"); 108 printf ("#include \"gmp.h\"\n"); 109 printf ("#include \"gmp-impl.h\"\n"); 110 printf ("\n"); 111 printf ("#if GMP_NUMB_BITS != %d\n", numb_bits); 112 printf ("Error, error, this data is for %d bits\n", numb_bits); 113 printf ("#endif\n"); 114 printf ("\n"); 115 puts ("const struct bases mp_bases[257] =\n{"); 116 puts (" /* 0 */ { 0, 0.0, 0 },"); 117 puts (" /* 1 */ { 0, 1e37, 0 },"); 118 for (base = 2; base <= 256; base++) 119 { 120 generate (limb_bits, nail_bits, base); 121 122 printf (" /* %3u */ { ", base); 123 if (POW2_P (base)) 124 { 125 printf ("%u, %.16f, 0x%x },\n", 126 chars_per_limb, chars_per_bit_exactly, ulog2 (base) - 1); 127 } 128 else 129 { 130 printf ("%u, %.16f, CNST_LIMB(0x", 131 chars_per_limb, chars_per_bit_exactly); 132 mpz_out_str (stdout, 16, big_base); 133 printf ("), CNST_LIMB(0x"); 134 mpz_out_str (stdout, 16, big_base_inverted); 135 printf (") },\n"); 136 } 137 } 138 139 puts ("};"); 140 } 141 142 int 143 main (int argc, char **argv) 144 { 145 int limb_bits, nail_bits; 146 147 mpz_init (big_base); 148 mpz_init (big_base_inverted); 149 mpz_init (t); 150 151 if (argc != 4) 152 { 153 fprintf (stderr, "Usage: gen-bases <header|table> <limbbits> <nailbits>\n"); 154 exit (1); 155 } 156 157 limb_bits = atoi (argv[2]); 158 nail_bits = atoi (argv[3]); 159 160 if (limb_bits <= 0 161 || nail_bits < 0 162 || nail_bits >= limb_bits) 163 { 164 fprintf (stderr, "Invalid limb/nail bits: %d %d\n", 165 limb_bits, nail_bits); 166 exit (1); 167 } 168 169 if (strcmp (argv[1], "header") == 0) 170 header (limb_bits, nail_bits); 171 else if (strcmp (argv[1], "table") == 0) 172 table (limb_bits, nail_bits); 173 else 174 { 175 fprintf (stderr, "Invalid header/table choice: %s\n", argv[1]); 176 exit (1); 177 } 178 179 return 0; 180 } 181