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