Import gmp-4.3.1
[dragonfly.git] / contrib / gmp / gen-bases.c
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 }