xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/tversion.c (revision ba125506a622fe649968631a56eba5d42ff57863)
1 /* Test file for mpfr_version.
2 
3 Copyright 2004-2023 Free Software Foundation, Inc.
4 Contributed by the AriC and Caramba projects, INRIA.
5 
6 This file is part of the GNU MPFR Library.
7 
8 The GNU MPFR 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 MPFR 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 MPFR Library; see the file COPYING.LESSER.  If not, see
20 https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
21 51 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 
39 int
main(void)40 main (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