1/* Generate mp_bases data. 2 3Copyright 1991, 1993, 1994, 1996, 2000, 2002, 2004 Free Software Foundation, 4Inc. 5 6This file is part of the GNU MP Library. 7 8The GNU MP Library is free software; you can redistribute it and/or modify 9it under the terms of the GNU Lesser General Public License as published by 10the Free Software Foundation; either version 3 of the License, or (at your 11option) any later version. 12 13The GNU MP Library is distributed in the hope that it will be useful, but 14WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16License for more details. 17 18You should have received a copy of the GNU Lesser General Public License 19along 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 26int chars_per_limb; 27double chars_per_bit_exactly; 28mpz_t big_base; 29int normalization_steps; 30mpz_t big_base_inverted; 31 32mpz_t t; 33 34#define POW2_P(n) (((n) & ((n) - 1)) == 0) 35 36unsigned int 37ulog2 (unsigned int x) 38{ 39 unsigned int i; 40 for (i = 0; x != 0; i++) 41 x >>= 1; 42 return i; 43} 44 45void 46generate (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 76void 77header (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 100void 101table (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 142int 143main (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