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
ulog2(unsigned int x)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
generate(int limb_bits,int nail_bits,int base)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
header(int limb_bits,int nail_bits)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
table(int limb_bits,int nail_bits)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
main(int argc,char ** argv)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