1/*
2 * Output various information about GMP and MPFR.
3 */
4
5/*
6Copyright 2010-2023 Free Software Foundation, Inc.
7Contributed by the AriC and Caramba projects, INRIA.
8
9This file is part of the GNU MPFR Library.
10
11The GNU MPFR Library is free software; you can redistribute it and/or modify
12it under the terms of the GNU Lesser General Public License as published by
13the Free Software Foundation; either version 3 of the License, or (at your
14option) any later version.
15
16The GNU MPFR Library is distributed in the hope that it will be useful, but
17WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
19License for more details.
20
21You should have received a copy of the GNU Lesser General Public License
22along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
23https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
2451 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
25*/
26
27#include <stdio.h>
28#include <limits.h>
29#include <gmp.h>
30#include <mpfr.h>
31
32/* The following failure can occur if GMP has been rebuilt with
33 * a different ABI, e.g.
34 *   1. GMP built with ABI=mode32.
35 *   2. MPFR built against this GMP version.
36 *   3. GMP rebuilt with ABI=32.
37 */
38static void failure_test (void)
39{
40  mpfr_t x;
41
42  mpfr_init2 (x, 128);
43  mpfr_set_str (x, "17", 0, MPFR_RNDN);
44  if (mpfr_cmp_ui (x, 17) != 0)
45    printf ("\nFailure in mpfr_set_str! Probably an unmatched ABI!\n");
46  mpfr_clear (x);
47}
48
49static void patches (void)
50{
51  const char *p = mpfr_get_patches ();
52  printf ("MPFR patches: %s\n", p[0] ? p : "[none]");
53}
54
55#define STRINGIZE(S) #S
56#define MAKE_STR(S) STRINGIZE(S)
57
58#define SIGNED_STR(V) ((V) < 0 ? "signed" : "unsigned")
59#define SIGNED(I) SIGNED_STR((I) - (I) - 1)
60
61int main (void)
62{
63  unsigned long c;
64  mp_limb_t t[4];
65  int i;
66
67  /* Casts are for C++ compilers. */
68  for (i = 0; i < (int) (sizeof (t) / sizeof (mp_limb_t)); i++)
69    t[i] = (mp_limb_t) -1;
70
71  /**************** Information about the C implementation ****************/
72
73  /* This is useful, as this can affect the behavior of MPFR. */
74
75#define COMP "Compiler: "
76#ifdef __INTEL_COMPILER
77# ifdef __VERSION__
78#  define ICCV " [" __VERSION__ "]"
79# else
80#  define ICCV ""
81# endif
82  printf (COMP "ICC %d.%d.%d" ICCV "\n", __INTEL_COMPILER / 100,
83          __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE);
84#elif defined(__TINYC__)
85  /* The format of __TINYC__ is not described, but libtcc.c defines it with
86   *   sprintf(buffer, "%d", a*10000 + b*100 + c);
87   *   tcc_define_symbol(s, "__TINYC__", buffer);
88   */
89  printf (COMP "TCC %d.%d.%d\n", (int) (__TINYC__ / 10000),
90          (int) ((__TINYC__ / 100) % 100), (int) (__TINYC__ % 100));
91#elif (defined(__GNUC__) || defined(__clang__)) && defined(__VERSION__)
92# ifdef __clang__
93#  define COMP2 COMP
94# else
95#  define COMP2 COMP "GCC "
96# endif
97  printf (COMP2 "%s\n", __VERSION__);
98#endif
99
100#if defined(__STDC__) || defined(__STDC_VERSION__)
101  printf ("C/C++: __STDC__ = "
102#if defined(__STDC__)
103          MAKE_STR(__STDC__)
104#else
105          "undef"
106#endif
107          ", __STDC_VERSION__ = "
108#if defined(__STDC_VERSION__)
109          MAKE_STR(__STDC_VERSION__)
110#else
111          "undef"
112#endif
113#if defined(__cplusplus)
114          ", C++"
115#endif
116          "\n");
117#endif
118
119#if defined(__GNUC__)
120  printf ("GNU compatibility: __GNUC__ = " MAKE_STR(__GNUC__)
121          ", __GNUC_MINOR__ = "
122#if defined(__GNUC_MINOR__)
123          MAKE_STR(__GNUC_MINOR__)
124#else
125          "undef"
126#endif
127          "\n");
128#endif
129
130#if defined(__ICC) || defined(__INTEL_COMPILER)
131  printf ("Intel compiler: __ICC = "
132#if defined(__ICC)
133          MAKE_STR(__ICC)
134#else
135          "undef"
136#endif
137          ", __INTEL_COMPILER = "
138#if defined(__INTEL_COMPILER)
139          MAKE_STR(__INTEL_COMPILER)
140#else
141          "undef"
142#endif
143          "\n");
144#endif
145
146#if defined(_WIN32) || defined(_MSC_VER)
147  printf ("MS Windows: _WIN32 = "
148#if defined(_WIN32)
149          MAKE_STR(_WIN32)
150#else
151          "undef"
152#endif
153          ", _MSC_VER = "
154#if defined(_MSC_VER)
155          MAKE_STR(_MSC_VER)
156#else
157          "undef"
158#endif
159          "\n");
160#endif
161
162#if defined(__GLIBC__)
163  printf ("GNU C library: __GLIBC__ = " MAKE_STR(__GLIBC__)
164          ", __GLIBC_MINOR__ = "
165#if defined(__GLIBC_MINOR__)
166          MAKE_STR(__GLIBC_MINOR__)
167#else
168          "undef"
169#endif
170          "\n");
171#endif
172
173  printf ("\n");
174
175  /************************************************************************/
176
177#if defined(__MPIR_VERSION)
178  printf ("MPIR ....  Library: %-12s  Header: %d.%d.%d\n",
179          mpir_version, __MPIR_VERSION, __MPIR_VERSION_MINOR,
180          __MPIR_VERSION_PATCHLEVEL);
181#else
182  printf ("GMP .....  Library: %-12s  Header: %d.%d.%d\n",
183          gmp_version, __GNU_MP_VERSION, __GNU_MP_VERSION_MINOR,
184          __GNU_MP_VERSION_PATCHLEVEL);
185#endif
186
187  printf ("MPFR ....  Library: %-12s  Header: %s (based on %d.%d.%d)\n",
188          mpfr_get_version (), MPFR_VERSION_STRING, MPFR_VERSION_MAJOR,
189          MPFR_VERSION_MINOR, MPFR_VERSION_PATCHLEVEL);
190
191  printf ("MPFR features: TLS = %s", mpfr_buildopt_tls_p () ? "yes" : "no");
192#if MPFR_VERSION_MAJOR >= 4
193  printf (", float128 = %s", mpfr_buildopt_float128_p () ? "yes" : "no");
194#endif
195  printf (", decimal = %s", mpfr_buildopt_decimal_p () ? "yes" : "no");
196#if MPFR_VERSION_MAJOR > 3 || MPFR_VERSION_MINOR >= 1
197  printf (", GMP internals = %s\nMPFR tuning: %s",
198          mpfr_buildopt_gmpinternals_p () ? "yes" : "no",
199          mpfr_buildopt_tune_case ());
200#endif  /* 3.1 */
201  printf ("\n");
202
203  patches ();
204
205  printf ("\n");
206#ifdef __GMP_CC
207  printf ("__GMP_CC = \"%s\"\n", __GMP_CC);
208#endif
209#ifdef __GMP_CFLAGS
210  printf ("__GMP_CFLAGS = \"%s\"\n", __GMP_CFLAGS);
211#endif
212  printf ("GMP_LIMB_BITS     = %d\n", (int) GMP_LIMB_BITS);
213  printf ("GMP_NAIL_BITS     = %d\n", (int) GMP_NAIL_BITS);
214  printf ("GMP_NUMB_BITS     = %d\n", (int) GMP_NUMB_BITS);
215  printf ("mp_bits_per_limb  = %d\n", (int) mp_bits_per_limb);
216  printf ("sizeof(mp_limb_t) = %d\n", (int) sizeof(mp_limb_t));
217  if (mp_bits_per_limb != GMP_LIMB_BITS)
218    printf ("Warning! mp_bits_per_limb != GMP_LIMB_BITS\n");
219  if (GMP_LIMB_BITS != sizeof(mp_limb_t) * CHAR_BIT)
220    printf ("Warning! GMP_LIMB_BITS != sizeof(mp_limb_t) * CHAR_BIT\n");
221
222  c = mpn_popcount (t, 1);
223  printf ("The GMP library expects %lu bits in a mp_limb_t.\n", c);
224  if (c != GMP_LIMB_BITS)
225    printf ("Warning! This is different from GMP_LIMB_BITS!\n"
226            "Different ABI caused by a GMP library upgrade?\n");
227
228  printf ("\n");
229  printf ("sizeof(mpfr_prec_t) = %d (%s type)\n", (int) sizeof(mpfr_prec_t),
230          SIGNED_STR((mpfr_prec_t) -1));
231  printf ("sizeof(mpfr_exp_t)  = %d (%s type)\n", (int) sizeof(mpfr_exp_t),
232          SIGNED_STR((mpfr_exp_t) -1));
233#ifdef _MPFR_PREC_FORMAT
234  printf ("_MPFR_PREC_FORMAT = %d\n", (int) _MPFR_PREC_FORMAT);
235#endif
236  /* Note: "long" is sufficient for all current _MPFR_PREC_FORMAT values
237     (1, 2, 3). Thus we do not need to depend on ISO C99 or later. */
238  printf ("MPFR_PREC_MIN = %ld (%s)\n", (long) MPFR_PREC_MIN,
239          SIGNED (MPFR_PREC_MIN));
240  printf ("MPFR_PREC_MAX = %ld (%s)\n", (long) MPFR_PREC_MAX,
241          SIGNED (MPFR_PREC_MAX));
242#ifdef _MPFR_EXP_FORMAT
243  printf ("_MPFR_EXP_FORMAT = %d\n", (int) _MPFR_EXP_FORMAT);
244#endif
245  printf ("sizeof(mpfr_t) = %d\n", (int) sizeof(mpfr_t));
246  printf ("sizeof(mpfr_ptr) = %d\n", (int) sizeof(mpfr_ptr));
247  failure_test ();
248
249  mpfr_free_cache ();
250  return 0;
251}
252