xref: /netbsd-src/external/lgpl3/gmp/dist/gen-fib.c (revision ce54336801cf28877c3414aa2fcb251dddd543a2)
1 /* Generate Fibonacci table data.
2 
3 Copyright 2001, 2002, 2004, 2012, 2014, 2015 Free Software Foundation, Inc.
4 
5 This file is part of the GNU MP Library.
6 
7 The GNU MP Library is free software; you can redistribute it and/or modify
8 it under the terms of either:
9 
10   * the GNU Lesser General Public License as published by the Free
11     Software Foundation; either version 3 of the License, or (at your
12     option) any later version.
13 
14 or
15 
16   * the GNU General Public License as published by the Free Software
17     Foundation; either version 2 of the License, or (at your option) any
18     later version.
19 
20 or both in parallel, as here.
21 
22 The GNU MP Library is distributed in the hope that it will be useful, but
23 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
25 for more details.
26 
27 You should have received copies of the GNU General Public License and the
28 GNU Lesser General Public License along with the GNU MP Library.  If not,
29 see https://www.gnu.org/licenses/.  */
30 
31 #include <stdio.h>
32 #include "bootstrap.c"
33 
34 mpz_t  *f;
35 int    fnum, fib_limit, luc_limit;
36 
37 void
generate(int numb_bits)38 generate (int numb_bits)
39 {
40   mpz_t  limit, l;
41   int    falloc, i;
42 
43   mpz_init2 (limit, numb_bits + 1);
44   mpz_setbit (limit, numb_bits);
45 
46   /* fib(2n) > 2^n, so use 2n as a limit for the table size */
47   falloc = 2 * numb_bits;
48   f = (mpz_t*) xmalloc (falloc * sizeof (*f));
49 
50   mpz_init_set_ui (f[0], 1L);  /* F[-1] */
51   mpz_init_set_ui (f[1], 0L);  /* F[0] */
52 
53   mpz_init (l);
54 
55   for (i = 2; ; i++)
56     {
57       assert (i < falloc);
58 
59       /* F[i] = F[i-1] + F[i-2] */
60       mpz_init (f[i]);
61       mpz_add (f[i], f[i-1], f[i-2]);
62       if (mpz_cmp (f[i], limit) >= 0)
63         break;
64 
65       fnum = i+1;
66       fib_limit = i-1;
67 
68       /* L[i] = F[i]+2*F[i-1] */
69       mpz_add (l, f[i], f[i-1]);
70       mpz_add (l, l, f[i-1]);
71 
72       if (mpz_cmp (l, limit) < 0)
73         luc_limit = i-1;
74     }
75 
76   mpz_clear (limit);
77 }
78 
79 
80 void
header(int numb_bits)81 header (int numb_bits)
82 {
83   printf ("/* This file generated by gen-fib.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 ("#define FIB_TABLE_LIMIT         %d\n", fib_limit);
90   printf ("#define FIB_TABLE_LUCNUM_LIMIT  %d\n", luc_limit);
91 }
92 
93 void
table(int numb_bits)94 table (int numb_bits)
95 {
96   int  i;
97 
98   printf ("/* This file generated by gen-fib.c - DO NOT EDIT. */\n");
99   printf ("\n");
100   printf ("#include \"gmp.h\"\n");
101   printf ("#include \"gmp-impl.h\"\n");
102   printf ("\n");
103   printf ("#if GMP_NUMB_BITS != %d\n", numb_bits);
104   printf ("Error, error, this data is for %d bits\n", numb_bits);
105   printf ("#endif\n");
106   printf ("\n");
107   printf ("const mp_limb_t\n");
108   printf ("__gmp_fib_table[FIB_TABLE_LIMIT+2] = {\n");
109 
110   for (i = 0; i < fnum; i++)
111     {
112       printf ("  CNST_LIMB (0x");
113       mpz_out_str (stdout, 16, f[i]);
114       printf ("),  /* %d */\n", i-1);
115     }
116   printf ("};\n");
117 }
118 
119 int
main(int argc,char * argv[])120 main (int argc, char *argv[])
121 {
122   int  limb_bits, nail_bits, numb_bits;
123 
124   if (argc != 4)
125     {
126       fprintf (stderr, "Usage: gen-fib <header|table> <limbbits> <nailbits>\n");
127       exit (1);
128     }
129 
130   limb_bits = atoi (argv[2]);
131   nail_bits = atoi (argv[3]);
132 
133   if (limb_bits <= 0
134       || nail_bits < 0
135       || nail_bits >= limb_bits)
136     {
137       fprintf (stderr, "Invalid limb/nail bits: %d %d\n",
138                limb_bits, nail_bits);
139       exit (1);
140     }
141   numb_bits = limb_bits - nail_bits;
142 
143   generate (numb_bits);
144 
145   if (strcmp (argv[1], "header") == 0)
146     header (numb_bits);
147   else if (strcmp (argv[1], "table") == 0)
148     table (numb_bits);
149   else
150     {
151       fprintf (stderr, "Invalid header/table choice: %s\n", argv[1]);
152       exit (1);
153     }
154 
155   return 0;
156 }
157