xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/tversion.c (revision 9fb66d812c00ebfb445c0b47dea128f32aa6fe96)
1 /* Test file for mpfr_version.
2 
3 Copyright 2004-2020 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
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    * http://sourceforge.net/p/predef/wiki/Compilers/
74    * 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(__GNUC__) || defined(__clang__)) && defined(__VERSION__)
89 # ifdef __clang__
90 #  define COMP2 COMP
91 # else
92 #  define COMP2 COMP "GCC "
93 # endif
94   printf (COMP2 "%s\n", __VERSION__);
95 #endif
96 
97   /************** More information about the C implementation **************/
98 
99   /* The following macros are currently used by src/mpfr-cvers.h and/or
100      src/mpfr-impl.h; they may have an influcence on how MPFR is compiled. */
101 
102 #if defined(__STDC__) || defined(__STDC_VERSION__)
103   (puts) ("[tversion] C standard: __STDC__ = "
104 #if defined(__STDC__)
105           MAKE_STR(__STDC__)
106 #else
107           "undef"
108 #endif
109           ", __STDC_VERSION__ = "
110 #if defined(__STDC_VERSION__)
111           MAKE_STR(__STDC_VERSION__)
112 #else
113           "undef"
114 #endif
115           );
116 #endif
117 
118 #if defined(__GNUC__)
119   (puts) ("[tversion] __GNUC__ = " MAKE_STR(__GNUC__) ", __GNUC_MINOR__ = "
120 #if defined(__GNUC_MINOR__)
121           MAKE_STR(__GNUC_MINOR__)
122 #else
123           "undef"
124 #endif
125 #if defined(__STRICT_ANSI__)
126           ", __STRICT_ANSI__"
127 #endif
128           );
129 #endif
130 
131 #if defined(__ICC) || defined(__INTEL_COMPILER)
132   (puts) ("[tversion] Intel compiler: __ICC = "
133 #if defined(__ICC)
134           MAKE_STR(__ICC)
135 #else
136           "undef"
137 #endif
138           ", __INTEL_COMPILER = "
139 #if defined(__INTEL_COMPILER)
140           MAKE_STR(__INTEL_COMPILER)
141 #else
142           "undef"
143 #endif
144           );
145 #endif
146 
147 #if defined(_WIN32) || defined(_MSC_VER)
148   (puts) ("[tversion] MS Windows: _WIN32 = "
149 #if defined(_WIN32)
150           MAKE_STR(_WIN32)
151 #else
152           "undef"
153 #endif
154           ", _MSC_VER = "
155 #if defined(_MSC_VER)
156           MAKE_STR(_MSC_VER)
157 #else
158           "undef"
159 #endif
160           );
161 #endif
162 
163   /* With MinGW64, both __MINGW32__ and __MINGW64__ seem to be defined,
164      but test both, just in case this will change in the future. Tested
165      with "x86_64-w64-mingw32-gcc -dM -E -xc /dev/null" under Debian. */
166 #if defined(__MINGW32__) || defined(__MINGW64__)
167   (puts) ("[tversion] MinGW"
168 #if defined(__MINGW64__)
169           "64"
170 #else
171           "32"
172 #endif
173           ": __USE_MINGW_ANSI_STDIO = "
174 #if defined(__USE_MINGW_ANSI_STDIO)
175           MAKE_STR(__USE_MINGW_ANSI_STDIO)
176 #else
177           "undef"
178 #endif
179           );
180 #endif
181 
182 #if defined(__GLIBC__)
183   (puts) ("[tversion] __GLIBC__ = " MAKE_STR(__GLIBC__) ", __GLIBC_MINOR__ = "
184 #if defined(__GLIBC_MINOR__)
185           MAKE_STR(__GLIBC_MINOR__)
186 #else
187           "undef"
188 #endif
189           );
190 #endif
191 
192   /******************* GMP version and build information *******************/
193 
194 #ifdef __MPIR_VERSION
195   printf ("[tversion] MPIR: header %d.%d.%d, library %s\n",
196           __MPIR_VERSION, __MPIR_VERSION_MINOR, __MPIR_VERSION_PATCHLEVEL,
197           mpir_version);
198 #else
199 #ifdef MPFR_USE_MINI_GMP
200   printf ("[tversion] mini-gmp\n");
201 #else
202   printf ("[tversion] GMP: header %d.%d.%d, library %s\n",
203           __GNU_MP_VERSION, __GNU_MP_VERSION_MINOR, __GNU_MP_VERSION_PATCHLEVEL,
204           gmp_version);
205 #endif
206 #endif
207 
208 #ifdef __GMP_CC
209   printf ("[tversion] __GMP_CC = \"%s\"\n", __GMP_CC);
210 #endif
211 #ifdef __GMP_CFLAGS
212   printf ("[tversion] __GMP_CFLAGS = \"%s\"\n", __GMP_CFLAGS);
213 #endif
214 
215   /* The following output is also useful under Unix, where one should get:
216      WinDLL: __GMP_LIBGMP_DLL = 0, MPFR_WIN_THREAD_SAFE_DLL = undef
217      If this is not the case, something is probably broken. We cannot test
218      automatically as some MS Windows implementations may declare some Unix
219      (POSIX) compatibility; for instance, Cygwin32 defines __unix__ (but
220      Cygwin64 does not, probably because providing both MS Windows API and
221      POSIX API is not possible with a 64-bit ABI, since MS Windows is LLP64
222      and Unix is LP64).
223      MPFR_WIN_THREAD_SAFE_DLL is directly set up from __GMP_LIBGMP_DLL;
224      that is why it is output here. */
225   (puts) ("[tversion] WinDLL: __GMP_LIBGMP_DLL = "
226 #if defined(__GMP_LIBGMP_DLL)
227           MAKE_STR(__GMP_LIBGMP_DLL)
228 #else
229           "undef"
230 #endif
231           ", MPFR_WIN_THREAD_SAFE_DLL = "
232 #if defined(MPFR_WIN_THREAD_SAFE_DLL)
233           MAKE_STR(MPFR_WIN_THREAD_SAFE_DLL)
234 #else
235           "undef"
236 #endif
237           );
238 
239   /********************* MPFR configuration parameters *********************/
240 
241   /* The following code outputs configuration parameters, either set up
242      by the user or determined automatically (default values). */
243 
244   if (
245 #ifdef MPFR_USE_THREAD_SAFE
246       !
247 #endif
248       mpfr_buildopt_tls_p ())
249     {
250       printf ("ERROR! mpfr_buildopt_tls_p() and macros"
251               " do not match!\n");
252       err = 1;
253     }
254 
255   if (
256 #ifdef MPFR_WANT_FLOAT128
257       !
258 #endif
259       mpfr_buildopt_float128_p ())
260     {
261       printf ("ERROR! mpfr_buildopt_float128_p() and macros"
262               " do not match!\n");
263       err = 1;
264     }
265 
266   if (
267 #ifdef MPFR_WANT_DECIMAL_FLOATS
268       !
269 #endif
270       mpfr_buildopt_decimal_p ())
271     {
272       printf ("ERROR! mpfr_buildopt_decimal_p() and macros"
273               " do not match!\n");
274       err = 1;
275     }
276 
277   if (
278 #if defined(MPFR_HAVE_GMP_IMPL) || defined(WANT_GMP_INTERNALS)
279       !
280 #endif
281       mpfr_buildopt_gmpinternals_p ())
282     {
283       printf ("ERROR! mpfr_buildopt_gmpinternals_p() and macros"
284               " do not match!\n");
285       err = 1;
286     }
287 
288 #if defined(MPFR_HAVE_GMP_IMPL)
289   (puts) ("[tversion] MPFR built with the GMP build (--with-gmp-build)");
290 #else
291   (printf) ("[tversion] MPFR_ALLOCA_MAX = %ld\n", (long) MPFR_ALLOCA_MAX);
292 #endif
293 
294   if (
295 #ifdef MPFR_WANT_SHARED_CACHE
296       !
297 #endif
298       mpfr_buildopt_sharedcache_p ())
299     {
300       printf ("ERROR! mpfr_buildopt_sharedcache_p() and macros"
301               " do not match!\n");
302       err = 1;
303     }
304 
305   (printf) ("[tversion] TLS = %s, float128 = %s, decimal = %s,"
306             " GMP internals = %s\n",
307             mpfr_buildopt_tls_p () ? "yes" : "no",
308             mpfr_buildopt_float128_p () ? "yes" : "no",
309             mpfr_buildopt_decimal_p () ? "yes"
310 #if defined(DECIMAL_BID_FORMAT)
311             " (BID)"
312 #elif defined(DECIMAL_DPD_FORMAT)
313             " (DPD)"
314 #endif
315             : "no",
316             mpfr_buildopt_gmpinternals_p () ? "yes" : "no");
317 
318 #ifdef MPFR_THREAD_LOCK_METHOD
319 # define LOCK_METHOD " (lock method: " MPFR_THREAD_LOCK_METHOD ")"
320 #else
321 # define LOCK_METHOD ""
322 #endif
323 
324   (printf) ("[tversion] Shared cache = %s\n",
325             mpfr_buildopt_sharedcache_p () ? "yes" LOCK_METHOD : "no");
326 
327   (puts) ("[tversion] intmax_t = "
328 #if defined(_MPFR_H_HAVE_INTMAX_T)
329           "yes"
330 #else
331           "no"
332 #endif
333           ", printf = "
334 #if defined(HAVE_STDARG) && !defined(MPFR_USE_MINI_GMP)
335           "yes"
336 #else
337           "no"
338 #endif
339           ", IEEE floats = "
340 #if _MPFR_IEEE_FLOATS
341           "yes"
342 #else
343           "no"
344 #endif
345           );
346 
347   (puts) ("[tversion] gmp_printf: hhd = "
348 #if defined(NPRINTF_HH)
349           "no"
350 #else
351           "yes"
352 #endif
353           ", lld = "
354 #if defined(NPRINTF_LL)
355           "no"
356 #else
357           "yes"
358 #endif
359           ", jd = "
360 #if defined(NPRINTF_J)
361           "no"
362 #else
363           "yes"
364 #endif
365           ", td = "
366 #if defined(NPRINTF_T)
367           "no"
368 #elif defined(PRINTF_T)
369           "yes"
370 #else
371           "?"
372 #endif
373           ", Ld = "
374 #if defined(NPRINTF_L)
375           "no"
376 #elif defined(PRINTF_L)
377           "yes"
378 #else
379           "?"
380 #endif
381           );
382 
383   (puts) ("[tversion] _mulx_u64 = "
384 #if defined(HAVE_MULX_U64)
385           "yes"
386 #else
387           "no"
388 #endif
389           );
390 
391   if (strcmp (mpfr_buildopt_tune_case (), MPFR_TUNE_CASE) != 0)
392     {
393       printf ("ERROR! mpfr_buildopt_tune_case() and MPFR_TUNE_CASE"
394               " do not match!\n  %s\n  %s\n",
395               mpfr_buildopt_tune_case (), MPFR_TUNE_CASE);
396       err = 1;
397     }
398   else
399     printf ("[tversion] MPFR tuning parameters from %s\n", MPFR_TUNE_CASE);
400 
401   /**************************** ABI information ****************************/
402 
403   (printf) ("[tversion] sizeof(long) = %ld, sizeof(mpfr_intmax_t) = %ld"
404 #if defined(_MPFR_H_HAVE_INTMAX_T)
405             ", sizeof(intmax_t) = %ld"
406 #endif
407             "\n", (long) sizeof(long), (long) sizeof(mpfr_intmax_t)
408 #if defined(_MPFR_H_HAVE_INTMAX_T)
409             , (long) sizeof(intmax_t)
410 #endif
411             );
412 
413   if (mp_bits_per_limb != GMP_NUMB_BITS)
414     {
415       printf ("ERROR! mp_bits_per_limb != GMP_NUMB_BITS (%ld vs %ld)\n",
416               (long) mp_bits_per_limb, (long) GMP_NUMB_BITS);
417       err = 1;
418     }
419 
420   printf ("[tversion] GMP_NUMB_BITS = %ld, sizeof(mp_limb_t) = %ld\n",
421           (long) GMP_NUMB_BITS, (long) sizeof(mp_limb_t));
422 
423   /* Concerning the MPFR_LONG_WITHIN_LIMB and MPFR_INTMAX_WITHIN_LIMB macros,
424      if defined, code may be optimized to take these properties into account.
425      If not defined, MPFR should select portable code. So one should ideally
426      get either "y/y" or "n/n"; "n/y" is allowed, but "y/n" is forbidden.
427      Note: MPFR_LONG_WITHIN_LIMB should be defined by the configure script,
428      but may also be defined by the src/mpfr-impl.h header file. */
429 #define WITHIN_LIMB(T)                         \
430   (MPFR_LIMB_MAX >= (T) -1 ?                   \
431    ((WM) ? "y/y" : "n/y") :                    \
432    ((WM) ? (err = 1, "y/n (WRONG!)") : "n/n"))
433 
434   (printf) ("[tversion] Within limb: long = %s"
435 #if defined(_MPFR_H_HAVE_INTMAX_T)
436             ", intmax_t = %s"
437 #endif
438             "\n"
439 #undef WM
440 #if defined(MPFR_LONG_WITHIN_LIMB)
441 # define WM 1
442 #else
443 # define WM 0
444 #endif
445             , WITHIN_LIMB (unsigned long)
446 #if defined(_MPFR_H_HAVE_INTMAX_T)
447 #undef WM
448 #if defined(MPFR_INTMAX_WITHIN_LIMB)
449 # define WM 1
450 #else
451 # define WM 0
452 #endif
453             , WITHIN_LIMB (uintmax_t)
454 #endif
455             );
456 
457   printf ("[tversion] _MPFR_PREC_FORMAT = %ld, sizeof(mpfr_prec_t) = %ld\n",
458           (long) _MPFR_PREC_FORMAT, (long) sizeof(mpfr_prec_t));
459 
460   printf ("[tversion] _MPFR_EXP_FORMAT = %ld, sizeof(mpfr_exp_t) = %ld\n",
461           (long) _MPFR_EXP_FORMAT, (long) sizeof(mpfr_exp_t));
462 
463   printf ("[tversion] sizeof(mpfr_t) = %ld, sizeof(mpfr_ptr) = %ld\n",
464           (long) sizeof(mpfr_t), (long) sizeof(mpfr_ptr));
465 
466 #define RANGE " range: [%" MPFR_EXP_FSPEC "d,%" MPFR_EXP_FSPEC "d]\n"
467 
468   printf ("[tversion] Precision" RANGE,
469           (mpfr_eexp_t) MPFR_PREC_MIN, (mpfr_eexp_t) MPFR_PREC_MAX);
470 
471   e = mpfr_get_emin_min ();
472   if (e != MPFR_EMIN_MIN)
473     {
474       printf ("ERROR! mpfr_get_emin_min != MPFR_EMIN_MIN (%ld vs %ld)\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 (%ld vs %ld)\n",
483               (mpfr_eexp_t) e, (mpfr_eexp_t) MPFR_EMAX_MAX);
484       err = 1;
485     }
486 
487   printf ("[tversion] Max exponent" RANGE,
488           (mpfr_eexp_t) MPFR_EMIN_MIN, (mpfr_eexp_t) MPFR_EMAX_MAX);
489 
490   (puts) ("[tversion] Generic ABI code: "
491 #if defined(MPFR_GENERIC_ABI)
492           "yes"
493 #else
494           "no"
495 #endif
496           );
497 
498   (puts) ("[tversion] Enable formally proven code: "
499 #if defined(MPFR_WANT_PROVEN_CODE)
500           "yes"
501 #else
502           "no"
503 #endif
504           );
505 
506   /************************* Run-time information **************************/
507 
508   if (locale != NULL)
509     printf ("[tversion] Locale: %s\n", locale);
510   /* The memory limit should not be changed for "make check".
511      The warning below signals a possible user mistake.
512      Do not use "%zu" because it is not available in C90;
513      the type mpfr_ueexp_t should be sufficiently large. */
514   if (tests_memory_limit != DEFAULT_MEMORY_LIMIT)
515     printf ("[tversion] Warning! Memory limit changed to %" MPFR_EXP_FSPEC
516             "u\n", (mpfr_ueexp_t) tests_memory_limit);
517 
518   /*************************************************************************/
519 
520   if (errno != 0)
521     {
522       perror ("tversion");
523       err = 1;
524     }
525 
526   tests_end_mpfr ();
527 
528   return err;
529 }
530