Home | History | Annotate | Line # | Download | only in tests
      1 /* Miscellaneous support for test programs.
      2 
      3 Copyright 2001-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 /* NOTE. Some tests on macro definitions are already done in src/init2.c
     24  * as static assertions (in general). This allows one to get a failure at
     25  * build time in case of inconsistency (probably due to search path issues
     26  * in header file inclusion). This does not need to be done again in the
     27  * test suite.
     28  */
     29 
     30 #ifdef HAVE_CONFIG_H
     31 # include "config.h"
     32 #endif
     33 
     34 #include <float.h>
     35 
     36 #ifdef HAVE_LOCALE_H
     37 #include <locale.h>
     38 #endif
     39 
     40 #ifdef MPFR_TESTS_FPE_DIV
     41 # ifdef MPFR_TESTS_FPE_TRAP
     42 #  define _GNU_SOURCE /* for feenableexcept */
     43 # endif
     44 # include <fenv.h>
     45 #endif
     46 
     47 #ifdef HAVE_GETTIMEOFDAY
     48 # include <sys/time.h>
     49 #else
     50 # include <time.h>
     51 #endif
     52 
     53 /* <sys/fpu.h> is needed to have union fpc_csr defined under IRIX64
     54    (see below). Let's include it only if need be. */
     55 #if defined HAVE_SYS_FPU_H && defined HAVE_FPC_CSR
     56 # include <sys/fpu.h>
     57 #endif
     58 
     59 #ifdef MPFR_TESTS_TIMEOUT
     60 #include <sys/resource.h>
     61 #endif
     62 
     63 #if defined(HAVE_SIGNAL) || defined(HAVE_SIGACTION)
     64 # include <signal.h>
     65 #endif
     66 
     67 #include "mpfr-test.h"
     68 
     69 #ifdef MPFR_FPU_PREC
     70 /* This option allows to test MPFR on x86 processors when the FPU
     71  * rounding precision has been changed. As MPFR is a library, this can
     72  * occur in practice, either by the calling software or by some other
     73  * library or plug-in used by the calling software. This option is
     74  * mainly for developers. If it is used, then the <fpu_control.h>
     75  * header is assumed to exist and work like under Linux/x86. MPFR does
     76  * not need to be recompiled. So, a possible usage is the following:
     77  *
     78  *   cd tests
     79  *   make clean
     80  *   make check CFLAGS="-g -O2 -ffloat-store -DMPFR_FPU_PREC=_FPU_SINGLE"
     81  *
     82  * i.e. just add -DMPFR_FPU_PREC=... to the CFLAGS found in Makefile.
     83  *
     84  * Notes:
     85  *   + SSE2 (used to implement double's on x86_64, and possibly on x86
     86  *     too, depending on the compiler configuration and flags) is not
     87  *     affected by the dynamic precision.
     88  *   + When the FPU is set to single precision, the behavior of MPFR
     89  *     functions that have a native floating-point type (float, double,
     90  *     long double) as argument or return value is not guaranteed.
     91  */
     92 
     93 #include <fpu_control.h>
     94 
     95 static void
     96 set_fpu_prec (void)
     97 {
     98   fpu_control_t cw;
     99 
    100   _FPU_GETCW(cw);
    101   cw &= ~(_FPU_EXTENDED|_FPU_DOUBLE|_FPU_SINGLE);
    102   cw |= (MPFR_FPU_PREC);
    103   _FPU_SETCW(cw);
    104 }
    105 
    106 #endif
    107 
    108 char             mpfr_rands_initialized = 0;
    109 gmp_randstate_t  mpfr_rands;
    110 
    111 char *locale = NULL;
    112 
    113 /* Programs that test GMP's mp_set_memory_functions() need to set
    114    tests_memory_disabled = 2 before calling tests_start_mpfr(). */
    115 #ifdef MPFR_USE_MINI_GMP
    116 /* disable since mini-gmp does not keep track of old_size in realloc/free */
    117 int tests_memory_disabled = 1;
    118 #else
    119 int tests_memory_disabled = 0;
    120 #endif
    121 
    122 static mpfr_exp_t default_emin, default_emax;
    123 
    124 static void tests_rand_start (void);
    125 static void tests_rand_end   (void);
    126 static void tests_limit_start (void);
    127 
    128 /* We want to always import the function mpfr_dump inside the test
    129    suite, so that we can use it in GDB. But it doesn't work if we build
    130    a Windows DLL (initializer element is not a constant) */
    131 #if !__GMP_LIBGMP_DLL
    132 extern void (*dummy_func) (mpfr_srcptr);
    133 void (*dummy_func)(mpfr_srcptr) = mpfr_dump;
    134 #endif
    135 
    136 /* Various version checks.
    137    A mismatch on the GMP version is not regarded as fatal. A mismatch
    138    on the MPFR version is regarded as fatal, since this means that we
    139    would not check the MPFR library that has just been built (the goal
    140    of "make check") but a different library that is already installed,
    141    i.e. any test result would be meaningless; in such a case, we exit
    142    immediately with an error (exit status = 1).
    143    Return value: 0 for no errors, 1 in case of any non-fatal error.
    144    Note: If the return value is 0, no data must be sent to stdout. */
    145 int
    146 test_version (void)
    147 {
    148   const char *version;
    149   char buffer[256];
    150   int err = 0;
    151 
    152 #ifndef MPFR_USE_MINI_GMP
    153   sprintf (buffer, "%d.%d.%d", __GNU_MP_VERSION, __GNU_MP_VERSION_MINOR,
    154            __GNU_MP_VERSION_PATCHLEVEL);
    155   if (strcmp (buffer, gmp_version) != 0 &&
    156       (__GNU_MP_VERSION_PATCHLEVEL != 0 ||
    157        (sprintf (buffer, "%d.%d", __GNU_MP_VERSION, __GNU_MP_VERSION_MINOR),
    158         strcmp (buffer, gmp_version) != 0)))
    159     err = 1;
    160 
    161   /* In some cases, it may be acceptable to have different versions for
    162      the header and the library, in particular when shared libraries are
    163      used (e.g., after a bug-fix upgrade of the library, and versioning
    164      ensures that this can be done only when the binary interface is
    165      compatible). However, when recompiling software like here, this
    166      should never happen (except if GMP has been upgraded between two
    167      "make check" runs, but there's no reason for that). A difference
    168      between the versions of gmp.h and libgmp probably indicates either
    169      a bad configuration or some other inconsistency in the development
    170      environment, and it is better to fail (in particular for automatic
    171      installations). */
    172   if (err)
    173     {
    174       printf ("ERROR! The versions of gmp.h (%s) and libgmp (%s) do not "
    175               "match.\nThe possible causes are:\n", buffer, gmp_version);
    176       printf ("  * A bad configuration in your include/library search paths.\n"
    177               "  * An inconsistency in the include/library search paths of\n"
    178               "    your development environment; an example:\n"
    179               "      "
    180               "https://gcc.gnu.org/legacy-ml/gcc-help/2010-11/msg00359.html\n"
    181               "  * GMP has been upgraded after the first \"make check\".\n"
    182               "    In such a case, try again after a \"make clean\".\n"
    183               "  * A new or non-standard version naming is used in GMP.\n"
    184               "    In this case, a patch may already be available on the\n"
    185               "    MPFR web site.  Otherwise please report the problem.\n");
    186       printf ("In the first two cases, this may lead to errors, in particular"
    187               " with MPFR.\nIf some other tests fail, please solve that"
    188               " problem first.\n");
    189     }
    190 #endif
    191 
    192   /* VL: I get the following error on an OpenSUSE machine, and changing
    193      the value of shlibpath_overrides_runpath in the libtool file from
    194      'no' to 'yes' fixes the problem. */
    195   version = mpfr_get_version ();
    196   if (strcmp (MPFR_VERSION_STRING, version) == 0)
    197     {
    198       int i;
    199 
    200       sprintf (buffer, "%d.%d.%d", MPFR_VERSION_MAJOR, MPFR_VERSION_MINOR,
    201                MPFR_VERSION_PATCHLEVEL);
    202       for (i = 0; buffer[i] == version[i]; i++)
    203         if (buffer[i] == '\0')
    204           return err;
    205       if (buffer[i] == '\0' && version[i] == '-')
    206         return err;
    207       printf ("%sMPFR_VERSION_MAJOR.MPFR_VERSION_MINOR.MPFR_VERSION_PATCHLEVEL"
    208               " (%s)\nand MPFR_VERSION_STRING (%s) do not match!\nIt seems "
    209               "that the mpfr.h file has been corrupted.\n", err ? "\n" : "",
    210               buffer, version);
    211     }
    212   else
    213     printf (
    214       "%sIncorrect MPFR version! (%s header vs %s library)\n"
    215       "Nothing else has been tested since for this reason, any other test\n"
    216       "may fail.  Please fix this problem first, as suggested below.  It\n"
    217       "probably comes from libtool (included in the MPFR tarball), which\n"
    218       "is responsible for setting up the search paths depending on the\n"
    219       "platform, or automake.\n"
    220       "  * On some platforms such as Solaris, $LD_LIBRARY_PATH overrides\n"
    221       "    the rpath, and if the MPFR library is already installed in a\n"
    222       "    $LD_LIBRARY_PATH directory, you typically get this error.  Do\n"
    223       "    not use $LD_LIBRARY_PATH permanently on such platforms; it may\n"
    224       "    also break other things.\n"
    225       "  * You may have an ld option that specifies a library search path\n"
    226       "    where MPFR can be found, taking the precedence over the path\n"
    227       "    added by libtool.  Check your environment variables, such as\n"
    228       "    LD_OPTIONS under Solaris.  Moreover, under Solaris, the run path\n"
    229       "    generated by libtool 2.4.6 may be incorrect: the build directory\n"
    230       "    may not appear first in the run path; set $LD_LIBRARY_PATH to\n"
    231       "    /path/to/builddir/src/.libs for the tests as a workaround.\n"
    232       "  * Then look at https://www.mpfr.org/mpfr-current/ for any update.\n"
    233       "  * Try again on a completely clean source (some errors might come\n"
    234       "    from a previous build or previous source changes).\n"
    235       "  * If the error still occurs, you can try to change the value of\n"
    236       "    shlibpath_overrides_runpath ('yes' or 'no') in the \"libtool\"\n"
    237       "    file and rebuild MPFR (make clean && make && make check).  You\n"
    238       "    may want to report the problem to the libtool and/or automake\n"
    239       "    developers, with the effect of this change.\n",
    240       err ? "\n" : "", MPFR_VERSION_STRING, version);
    241   /* Note about $LD_LIBRARY_PATH under Solaris:
    242    *   https://en.wikipedia.org/wiki/Rpath#Solaris_ld.so
    243    * This cause has been confirmed by a user who got this error.
    244    * And about the libtool 2.4.6 bug also concerning Solaris:
    245    *   https://debbugs.gnu.org/cgi/bugreport.cgi?bug=30222
    246    *   https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=888059
    247    */
    248   exit (1);
    249 }
    250 
    251 /* The inexact exception occurs very often, and is normal.
    252    The underflow exception also might occur, for example in test_generic
    253    for mpfr_xxx_d functions. Same for overflow. Thus we only check for
    254    the division-by-zero and invalid exceptions, which should not occur
    255    inside MPFR. */
    256 #define FPE_FLAGS (FE_DIVBYZERO | FE_INVALID)
    257 
    258 void
    259 tests_start_mpfr (void)
    260 {
    261   /* Don't buffer, so output is not lost if a test causes a segv, etc.
    262      For stdout, this is important as it will typically be fully buffered
    263      by default with "make check". For stderr, the C standard just says
    264      that it is not fully buffered (it may be line buffered by default);
    265      disabling buffering completely might be useful in some cases.
    266      Warning! No operations must have already been done on stdout/stderr
    267      (this is a requirement of ISO C, and this is important on AIX).
    268      Thus tests_start_mpfr should be called at the beginning of main(),
    269      possibly after some variable settings. */
    270   setbuf (stdout, NULL);
    271   setbuf (stderr, NULL);
    272 
    273   test_version ();
    274 
    275 #if defined HAVE_LOCALE_H && defined HAVE_SETLOCALE
    276   /* Added on 2005-07-09. This allows to test MPFR under various
    277      locales. New bugs will probably be found, in particular with
    278      LC_ALL="tr_TR.ISO8859-9" because of the i/I character... */
    279   locale = setlocale (LC_ALL, "");
    280 #endif
    281 
    282 #ifdef MPFR_FPU_PREC
    283   set_fpu_prec ();
    284 #endif
    285 
    286 #ifdef MPFR_TESTS_FPE_DIV
    287   /* Define to test the use of MPFR_ERRDIVZERO */
    288   feclearexcept (FE_ALL_EXCEPT);
    289 # ifdef MPFR_TESTS_FPE_TRAP
    290   /* to trap the corresponding FP exceptions */
    291   feenableexcept (FPE_FLAGS);
    292 # endif
    293 #endif
    294 
    295   if (tests_memory_disabled != 2)
    296     {
    297       if (tests_memory_disabled == 0)
    298         tests_memory_start ();
    299       tests_rand_start ();
    300     }
    301   tests_limit_start ();
    302 
    303   default_emin = mpfr_get_emin ();
    304   default_emax = mpfr_get_emax ();
    305 }
    306 
    307 void
    308 tests_end_mpfr (void)
    309 {
    310   int err = 0;
    311 
    312   if (mpfr_get_emin () != default_emin)
    313     {
    314       printf ("Default emin value has not been restored!\n");
    315       err = 1;
    316     }
    317 
    318   if (mpfr_get_emax () != default_emax)
    319     {
    320       printf ("Default emax value has not been restored!\n");
    321       err = 1;
    322     }
    323 
    324   mpfr_free_cache ();
    325   mpfr_free_cache2 (MPFR_FREE_GLOBAL_CACHE);
    326   if (tests_memory_disabled != 2)
    327     {
    328       tests_rand_end ();
    329       if (tests_memory_disabled == 0)
    330         tests_memory_end ();
    331     }
    332 
    333 #ifdef MPFR_TESTS_FPE_DIV
    334   /* Define to test the use of MPFR_ERRDIVZERO */
    335   if (fetestexcept (FPE_FLAGS))
    336     {
    337       /* With MPFR_ERRDIVZERO, such exceptions should never occur
    338          because the purpose of defining MPFR_ERRDIVZERO is to avoid
    339          all the FP divisions by 0. */
    340       printf ("Some floating-point exception(s) occurred:");
    341       if (fetestexcept (FE_DIVBYZERO))
    342         printf (" DIVBYZERO");  /* e.g. from 1.0 / 0.0 to generate an inf */
    343       if (fetestexcept (FE_INVALID))
    344         printf (" INVALID");    /* e.g. from 0.0 / 0.0 to generate a NaN */
    345       printf ("\n");
    346       err = 1;
    347     }
    348 #endif
    349 
    350   if (err)
    351     exit (err);
    352 }
    353 
    354 static void
    355 tests_limit_start (void)
    356 {
    357 #ifdef MPFR_TESTS_TIMEOUT
    358   struct rlimit rlim[1];
    359   char *timeoutp;
    360   int timeout;
    361 
    362   timeoutp = getenv ("MPFR_TESTS_TIMEOUT");
    363   timeout = timeoutp != NULL ? atoi (timeoutp) : MPFR_TESTS_TIMEOUT;
    364   if (timeout > 0)
    365     {
    366       /* We need to call getrlimit first to initialize rlim_max to
    367          an acceptable value for setrlimit. When enabled, timeouts
    368          are regarded as important: we don't want to take too much
    369          CPU time on machines shared with other users. So, if we
    370          can't set the timeout, we exit immediately. */
    371       if (getrlimit (RLIMIT_CPU, rlim))
    372         {
    373           printf ("Error: getrlimit failed\n");
    374           exit (1);
    375         }
    376       rlim->rlim_cur = timeout;
    377       if (setrlimit (RLIMIT_CPU, rlim))
    378         {
    379           printf ("Error: setrlimit failed\n");
    380           exit (1);
    381         }
    382     }
    383 #endif
    384 }
    385 
    386 static void
    387 tests_rand_start (void)
    388 {
    389   char           *perform_seed;
    390   unsigned long  seed;
    391 
    392   if (mpfr_rands_initialized)
    393     {
    394       printf (
    395         "Please let tests_start() initialize the global mpfr_rands, i.e.\n"
    396         "ensure that function is called before the first use of RANDS.\n");
    397       exit (1);
    398     }
    399 
    400   gmp_randinit_default (mpfr_rands);
    401   mpfr_rands_initialized = 1;
    402 
    403   perform_seed = getenv ("GMP_CHECK_RANDOMIZE");
    404   if (perform_seed != NULL)
    405     {
    406       seed = strtoul (perform_seed, NULL, 10);
    407       if (! (seed == 0 || seed == 1))
    408         {
    409           printf ("Re-seeding with GMP_CHECK_RANDOMIZE=%lu\n", seed);
    410           gmp_randseed_ui (mpfr_rands, seed);
    411         }
    412       else
    413         {
    414 #ifdef HAVE_GETTIMEOFDAY
    415           struct timeval  tv;
    416           gettimeofday (&tv, NULL);
    417           /* Note: If time_t is a "floating type" (as allowed by ISO C99),
    418              the cast below can yield undefined behavior. But this would
    419              be uncommon (gettimeofday() is specified by POSIX only and
    420              POSIX requires time_t to be an integer type) and this line
    421              is not executed by default. So, this should be OK. Moreover,
    422              gettimeofday() is marked obsolescent by POSIX.1-2008. */
    423           seed = 1000000 * (unsigned long) tv.tv_sec + tv.tv_usec;
    424 #else
    425           time_t  tv;
    426           time (&tv);
    427           seed = tv;
    428 #endif
    429           gmp_randseed_ui (mpfr_rands, seed);
    430           printf ("Seed GMP_CHECK_RANDOMIZE=%lu "
    431                   "(include this in bug reports)\n", seed);
    432         }
    433     }
    434   else
    435     gmp_randseed_ui (mpfr_rands, 0x2143FEDC);
    436 }
    437 
    438 static void
    439 tests_rand_end (void)
    440 {
    441   RANDS_CLEAR ();
    442 }
    443 
    444 /* true if subnormals are supported for double */
    445 int
    446 have_subnorm_dbl (void)
    447 {
    448   volatile double x = DBL_MIN, y;
    449 
    450   y = x / 2.0;
    451   return 2.0 * y == x;
    452 }
    453 
    454 /* true if subnormals are supported for float */
    455 int
    456 have_subnorm_flt (void)
    457 {
    458   volatile float x = FLT_MIN, y;
    459 
    460   y = x / 2.0f;
    461   return 2.0f * y == x;
    462 }
    463 
    464 /* initialization function for tests using the hardware floats
    465    Not very useful now. */
    466 void
    467 mpfr_test_init (void)
    468 {
    469 #ifdef HAVE_FPC_CSR
    470   /* to get subnormal numbers on IRIX64 */
    471   union fpc_csr exp;
    472 
    473   exp.fc_word = get_fpc_csr();
    474   exp.fc_struct.flush = 0;
    475   set_fpc_csr(exp.fc_word);
    476 #endif
    477 
    478   /* generate DBL_EPSILON with a loop to avoid that the compiler
    479      optimizes the code below in non-IEEE 754 mode, deciding that
    480      c = d is always false. */
    481 #if 0
    482   for (eps = 1.0; eps != DBL_EPSILON; eps /= 2.0);
    483   c = 1.0 + eps;
    484   d = eps * (1.0 - eps) / 2.0;
    485   d += c;
    486   if (c != d)
    487     {
    488       printf ("Warning: IEEE 754 standard not fully supported\n"
    489               "         (maybe extended precision not disabled)\n"
    490               "         Some tests may fail\n");
    491     }
    492 #endif
    493 }
    494 
    495 
    496 /* generate a random limb */
    497 mp_limb_t
    498 randlimb (void)
    499 {
    500   mp_limb_t limb;
    501 
    502   mpfr_rand_raw (&limb, RANDS, GMP_NUMB_BITS);
    503   return limb;
    504 }
    505 
    506 unsigned long
    507 randulong (void)
    508 {
    509 #ifdef MPFR_LONG_WITHIN_LIMB
    510 
    511   return randlimb ();
    512 
    513 #else
    514 
    515   unsigned long u = 0, v = 0;
    516 
    517   while (u |= randlimb (), v |= MPFR_LIMB_MAX, v != ULONG_MAX)
    518     {
    519       u <<= GMP_NUMB_BITS;
    520       v <<= GMP_NUMB_BITS;
    521     }
    522 
    523   return u;
    524 
    525 #endif
    526 }
    527 
    528 long
    529 randlong (void)
    530 {
    531   unsigned long u = randulong ();
    532 
    533   return ULONG2LONG (u);
    534 }
    535 
    536 /* returns ulp(x) for x a 'normal' double-precision number */
    537 double
    538 Ulp (double x)
    539 {
    540    double y, eps;
    541 
    542    if (x < 0) x = -x;
    543 
    544    y = x * 2.220446049250313080847263336181640625e-16 ; /* x / 2^52 */
    545 
    546    /* as ulp(x) <= y = x/2^52 < 2*ulp(x),
    547    we have x + ulp(x) <= x + y <= x + 2*ulp(x),
    548    therefore o(x + y) = x + ulp(x) or x + 2*ulp(x) */
    549 
    550    eps =  x + y;
    551    eps = eps - x; /* ulp(x) or 2*ulp(x) */
    552 
    553    return (eps > y) ? 0.5 * eps : eps;
    554 }
    555 
    556 /* returns the number of ulp's between a and b,
    557    where a and b can be any floating-point number, except NaN
    558  */
    559 int
    560 ulp (double a, double b)
    561 {
    562   double twoa;
    563 
    564   if (a == b) return 0; /* also deals with a=b=inf or -inf */
    565 
    566   twoa = a + a;
    567   if (twoa == a) /* a is +/-0.0 or +/-Inf */
    568     return ((b < a) ? INT_MAX : -INT_MAX);
    569 
    570   return (int) ((a - b) / Ulp (a));
    571 }
    572 
    573 /* return double m*2^e */
    574 double
    575 dbl (double m, int e)
    576 {
    577   if (e >=0 )
    578     while (e-- > 0)
    579       m *= 2.0;
    580   else
    581     while (e++ < 0)
    582       m /= 2.0;
    583   return m;
    584 }
    585 
    586 /* Warning: NaN values cannot be distinguished if MPFR_NANISNAN is defined. */
    587 int
    588 Isnan (double d)
    589 {
    590   return (d) != (d);
    591 }
    592 
    593 void
    594 d_trace (const char *name, double d)
    595 {
    596   double x = d;
    597   unsigned char *p = (unsigned char *) &x;
    598   int  i;
    599 
    600   if (name != NULL && name[0] != '\0')
    601     printf ("%s = ", name);
    602 
    603   printf ("[");
    604   for (i = 0; i < (int) sizeof (double); i++)
    605     {
    606       if (i != 0)
    607         printf (" ");
    608       printf ("%02X", (unsigned int) p[i]);
    609     }
    610   printf ("] %.20g\n", d);
    611 }
    612 
    613 void
    614 ld_trace (const char *name, long double ld)
    615 {
    616   long double x = ld;
    617   unsigned char *p = (unsigned char *) &x;
    618   int  i;
    619 
    620   if (name != NULL && name[0] != '\0')
    621     printf ("%s = ", name);
    622 
    623   printf ("[");
    624   for (i = 0; i < (int) sizeof (long double); i++)
    625     {
    626       if (i != 0)
    627         printf (" ");
    628       printf ("%02X", (unsigned int) p[i]);
    629     }
    630   printf ("] %.20Lg\n", ld);
    631 }
    632 
    633 void
    634 n_trace (const char *name, mp_limb_t *p, mp_size_t n)
    635 {
    636   unsigned char *buf;
    637   size_t bufsize;
    638   mp_size_t i, m;
    639 
    640   if (name != NULL && name[0] != '\0')
    641     printf ("%s=", name);
    642 
    643   /* similar to gmp_printf ("%NX\n",...), which is not available
    644      with mini-gmp */
    645   bufsize = 2 + ((mpfr_prec_t) n * GMP_NUMB_BITS - 1) / 4;
    646   buf = (unsigned char *) tests_allocate (bufsize);
    647   m = mpn_get_str (buf, 16, p, n);
    648   i = 0;
    649   while (i < m - 1 && buf[i] == 0)
    650     i++;  /* skip leading zeros (keeping at least one digit) */
    651   while (i < m)
    652     putchar ("0123456789ABCDEF"[buf[i++]]);
    653   putchar ('\n');
    654   tests_free (buf, bufsize);
    655 }
    656 
    657 /* Open a file in the SRCDIR directory, i.e. the "tests" source directory,
    658    which is different from the current directory when objdir is different
    659    from srcdir. One should generally use this function instead of fopen
    660    directly. */
    661 FILE *
    662 src_fopen (const char *filename, const char *mode)
    663 {
    664 #ifndef SRCDIR
    665   return fopen (filename, mode);
    666 #else
    667   const char *srcdir = SRCDIR;
    668   char *buffer;
    669   size_t buffsize;
    670   FILE *f;
    671 
    672   buffsize = strlen (filename) + strlen (srcdir) + 2;
    673   buffer = (char *) tests_allocate (buffsize);
    674   if (buffer == NULL)
    675     {
    676       printf ("src_fopen: failed to alloc memory)\n");
    677       exit (1);
    678     }
    679   sprintf (buffer, "%s/%s", srcdir, filename);
    680   f = fopen (buffer, mode);
    681   tests_free (buffer, buffsize);
    682   return f;
    683 #endif
    684 }
    685 
    686 void
    687 set_emin (mpfr_exp_t exponent)
    688 {
    689   if (mpfr_set_emin (exponent))
    690     {
    691       printf ("set_emin: setting emin to %" MPFR_EXP_FSPEC "d failed\n",
    692               (mpfr_eexp_t) exponent);
    693       exit (1);
    694     }
    695 }
    696 
    697 void
    698 set_emax (mpfr_exp_t exponent)
    699 {
    700   if (mpfr_set_emax (exponent))
    701     {
    702       printf ("set_emax: setting emax to %" MPFR_EXP_FSPEC "d failed\n",
    703               (mpfr_eexp_t) exponent);
    704       exit (1);
    705     }
    706 }
    707 
    708 /* pos is 512 times the proportion of negative numbers.
    709    If pos=256, half of the numbers are negative.
    710    If pos=0, all generated numbers are positive.
    711 */
    712 void
    713 tests_default_random (mpfr_ptr x, int pos, mpfr_exp_t emin, mpfr_exp_t emax,
    714                       int always_scale)
    715 {
    716   MPFR_ASSERTN (emin <= emax);
    717   MPFR_ASSERTN (emin >= MPFR_EMIN_MIN);
    718   MPFR_ASSERTN (emax <= MPFR_EMAX_MAX);
    719   /* but it isn't required that emin and emax are in the current
    720      exponent range (see below), so that underflow/overflow checks
    721      can be done on 64-bit machines without a manual change of the
    722      exponent range (well, this is a bit ugly...). */
    723 
    724   mpfr_urandomb (x, RANDS);
    725   if (MPFR_IS_PURE_FP (x) && (emin >= 1 || always_scale || RAND_BOOL ()))
    726     {
    727       mpfr_exp_t e;
    728       e = emin + (mpfr_exp_t) (randlimb () % (emax - emin + 1));
    729       /* Note: There should be no overflow here because both terms are
    730          between MPFR_EMIN_MIN and MPFR_EMAX_MAX. */
    731       MPFR_ASSERTD (e >= emin && e <= emax);
    732       if (mpfr_set_exp (x, e))
    733         {
    734           /* The random number doesn't fit in the current exponent range.
    735              In this case, test the function in the extended exponent range,
    736              which should be restored by the caller. */
    737           set_emin (MPFR_EMIN_MIN);
    738           set_emax (MPFR_EMAX_MAX);
    739           mpfr_set_exp (x, e);
    740         }
    741     }
    742   if (randlimb () % 512 < pos)
    743     mpfr_neg (x, x, MPFR_RNDN);
    744 }
    745 
    746 /* If sb = -1, then the function is tested in only one rounding mode
    747    (the one provided in rnd) and the ternary value is not checked.
    748    Otherwise, the function is tested in the 5 rounding modes, rnd must
    749    initially be MPFR_RNDZ, y = RNDZ(f(x)), and sb is 0 if f(x) is exact,
    750    1 if f(x) is inexact (in which case, y must be a regular number,
    751    i.e. not the result of an overflow or an underflow); the successive
    752    rounding modes are:
    753      * MPFR_RNDZ, MPFR_RNDD, MPFR_RNDA, MPFR_RNDU, MPFR_RNDN for positive y;
    754      * MPFR_RNDZ, MPFR_RNDU, MPFR_RNDA, MPFR_RNDD, MPFR_RNDN for negative y;
    755    for the last test MPFR_RNDN, the target precision is decreased by 1 in
    756    order to be able to deduce the result (anyway, for a hard-to-round case
    757    in directed rounding modes, if yprec is chosen to be minimum precision
    758    preserving this hard-to-round case, then one has a hard-to-round case
    759    in round-to-nearest for precision yprec-1). If the target precision was
    760    MPFR_PREC_MIN, then skip the MPFR_RNDN test; thus to test exact special
    761    cases, use a target precision larger than MPFR_PREC_MIN.
    762    Note: if y is a regular number, sb corresponds to the sticky bit when
    763    considering round-to-nearest with precision yprec-1.
    764    As examples of use, see the calls to test5rm from the data_check and
    765    bad_cases functions. */
    766 static void
    767 test5rm (int (*fct) (FLIST), mpfr_srcptr x, mpfr_ptr y, mpfr_ptr z,
    768          mpfr_rnd_t rnd, int sb, const char *name)
    769 {
    770   mpfr_prec_t yprec = MPFR_PREC (y);
    771   mpfr_rnd_t rndnext = MPFR_RND_MAX;  /* means uninitialized */
    772   int expected_inex = INT_MIN;
    773 
    774   MPFR_ASSERTN (sb == -1 || rnd == MPFR_RNDZ);
    775   mpfr_set_prec (z, yprec);
    776   while (1)
    777     {
    778       int inex;
    779 
    780       MPFR_ASSERTN (rnd != MPFR_RND_MAX);
    781       inex = fct (z, x, rnd);
    782       if (sb == -1)
    783         expected_inex = inex;  /* not checked */
    784       else if (rnd != MPFR_RNDN)
    785         expected_inex =
    786           sb == 0 ? 0 : MPFR_IS_LIKE_RNDD (rnd, MPFR_SIGN (y)) ? -1 : 1;
    787       MPFR_ASSERTN (expected_inex != INT_MIN);
    788       if (!(SAME_VAL (y, z) && SAME_SIGN (inex, expected_inex)))
    789         {
    790           printf ("test5rm: error for %s with xprec=%lu, yprec=%lu, rnd=%s\n"
    791                   "x = ",
    792                   name, (unsigned long) MPFR_PREC (x), (unsigned long) yprec,
    793                   mpfr_print_rnd_mode (rnd));
    794           mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN);
    795           printf ("\nexpected ");
    796           mpfr_out_str (stdout, 16, 0, y, MPFR_RNDN);
    797           printf ("\ngot      ");
    798           mpfr_out_str (stdout, 16, 0, z, MPFR_RNDN);
    799           printf ("\n");
    800           if (sb != -1)
    801             printf ("Expected inex = %d, got %d\n", expected_inex, inex);
    802           exit (1);
    803         }
    804 
    805       if (sb == -1 || rnd == MPFR_RNDN)
    806         break;
    807       else if (rnd == MPFR_RNDZ)
    808         {
    809           rnd = MPFR_IS_NEG (y) ? MPFR_RNDU : MPFR_RNDD;
    810           rndnext = MPFR_RNDA;
    811         }
    812       else
    813         {
    814           rnd = rndnext;
    815           if (rnd == MPFR_RNDA)
    816             {
    817               if (sb)
    818                 mpfr_nexttoinf (y);
    819               rndnext = MPFR_IS_NEG (y) ? MPFR_RNDD : MPFR_RNDU;
    820             }
    821           else if (rndnext != MPFR_RNDN)
    822             rndnext = MPFR_RNDN;
    823           else
    824             {
    825               if (yprec == MPFR_PREC_MIN)
    826                 break;
    827               /* If sb = 1, then mpfr_nexttoinf was called on y for the
    828                  MPFR_RNDA test, i.e. y = RNDA(yprec,f(x)); we use MPFR_RNDZ
    829                  since one has the property RNDN(p,w) = RNDZ(p,RNDA(p+1,w))
    830                  when w is not a midpoint in precision p. If sb = 0, then
    831                  y = f(x), so that RNDN(yprec-1,f(x)) = RNDN(yprec-1,y). */
    832               inex = mpfr_prec_round (y, --yprec, sb ? MPFR_RNDZ : MPFR_RNDN);
    833               expected_inex = sb ?
    834                 MPFR_SIGN (y) * (inex == 0 ? 1 : -1) : inex;
    835               mpfr_set_prec (z, yprec);
    836             }
    837         }
    838     }
    839 }
    840 
    841 /* Check data in file f for function foo, with name 'name'.
    842    Each line consists of the file f one:
    843 
    844    xprec yprec rnd x y
    845 
    846    where:
    847 
    848    xprec is the input precision
    849    yprec is the output precision
    850    rnd is the rounding mode (n, z, u, d, a, Z, *)
    851    x is the input (hexadecimal format)
    852    y is the expected output (hexadecimal format) for foo(x) with rounding rnd
    853 
    854    If rnd is Z, then y is the expected output in round-toward-zero and
    855    it is assumed to be inexact; the four directed rounding modes are
    856    tested, and the round-to-nearest mode is tested in precision yprec-1.
    857    See details in the description of test5rm above.
    858 
    859    If rnd is *, y must be an exact case (possibly a special case).
    860    All the rounding modes are tested and the ternary value is checked
    861    (it must be 0).
    862  */
    863 void
    864 data_check (const char *f, int (*foo) (FLIST), const char *name)
    865 {
    866   FILE *fp;
    867   long int xprec, yprec;  /* not mpfr_prec_t because of the fscanf */
    868   mpfr_t x, y, z;
    869   mpfr_rnd_t rnd;
    870   char r;
    871   int c;
    872 
    873   fp = fopen (f, "r");
    874   if (fp == NULL)
    875     fp = src_fopen (f, "r");
    876   if (fp == NULL)
    877     {
    878       char *v = (char *) MPFR_VERSION_STRING;
    879 
    880       /* In the '-dev' versions, assume that the data file exists and
    881          return an error if the file cannot be opened to make sure
    882          that such failures are detected. */
    883       while (*v != '\0')
    884         v++;
    885       if (v[-4] == '-' && v[-3] == 'd' && v[-2] == 'e' && v[-1] == 'v')
    886         {
    887           printf ("Error: unable to open file '%s'\n", f);
    888           exit (1);
    889         }
    890       else
    891         return;
    892     }
    893 
    894   mpfr_init (x);
    895   mpfr_init (y);
    896   mpfr_init (z);
    897 
    898   while (!feof (fp))
    899     {
    900       /* skip whitespace, for consistency */
    901       if (fscanf (fp, " ") == EOF)
    902         {
    903           if (ferror (fp))
    904             {
    905               perror ("data_check");
    906               exit (1);
    907             }
    908           else
    909             break;  /* end of file */
    910         }
    911 
    912       if ((c = getc (fp)) == EOF)
    913         {
    914           if (ferror (fp))
    915             {
    916               perror ("data_check");
    917               exit (1);
    918             }
    919           else
    920             break;  /* end of file */
    921         }
    922 
    923       if (c == '#') /* comment: read entire line */
    924         {
    925           do
    926             {
    927               c = getc (fp);
    928             }
    929           while (!feof (fp) && c != '\n');
    930         }
    931       else
    932         {
    933           ungetc (c, fp);
    934 
    935           c = fscanf (fp, "%ld %ld %c", &xprec, &yprec, &r);
    936           MPFR_ASSERTN (MPFR_PREC_COND (xprec));
    937           MPFR_ASSERTN (MPFR_PREC_COND (yprec));
    938           if (c == EOF)
    939             {
    940               perror ("data_check");
    941               exit (1);
    942             }
    943           else if (c != 3)
    944             {
    945               printf ("Error: corrupted line in file '%s'\n", f);
    946               exit (1);
    947             }
    948 
    949           switch (r)
    950             {
    951             case 'n':
    952               rnd = MPFR_RNDN;
    953               break;
    954             case 'z': case 'Z':
    955               rnd = MPFR_RNDZ;
    956               break;
    957             case 'u':
    958               rnd = MPFR_RNDU;
    959               break;
    960             case 'd':
    961               rnd = MPFR_RNDD;
    962               break;
    963             case '*':
    964               rnd = MPFR_RND_MAX; /* non-existing rounding mode */
    965               break;
    966             default:
    967               printf ("Error: unexpected rounding mode"
    968                       " in file '%s': %c\n", f, (int) r);
    969               exit (1);
    970             }
    971           mpfr_set_prec (x, xprec);
    972           mpfr_set_prec (y, yprec);
    973           if (mpfr_inp_str (x, fp, 0, MPFR_RNDN) == 0)
    974             {
    975               printf ("Error: corrupted argument in file '%s'\n", f);
    976               exit (1);
    977             }
    978           if (mpfr_inp_str (y, fp, 0, MPFR_RNDN) == 0)
    979             {
    980               printf ("Error: corrupted result in file '%s'\n", f);
    981               exit (1);
    982             }
    983           if (getc (fp) != '\n')
    984             {
    985               printf ("Error: result not followed by \\n in file '%s'\n", f);
    986               exit (1);
    987             }
    988           /* Skip whitespace, in particular at the end of the file. */
    989           if (fscanf (fp, " ") == EOF && ferror (fp))
    990             {
    991               perror ("data_check");
    992               exit (1);
    993             }
    994           if (r == '*')
    995             test5rm (foo, x, y, z, MPFR_RNDZ, 0, name);
    996           else
    997             test5rm (foo, x, y, z, rnd, r == 'Z' ? 1 : -1, name);
    998         }
    999     }
   1000 
   1001   mpfr_clear (x);
   1002   mpfr_clear (y);
   1003   mpfr_clear (z);
   1004 
   1005   fclose (fp);
   1006 }
   1007 
   1008 /* Test n random bad cases. A precision py in [pymin,pymax] and
   1009  * a number y of precision py are chosen randomly. One computes
   1010  * x = inv(y) in precision px = py + psup (rounded to nearest).
   1011  * Then (in general), y is a bad case for fct in precision py (in
   1012  * the directed rounding modes, but also in the rounding-to-nearest
   1013  * mode for some lower precision: see data_check).
   1014  * fct, inv, name: data related to the function.
   1015  * pos, emin, emax: arguments for tests_default_random.
   1016  * For debugging purpose (e.g. in case of crash or infinite loop),
   1017  * you can set the MPFR_DEBUG_BADCASES environment variable to 1 in
   1018  * order to output information about the tested worst cases. You can
   1019  * also enable logging (when supported), but this may give too much
   1020  * information.
   1021  */
   1022 void
   1023 bad_cases (int (*fct)(FLIST), int (*inv)(FLIST), const char *name,
   1024            int pos, mpfr_exp_t emin, mpfr_exp_t emax,
   1025            mpfr_prec_t pymin, mpfr_prec_t pymax, mpfr_prec_t psup,
   1026            int n)
   1027 {
   1028   mpfr_t x, y, z;
   1029   char *dbgenv;
   1030   int cnt = 0, i, dbg;
   1031   mpfr_exp_t old_emin, old_emax;
   1032 
   1033   old_emin = mpfr_get_emin ();
   1034   old_emax = mpfr_get_emax ();
   1035 
   1036   dbgenv = getenv ("MPFR_DEBUG_BADCASES");
   1037   dbg = dbgenv != 0 ? atoi (dbgenv) : 0;  /* debug level */
   1038   mpfr_inits2 (MPFR_PREC_MIN, x, y, z, (mpfr_ptr) 0);
   1039   for (i = 0; i < n; i++)
   1040     {
   1041       mpfr_prec_t px, py, pz;
   1042       int inex_inv, inex, sb;
   1043 
   1044       if (dbg)
   1045         printf ("bad_cases: %s, i = %d\n", name, i);
   1046       py = pymin + (randlimb () % (pymax - pymin + 1));
   1047       mpfr_set_prec (y, py);
   1048       tests_default_random (y, pos, emin, emax, 0);
   1049       if (dbg)
   1050         {
   1051           printf ("bad_cases: yprec =%6ld, y = ", (long) py);
   1052           mpfr_out_str (stdout, 16, 0, y, MPFR_RNDN);
   1053           printf ("\n");
   1054         }
   1055       px = py + psup;
   1056       mpfr_set_prec (x, px);
   1057       if (dbg)
   1058         printf ("bad_cases: xprec =%6ld\n", (long) px);
   1059       mpfr_clear_flags ();
   1060       inex_inv = inv (x, y, MPFR_RNDN);
   1061       if (mpfr_nanflag_p () || mpfr_overflow_p () || mpfr_underflow_p ())
   1062         {
   1063           if (dbg)
   1064             printf ("bad_cases: no normal inverse\n");
   1065           goto next_i;
   1066         }
   1067       if (dbg > 1)
   1068         {
   1069           printf ("bad_cases: x = ");
   1070           mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN);
   1071           printf ("\n");
   1072         }
   1073       pz = px;
   1074       do
   1075         {
   1076           pz += 32;
   1077           mpfr_set_prec (z, pz);
   1078           sb = fct (z, x, MPFR_RNDN) != 0;
   1079           if (!sb)
   1080             {
   1081               if (dbg)
   1082                 {
   1083                   printf ("bad_cases: exact case z = ");
   1084                   mpfr_out_str (stdout, 16, 0, z, MPFR_RNDN);
   1085                   printf ("\n");
   1086                 }
   1087               if (inex_inv)
   1088                 {
   1089                   if (dbg)
   1090                     printf ("bad_cases: f exact while f^(-1) inexact\n");
   1091                   goto does_not_match;
   1092                 }
   1093               inex = 0;
   1094               break;
   1095             }
   1096           if (dbg)
   1097             {
   1098               if (dbg > 1)
   1099                 {
   1100                   printf ("bad_cases: %s(x) ~= ", name);
   1101                   mpfr_out_str (stdout, 16, 0, z, MPFR_RNDN);
   1102                 }
   1103               else
   1104                 {
   1105                   printf ("bad_cases:   [MPFR_RNDZ]  ~= ");
   1106                   mpfr_out_str (stdout, 16, 40, z, MPFR_RNDZ);
   1107                 }
   1108               printf ("\n");
   1109             }
   1110           inex = mpfr_prec_round (z, py, MPFR_RNDN);
   1111           if (mpfr_nanflag_p () || mpfr_overflow_p () || mpfr_underflow_p ()
   1112               || ! mpfr_equal_p (z, y))
   1113             {
   1114               /* This may occur when psup is not large enough: evaluating
   1115                  x = (f^(-1))(y) then z = f(x) may not give back y if the
   1116                  precision of x is too small. */
   1117             does_not_match:
   1118               if (dbg)
   1119                 {
   1120                   printf ("bad_cases: inverse doesn't match for %s\ny = ",
   1121                           name);
   1122                   mpfr_out_str (stdout, 16, 0, y, MPFR_RNDN);
   1123                   printf ("\nz = ");
   1124                   mpfr_out_str (stdout, 16, 0, z, MPFR_RNDN);
   1125                   printf ("\n");
   1126                 }
   1127               goto next_i;
   1128             }
   1129         }
   1130       while (inex == 0);
   1131       /* We really have a bad case (or some special case). */
   1132       if (mpfr_zero_p (z))
   1133         {
   1134           /* This can occur on tlog (GMP_CHECK_RANDOMIZE=1630879377004032
   1135              in r14570, 2021-09-07):
   1136              y = -0, giving x = 1 and z = 0. We have y = z, but here,
   1137              y and z have different signs. Since test5rm will test f(x)
   1138              and its sign (in particular for 0), we need to take the
   1139              sign of f(x), i.e. of z.
   1140              Note: To avoid this special case, one might want to detect and
   1141              ignore y = 0 (of any sign) when taking the random number above,
   1142              as this case should be redundant with some other tests. */
   1143           mpfr_set (y, z, MPFR_RNDN);
   1144           py = MPFR_PREC_MIN;
   1145         }
   1146       else
   1147         {
   1148           do
   1149             py--;
   1150           while (py >= MPFR_PREC_MIN &&
   1151                  mpfr_prec_round (z, py, MPFR_RNDZ) == 0);
   1152           py++;
   1153         }
   1154       /* py is now the smallest output precision such that we have
   1155          a bad case in the directed rounding modes. */
   1156       if (mpfr_prec_round (y, py, MPFR_RNDZ) != 0)
   1157         {
   1158           printf ("Internal error for i = %d\n", i);
   1159           exit (1);
   1160         }
   1161       if ((inex > 0 && MPFR_IS_POS (z)) ||
   1162           (inex < 0 && MPFR_IS_NEG (z)))
   1163         {
   1164           mpfr_nexttozero (y);
   1165           if (mpfr_zero_p (y))
   1166             goto next_i;
   1167         }
   1168       if (dbg)
   1169         {
   1170           printf ("bad_cases: yprec =%6ld, y = ", (long) py);
   1171           mpfr_out_str (stdout, 16, 0, y, MPFR_RNDN);
   1172           printf ("\n");
   1173         }
   1174       /* Note: y is now the expected result rounded toward zero. */
   1175       test5rm (fct, x, y, z, MPFR_RNDZ, sb, name);
   1176       cnt++;
   1177     next_i:
   1178       /* In case the exponent range has been changed by
   1179          tests_default_random()... */
   1180       set_emin (old_emin);
   1181       set_emax (old_emax);
   1182     }
   1183   mpfr_clears (x, y, z, (mpfr_ptr) 0);
   1184 
   1185   if (dbg)
   1186     printf ("bad_cases: %d bad cases over %d generated values for %s\n",
   1187             cnt, n, name);
   1188 
   1189   if (getenv ("MPFR_CHECK_BADCASES") && n - cnt > n/10)
   1190     {
   1191       printf ("bad_cases: too few bad cases (%d over %d generated values)"
   1192               " for %s\n", cnt, n, name);
   1193       exit (1);
   1194     }
   1195 }
   1196 
   1197 void
   1198 flags_out (unsigned int flags)
   1199 {
   1200   int none = 1;
   1201 
   1202   if (flags & MPFR_FLAGS_UNDERFLOW)
   1203     none = 0, printf (" underflow");
   1204   if (flags & MPFR_FLAGS_OVERFLOW)
   1205     none = 0, printf (" overflow");
   1206   if (flags & MPFR_FLAGS_NAN)
   1207     none = 0, printf (" nan");
   1208   if (flags & MPFR_FLAGS_INEXACT)
   1209     none = 0, printf (" inexact");
   1210   if (flags & MPFR_FLAGS_ERANGE)
   1211     none = 0, printf (" erange");
   1212   if (none)
   1213     printf (" none");
   1214   printf (" (%u)\n", flags);
   1215 }
   1216 
   1217 static void
   1218 abort_called (int x)
   1219 {
   1220   /* Ok, abort has been called */
   1221   exit (0);
   1222 }
   1223 
   1224 /* This function has to be called for a test
   1225    that will call the abort function */
   1226 void
   1227 tests_expect_abort (void)
   1228 {
   1229 #if defined(HAVE_SIGACTION)
   1230   struct sigaction act;
   1231   int ret;
   1232 
   1233   memset (&act, 0, sizeof act);
   1234   act.sa_handler = abort_called;
   1235   ret = sigaction (SIGABRT, &act, NULL);
   1236   if (ret != 0)
   1237     {
   1238       /* Can't register error handler: Skip test */
   1239       exit (77);
   1240     }
   1241 #elif defined(HAVE_SIGNAL)
   1242   signal (SIGABRT, abort_called);
   1243 #else
   1244   /* Can't register error handler: Skip test */
   1245   exit (77);
   1246 #endif
   1247 }
   1248 
   1249 /* Guess whether the test runs within Valgrind.
   1250    Note: This should work at least under Linux and Solaris.
   1251    If need be, support for macOS (with DYLD_INSERT_LIBRARIES) and
   1252    i386 FreeBSD on amd64 (with LD_32_PRELOAD) could be added; thanks
   1253    to Paul Floyd for the information.
   1254    Up-to-date information should be found at
   1255    <https://stackoverflow.com/a/62364698/3782797>. */
   1256 int
   1257 tests_run_within_valgrind (void)
   1258 {
   1259   char *p;
   1260 
   1261   p = getenv ("LD_PRELOAD");
   1262   if (p == NULL)
   1263     return 0;
   1264   return (strstr (p, "/valgrind/") != NULL ||
   1265           strstr (p, "/vgpreload") != NULL);
   1266 }
   1267