xref: /dragonfly/contrib/gmp/gen-bases.c (revision 25a2db75)
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