1/* Test file for mpfr_version.
2
3Copyright 2004-2023 Free Software Foundation, Inc.
4Contributed by the AriC and Caramba projects, INRIA.
5
6This file is part of the GNU MPFR Library.
7
8The GNU MPFR Library is free software; you can redistribute it and/or modify
9it under the terms of the GNU Lesser General Public License as published by
10the Free Software Foundation; either version 3 of the License, or (at your
11option) any later version.
12
13The GNU MPFR Library is distributed in the hope that it will be useful, but
14WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16License for more details.
17
18You should have received a copy of the GNU Lesser General Public License
19along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
20https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
2151 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
22
23#include <errno.h>
24
25#define MPFR_NEED_INTMAX_H
26#include "mpfr-test.h"
27
28/* Warning about the usage of printf/puts below:
29 *
30 *   - If a macro expansion is used, it must not appear in the first
31 *     argument of printf (format string), as we do not know whether
32 *     the expanded string contains a '%' character.
33 *
34 *   - If a #if preprocessor directive is used in an argument, parentheses
35 *     must be put around the function name, in case this function is also
36 *     implemented as a macro (#if does not work in macro arguments).
37 */
38
39int
40main (void)
41{
42  mpfr_exp_t e;
43  int err = 0;
44
45  /* Test the GMP and MPFR versions. */
46  if (test_version ())
47    exit (1);
48
49  tests_start_mpfr ();
50
51  errno = 0;
52
53  /*********************** MPFR version and patches ************************/
54
55  /* The printf failure test was added because of an output issue under Wine,
56   * eventually not related to this output; this test is kept just in case...
57   * Details:
58   *   https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=914822
59   *   https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=914949
60   */
61  if (printf ("[tversion] MPFR %s\n", MPFR_VERSION_STRING) < 0)
62    {
63      perror ("tversion (first printf)");
64      err = 1;
65    }
66
67  if (strcmp (mpfr_get_patches (), "") != 0)
68    printf ("[tversion] MPFR patches: %s\n", mpfr_get_patches ());
69
70  /************************* Compiler information **************************/
71
72  /* TODO: We may want to output info for non-GNUC-compat compilers too. See:
73   * https://sourceforge.net/p/predef/wiki/Compilers/
74   * https://web.archive.org/web/20191011050717/http://nadeausoftware.com/articles/2012/10/c_c_tip_how_detect_compiler_name_and_version_using_compiler_predefined_macros
75   *
76   * For ICC, do not check the __ICC macro as it is obsolete and not always
77   * defined (in particular, on MS Windows).
78   */
79#define COMP "[tversion] Compiler: "
80#ifdef __INTEL_COMPILER
81# ifdef __VERSION__
82#  define ICCV " [" __VERSION__ "]"
83# else
84#  define ICCV ""
85# endif
86  printf (COMP "ICC %d.%d.%d" ICCV "\n", __INTEL_COMPILER / 100,
87          __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE);
88#elif defined(__TINYC__)
89  /* The format of __TINYC__ is not described, but libtcc.c defines it with
90   *   sprintf(buffer, "%d", a*10000 + b*100 + c);
91   *   tcc_define_symbol(s, "__TINYC__", buffer);
92   */
93  printf (COMP "TCC %d.%d.%d\n", (int) (__TINYC__ / 10000),
94          (int) ((__TINYC__ / 100) % 100), (int) (__TINYC__ % 100));
95#elif (defined(__GNUC__) || defined(__clang__)) && defined(__VERSION__)
96# ifdef __clang__
97#  define COMP2 COMP
98# else
99#  define COMP2 COMP "GCC "
100# endif
101  printf (COMP2 "%s\n", __VERSION__);
102#endif
103
104  /************** More information about the C implementation **************/
105
106  /* The following macros are currently used by src/mpfr-cvers.h and/or
107     src/mpfr-impl.h; they may have an influcence on how MPFR is compiled. */
108
109#if defined(__STDC__) || defined(__STDC_VERSION__)
110  (puts) ("[tversion] C standard: __STDC__ = "
111#if defined(__STDC__)
112          MAKE_STR(__STDC__)
113#else
114          "undef"
115#endif
116          ", __STDC_VERSION__ = "
117#if defined(__STDC_VERSION__)
118          MAKE_STR(__STDC_VERSION__)
119#else
120          "undef"
121#endif
122          );
123#endif
124
125#if defined(__GNUC__)
126  (puts) ("[tversion] __GNUC__ = " MAKE_STR(__GNUC__) ", __GNUC_MINOR__ = "
127#if defined(__GNUC_MINOR__)
128          MAKE_STR(__GNUC_MINOR__)
129#else
130          "undef"
131#endif
132#if defined(__STRICT_ANSI__)
133          ", __STRICT_ANSI__"
134#endif
135          );
136#endif
137
138#if defined(__ICC) || defined(__INTEL_COMPILER)
139  (puts) ("[tversion] Intel compiler: __ICC = "
140#if defined(__ICC)
141          MAKE_STR(__ICC)
142#else
143          "undef"
144#endif
145          ", __INTEL_COMPILER = "
146#if defined(__INTEL_COMPILER)
147          MAKE_STR(__INTEL_COMPILER)
148#else
149          "undef"
150#endif
151          );
152#endif
153
154#if defined(_WIN32) || defined(_MSC_VER)
155  (puts) ("[tversion] MS Windows: _WIN32 = "
156#if defined(_WIN32)
157          MAKE_STR(_WIN32)
158#else
159          "undef"
160#endif
161          ", _MSC_VER = "
162#if defined(_MSC_VER)
163          MAKE_STR(_MSC_VER)
164#else
165          "undef"
166#endif
167          );
168#endif
169
170  /* With MinGW64, both __MINGW32__ and __MINGW64__ seem to be defined,
171     but test both, just in case this will change in the future. Tested
172     with "x86_64-w64-mingw32-gcc -dM -E -xc /dev/null" under Debian. */
173#if defined(__MINGW32__) || defined(__MINGW64__)
174  (puts) ("[tversion] MinGW"
175#if defined(__MINGW64__)
176          "64"
177#else
178          "32"
179#endif
180          ": __USE_MINGW_ANSI_STDIO = "
181#if defined(__USE_MINGW_ANSI_STDIO)
182          MAKE_STR(__USE_MINGW_ANSI_STDIO)
183#else
184          "undef"
185#endif
186          );
187#endif
188
189#if defined(__GLIBC__)
190  (puts) ("[tversion] __GLIBC__ = " MAKE_STR(__GLIBC__) ", __GLIBC_MINOR__ = "
191#if defined(__GLIBC_MINOR__)
192          MAKE_STR(__GLIBC_MINOR__)
193#else
194          "undef"
195#endif
196          );
197#endif
198
199  /******************* GMP version and build information *******************/
200
201#ifdef __MPIR_VERSION
202  printf ("[tversion] MPIR: header %d.%d.%d, library %s\n",
203          __MPIR_VERSION, __MPIR_VERSION_MINOR, __MPIR_VERSION_PATCHLEVEL,
204          mpir_version);
205#else
206#ifdef MPFR_USE_MINI_GMP
207  printf ("[tversion] mini-gmp\n");
208#else
209  printf ("[tversion] GMP: header %d.%d.%d, library %s\n",
210          __GNU_MP_VERSION, __GNU_MP_VERSION_MINOR, __GNU_MP_VERSION_PATCHLEVEL,
211          gmp_version);
212#endif
213#endif
214
215#ifdef __GMP_CC
216  printf ("[tversion] __GMP_CC = \"%s\"\n", __GMP_CC);
217#endif
218#ifdef __GMP_CFLAGS
219  printf ("[tversion] __GMP_CFLAGS = \"%s\"\n", __GMP_CFLAGS);
220#endif
221
222  /* The following output is also useful under Unix, where one should get:
223     WinDLL: __GMP_LIBGMP_DLL = 0, MPFR_WIN_THREAD_SAFE_DLL = undef
224     If this is not the case, something is probably broken. We cannot test
225     automatically as some MS Windows implementations may declare some Unix
226     (POSIX) compatibility; for instance, Cygwin32 defines __unix__ (but
227     Cygwin64 does not, probably because providing both MS Windows API and
228     POSIX API is not possible with a 64-bit ABI, since MS Windows is LLP64
229     and Unix is LP64).
230     MPFR_WIN_THREAD_SAFE_DLL is directly set up from __GMP_LIBGMP_DLL;
231     that is why it is output here. */
232  (puts) ("[tversion] WinDLL: __GMP_LIBGMP_DLL = "
233#if defined(__GMP_LIBGMP_DLL)
234          MAKE_STR(__GMP_LIBGMP_DLL)
235#else
236          "undef"
237#endif
238          ", MPFR_WIN_THREAD_SAFE_DLL = "
239#if defined(MPFR_WIN_THREAD_SAFE_DLL)
240          MAKE_STR(MPFR_WIN_THREAD_SAFE_DLL)
241#else
242          "undef"
243#endif
244          );
245
246  /********************* MPFR configuration parameters *********************/
247
248  /* The following code outputs configuration parameters, either set up
249     by the user or determined automatically (default values). */
250
251  if (
252#ifdef MPFR_USE_THREAD_SAFE
253      !
254#endif
255      mpfr_buildopt_tls_p ())
256    {
257      printf ("ERROR! mpfr_buildopt_tls_p() and macros"
258              " do not match!\n");
259      err = 1;
260    }
261
262  if (
263#ifdef MPFR_WANT_FLOAT128
264      !
265#endif
266      mpfr_buildopt_float128_p ())
267    {
268      printf ("ERROR! mpfr_buildopt_float128_p() and macros"
269              " do not match!\n");
270      err = 1;
271    }
272
273  if (
274#ifdef MPFR_WANT_DECIMAL_FLOATS
275      !
276#endif
277      mpfr_buildopt_decimal_p ())
278    {
279      printf ("ERROR! mpfr_buildopt_decimal_p() and macros"
280              " do not match!\n");
281      err = 1;
282    }
283
284  if (
285#if defined(MPFR_HAVE_GMP_IMPL) || defined(WANT_GMP_INTERNALS)
286      !
287#endif
288      mpfr_buildopt_gmpinternals_p ())
289    {
290      printf ("ERROR! mpfr_buildopt_gmpinternals_p() and macros"
291              " do not match!\n");
292      err = 1;
293    }
294
295#if defined(MPFR_HAVE_GMP_IMPL)
296  (puts) ("[tversion] MPFR built with the GMP build (--with-gmp-build)");
297#else
298  (printf) ("[tversion] MPFR_ALLOCA_MAX = %ld\n", (long) MPFR_ALLOCA_MAX);
299#endif
300
301  if (
302#ifdef MPFR_WANT_SHARED_CACHE
303      !
304#endif
305      mpfr_buildopt_sharedcache_p ())
306    {
307      printf ("ERROR! mpfr_buildopt_sharedcache_p() and macros"
308              " do not match!\n");
309      err = 1;
310    }
311
312  (printf) ("[tversion] TLS = %s, float128 = %s, decimal = %s,"
313            " GMP internals = %s\n",
314            mpfr_buildopt_tls_p () ? "yes" : "no",
315            mpfr_buildopt_float128_p () ? "yes" : "no",
316            mpfr_buildopt_decimal_p () ? "yes"
317#if defined(DECIMAL_BID_FORMAT)
318            " (BID)"
319#elif defined(DECIMAL_DPD_FORMAT)
320            " (DPD)"
321#endif
322            : "no",
323            mpfr_buildopt_gmpinternals_p () ? "yes" : "no");
324
325#ifdef MPFR_THREAD_LOCK_METHOD
326# define LOCK_METHOD " (lock method: " MPFR_THREAD_LOCK_METHOD ")"
327#else
328# define LOCK_METHOD ""
329#endif
330
331  (printf) ("[tversion] Shared cache = %s\n",
332            mpfr_buildopt_sharedcache_p () ? "yes" LOCK_METHOD : "no");
333
334  (puts) ("[tversion] intmax_t = "
335#if defined(_MPFR_H_HAVE_INTMAX_T)
336          "yes"
337#else
338          "no"
339#endif
340          ", printf = "
341#if defined(HAVE_STDARG) && !defined(MPFR_USE_MINI_GMP)
342          "yes"
343#else
344          "no"
345#endif
346          ", IEEE floats = "
347#if _MPFR_IEEE_FLOATS
348          "yes"
349#else
350          "no"
351#endif
352          );
353
354  (puts) ("[tversion] gmp_printf: hhd = "
355#if defined(NPRINTF_HH)
356          "no"
357#else
358          "yes"
359#endif
360          ", lld = "
361#if defined(NPRINTF_LL)
362          "no"
363#else
364          "yes"
365#endif
366          ", jd = "
367#if defined(NPRINTF_J)
368          "no"
369#else
370          "yes"
371#endif
372          ", td = "
373#if defined(NPRINTF_T)
374          "no"
375#elif defined(PRINTF_T)
376          "yes"
377#else
378          "?"
379#endif
380          ", Ld = "
381#if defined(NPRINTF_L)
382          "no"
383#elif defined(PRINTF_L)
384          "yes"
385#else
386          "?"
387#endif
388          );
389
390  if (strcmp (mpfr_buildopt_tune_case (), MPFR_TUNE_CASE) != 0)
391    {
392      printf ("ERROR! mpfr_buildopt_tune_case() and MPFR_TUNE_CASE"
393              " do not match!\n  %s\n  %s\n",
394              mpfr_buildopt_tune_case (), MPFR_TUNE_CASE);
395      err = 1;
396    }
397  else
398    printf ("[tversion] MPFR tuning parameters from %s\n", MPFR_TUNE_CASE);
399
400  /**************************** ABI information ****************************/
401
402  (printf) ("[tversion] sizeof(long) = %ld, sizeof(mpfr_intmax_t) = %ld"
403#if defined(_MPFR_H_HAVE_INTMAX_T)
404            ", sizeof(intmax_t) = %ld"
405#endif
406            "\n", (long) sizeof(long), (long) sizeof(mpfr_intmax_t)
407#if defined(_MPFR_H_HAVE_INTMAX_T)
408            , (long) sizeof(intmax_t)
409#endif
410            );
411
412  if (mp_bits_per_limb != GMP_NUMB_BITS)
413    {
414      printf ("ERROR! mp_bits_per_limb != GMP_NUMB_BITS (%ld vs %ld)\n",
415              (long) mp_bits_per_limb, (long) GMP_NUMB_BITS);
416      err = 1;
417    }
418
419  printf ("[tversion] GMP_NUMB_BITS = %ld, sizeof(mp_limb_t) = %ld\n",
420          (long) GMP_NUMB_BITS, (long) sizeof(mp_limb_t));
421
422  /* Concerning the MPFR_LONG_WITHIN_LIMB and MPFR_INTMAX_WITHIN_LIMB macros,
423     if defined, code may be optimized to take these properties into account.
424     If not defined, MPFR should select portable code. So one should ideally
425     get either "y/y" or "n/n"; "n/y" is allowed, but "y/n" is forbidden.
426     Note: MPFR_LONG_WITHIN_LIMB should be defined by the configure script,
427     but may also be defined by the src/mpfr-impl.h header file. */
428#define WITHIN_LIMB(T)                         \
429  (MPFR_LIMB_MAX >= (T) -1 ?                   \
430   ((WM) ? "y/y" : "n/y") :                    \
431   ((WM) ? (err = 1, "y/n (WRONG!)") : "n/n"))
432
433  (printf) ("[tversion] Within limb: long = %s"
434#if defined(_MPFR_H_HAVE_INTMAX_T)
435            ", intmax_t = %s"
436#endif
437            "\n"
438#undef WM
439#if defined(MPFR_LONG_WITHIN_LIMB)
440# define WM 1
441#else
442# define WM 0
443#endif
444            , WITHIN_LIMB (unsigned long)
445#if defined(_MPFR_H_HAVE_INTMAX_T)
446#undef WM
447#if defined(MPFR_INTMAX_WITHIN_LIMB)
448# define WM 1
449#else
450# define WM 0
451#endif
452            , WITHIN_LIMB (uintmax_t)
453#endif
454            );
455
456  printf ("[tversion] _MPFR_PREC_FORMAT = %ld, sizeof(mpfr_prec_t) = %ld\n",
457          (long) _MPFR_PREC_FORMAT, (long) sizeof(mpfr_prec_t));
458
459  printf ("[tversion] _MPFR_EXP_FORMAT = %ld, sizeof(mpfr_exp_t) = %ld\n",
460          (long) _MPFR_EXP_FORMAT, (long) sizeof(mpfr_exp_t));
461
462  printf ("[tversion] sizeof(mpfr_t) = %ld, sizeof(mpfr_ptr) = %ld\n",
463          (long) sizeof(mpfr_t), (long) sizeof(mpfr_ptr));
464
465#define RANGE " range: [%" MPFR_EXP_FSPEC "d,%" MPFR_EXP_FSPEC "d]\n"
466
467  printf ("[tversion] Precision" RANGE,
468          (mpfr_eexp_t) MPFR_PREC_MIN, (mpfr_eexp_t) MPFR_PREC_MAX);
469
470  e = mpfr_get_emin_min ();
471  if (e != MPFR_EMIN_MIN)
472    {
473      printf ("ERROR! mpfr_get_emin_min != MPFR_EMIN_MIN (%"
474              MPFR_EXP_FSPEC "d vs %" MPFR_EXP_FSPEC "d)\n",
475              (mpfr_eexp_t) e, (mpfr_eexp_t) MPFR_EMIN_MIN);
476      err = 1;
477    }
478
479  e = mpfr_get_emax_max ();
480  if (e != MPFR_EMAX_MAX)
481    {
482      printf ("ERROR! mpfr_get_emax_max != MPFR_EMAX_MAX (%"
483              MPFR_EXP_FSPEC "d vs %" MPFR_EXP_FSPEC "d)\n",
484              (mpfr_eexp_t) e, (mpfr_eexp_t) MPFR_EMAX_MAX);
485      err = 1;
486    }
487
488  printf ("[tversion] Max exponent" RANGE,
489          (mpfr_eexp_t) MPFR_EMIN_MIN, (mpfr_eexp_t) MPFR_EMAX_MAX);
490
491  (puts) ("[tversion] Generic ABI code: "
492#if defined(MPFR_GENERIC_ABI)
493          "yes"
494#else
495          "no"
496#endif
497          );
498
499  (puts) ("[tversion] Enable formally proven code: "
500#if defined(MPFR_WANT_PROVEN_CODE)
501          "yes"
502#else
503          "no"
504#endif
505          );
506
507  /************************* Run-time information **************************/
508
509  if (locale != NULL)
510    printf ("[tversion] Locale: %s\n", locale);
511  /* The memory limit should not be changed for "make check".
512     The warning below signals a possible user mistake.
513     Do not use "%zu" because it is not available in C90;
514     the type mpfr_ueexp_t should be sufficiently large. */
515  if (tests_memory_limit != DEFAULT_MEMORY_LIMIT)
516    printf ("[tversion] Warning! Memory limit changed to %" MPFR_EXP_FSPEC
517            "u\n", (mpfr_ueexp_t) tests_memory_limit);
518
519  /*************************************************************************/
520
521  if (errno != 0)
522    {
523      perror ("tversion");
524      err = 1;
525    }
526
527  tests_end_mpfr ();
528
529  return err;
530}
531