Home | History | Annotate | Line # | Download | only in tests
tgeneric.c revision 1.1.1.6
      1 /* Generic test file for functions with one or two arguments (the second being
      2    either mpfr_t or double or unsigned long).
      3 
      4 Copyright 2001-2023 Free Software Foundation, Inc.
      5 Contributed by the AriC and Caramba projects, INRIA.
      6 
      7 This file is part of the GNU MPFR Library.
      8 
      9 The GNU MPFR Library is free software; you can redistribute it and/or modify
     10 it under the terms of the GNU Lesser General Public License as published by
     11 the Free Software Foundation; either version 3 of the License, or (at your
     12 option) any later version.
     13 
     14 The GNU MPFR Library is distributed in the hope that it will be useful, but
     15 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     16 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
     17 License for more details.
     18 
     19 You should have received a copy of the GNU Lesser General Public License
     20 along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
     21 https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
     22 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
     23 
     24 /* Define TWO_ARGS for two-argument functions like mpfr_pow.
     25    Define DOUBLE_ARG1 or DOUBLE_ARG2 for function with a double operand in
     26    first or second place like sub_d or d_sub.
     27    Define ULONG_ARG1 or ULONG_ARG2 for function with an unsigned long
     28    operand in first or second place like sub_ui or ui_sub.
     29    Define THREE_ARGS for three-argument functions like mpfr_atan2u. */
     30 
     31 /* TODO: Add support for type long and extreme integer values, as done
     32    in tgeneric_ui.c; then tgeneric_ui.c could probably disappear. */
     33 
     34 #ifdef THREE_ARGS
     35 /* This is like TWO_ARGS, but with an additional argument. */
     36 #define TWO_ARGS
     37 #endif
     38 
     39 #if defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
     40 #define DOUBLE_ARG
     41 #else
     42 #undef DOUBLE_ARG
     43 #endif
     44 
     45 #if defined(TWO_ARGS) || defined(DOUBLE_ARG)
     46 #define TWO_ARGS_ALL
     47 #define NSPEC 9
     48 #else
     49 #undef TWO_ARGS_ALL
     50 #define NSPEC 5
     51 #endif
     52 
     53 #if defined(ULONG_ARG1) || defined(ULONG_ARG2) || defined(THREE_ARGS)
     54 #define ULONG_ARG
     55 #else
     56 #undef ULONG_ARG
     57 #endif
     58 
     59 #ifndef TEST_RANDOM_POS
     60 /* For the random function: one number on two is negative. */
     61 #define TEST_RANDOM_POS 256
     62 #endif
     63 
     64 #ifndef TEST_RANDOM_POS2
     65 /* For the random function: one number on two is negative. */
     66 #define TEST_RANDOM_POS2 256
     67 #endif
     68 
     69 #ifndef TEST_RANDOM_EMIN
     70 #define TEST_RANDOM_EMIN -256
     71 #endif
     72 
     73 #ifndef TEST_RANDOM_EMAX
     74 #define TEST_RANDOM_EMAX 255
     75 #endif
     76 
     77 #ifndef TEST_RANDOM_ALWAYS_SCALE
     78 #define TEST_RANDOM_ALWAYS_SCALE 0
     79 #endif
     80 
     81 /* If the MPFR_SUSPICIOUS_OVERFLOW test fails but this is not a bug,
     82    then define TGENERIC_SO_TEST with an adequate test (possibly 0) to
     83    omit this particular case. */
     84 #ifndef TGENERIC_SO_TEST
     85 #define TGENERIC_SO_TEST 1
     86 #endif
     87 
     88 #define TGENERIC_DUMPARGS(X1,X2,U)                                      \
     89   do                                                                    \
     90     {                                                                   \
     91       printf ("x1 = ");                                                 \
     92       mpfr_dump (X1);                                                   \
     93       if ((X2) != 0)                                                    \
     94         {                                                               \
     95           printf ("x2 = ");                                             \
     96           mpfr_dump (X2);                                               \
     97         }                                                               \
     98       if ((U) >= 0)                                                     \
     99         printf ("u = %lu\n", (unsigned long) U);                        \
    100     }                                                                   \
    101   while (0)
    102 
    103 #define TGENERIC_FAIL(S,X1,X2,U)                                        \
    104   do                                                                    \
    105     {                                                                   \
    106       printf ("tgeneric: %s\n", (S));                                   \
    107       TGENERIC_DUMPARGS (X1, X2, U);                                    \
    108       printf ("yprec = %u, rnd_mode = %s, inexact = %d\nflags =",       \
    109               (unsigned int) yprec, mpfr_print_rnd_mode (rnd),          \
    110               compare);                                                 \
    111       flags_out (flags);                                                \
    112       exit (1);                                                         \
    113     }                                                                   \
    114   while (0)
    115 
    116 #define TGENERIC_CHECK_AUX(S,EXPR,X2,U)                                 \
    117   do                                                                    \
    118     if (!(EXPR))                                                        \
    119       TGENERIC_FAIL (S " for " MAKE_STR(TEST_FUNCTION), x, X2, U);      \
    120   while (0)
    121 
    122 #undef TGENERIC_CHECK
    123 #if defined(THREE_ARGS)
    124 #define TGENERIC_CHECK(S,EXPR) TGENERIC_CHECK_AUX (S, EXPR, x2, u)
    125 #elif defined(TWO_ARGS_ALL)
    126 #define TGENERIC_CHECK(S,EXPR) TGENERIC_CHECK_AUX (S, EXPR, x2, -1)
    127 #elif defined(ULONG_ARG)
    128 #define TGENERIC_CHECK(S,EXPR) TGENERIC_CHECK_AUX (S, EXPR, 0, u)
    129 #else
    130 #define TGENERIC_CHECK(S,EXPR) TGENERIC_CHECK_AUX (S, EXPR, 0, -1)
    131 #endif
    132 
    133 #ifdef MPFR_DEBUG_TGENERIC
    134 #define TGENERIC_IAUX(P,X1,X2,U)                                        \
    135   do                                                                    \
    136     {                                                                   \
    137       printf ("tgeneric: testing function " MAKE_STR(TEST_FUNCTION)     \
    138               ", %s, target prec = %u\n",                               \
    139               mpfr_print_rnd_mode (rnd), (unsigned int) (P));           \
    140       TGENERIC_DUMPARGS (X1, X2, U);                                    \
    141     }                                                                   \
    142   while (0)
    143 #undef TGENERIC_INFO
    144 #if defined(THREE_ARGS)
    145 #define TGENERIC_INFO(P) TGENERIC_IAUX (P, x, x2, u)
    146 #elif defined(TWO_ARGS_ALL)
    147 #define TGENERIC_INFO(P) TGENERIC_IAUX (P, x, x2, -1)
    148 #elif defined(ULONG_ARG)
    149 #define TGENERIC_INFO(P) TGENERIC_IAUX (P, x, 0, u)
    150 #else
    151 #define TGENERIC_INFO(P) TGENERIC_IAUX (P, x, 0, -1)
    152 #endif
    153 #endif  /* MPFR_DEBUG_TGENERIC */
    154 
    155 /* For some functions (for example cos), the argument reduction is too
    156    expensive when using mpfr_get_emax(). Then simply define REDUCE_EMAX
    157    to some reasonable value before including tgeneric.c. */
    158 #ifndef REDUCE_EMAX
    159 #define REDUCE_EMAX mpfr_get_emax ()
    160 #endif
    161 
    162 /* same for mpfr_get_emin() */
    163 #ifndef REDUCE_EMIN
    164 #define REDUCE_EMIN mpfr_get_emin ()
    165 #endif
    166 
    167 static void
    168 test_generic (mpfr_prec_t p0, mpfr_prec_t p1, unsigned int nmax)
    169 {
    170   mpfr_prec_t prec, xprec, yprec;
    171   mpfr_t x, y, z, t, w, yd, yu;
    172 #ifdef TWO_ARGS_ALL
    173   mpfr_t x2;
    174 #endif
    175 #if defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
    176   double d;
    177 #endif
    178 #ifdef ULONG_ARG
    179   unsigned long u;
    180 #endif
    181   mpfr_rnd_t rnd;
    182   int inexact, compare, compare2;
    183   unsigned int n;
    184   unsigned long ctrt = 0, ctrn = 0;
    185   mpfr_exp_t old_emin, old_emax;
    186 
    187   old_emin = mpfr_get_emin ();
    188   old_emax = mpfr_get_emax ();
    189 
    190   mpfr_inits2 (MPFR_PREC_MIN, x, y, yd, yu, z, t, w, (mpfr_ptr) 0);
    191 #if defined(TWO_ARGS_ALL)
    192   mpfr_init2 (x2, MPFR_PREC_MIN);
    193 #endif
    194 
    195   /* generic tests */
    196   for (prec = p0; prec <= p1; prec++)
    197     {
    198       /* Number of overflow/underflow tests for each precision.
    199          Since MPFR uses several algorithms and there may also be
    200          early overflow/underflow detection, several tests may be
    201          needed to detect a bug. */
    202       int test_of = 3, test_uf = 3;
    203 
    204       mpfr_set_prec (z, prec);
    205       mpfr_set_prec (t, prec);
    206       yprec = prec + 20;
    207       mpfr_set_prec (y, yprec);
    208       mpfr_set_prec (yd, yprec);
    209       mpfr_set_prec (yu, yprec);
    210       mpfr_set_prec (w, yprec);
    211 
    212       /* Note: in precision p1, we test NSPEC special cases. */
    213       for (n = 0; n < (prec == p1 ? nmax + NSPEC : nmax); n++)
    214         {
    215           int infinite_input = 0;
    216           mpfr_flags_t flags;
    217           mpfr_exp_t oemin, oemax;
    218 
    219           xprec = prec;
    220           if (RAND_BOOL ())
    221             {
    222               /* In half cases, modify the precision of the inputs:
    223                  If the base precision (for the result) is small,
    224                  take a larger input precision in general, else
    225                  take a smaller precision. */
    226               xprec *= (prec < 16 ? 256.0 : 1.0) *
    227                 (double) randlimb () / (double) MPFR_LIMB_MAX;
    228               if (xprec < MPFR_PREC_MIN)
    229                 xprec = MPFR_PREC_MIN;
    230             }
    231           mpfr_set_prec (x, xprec);
    232 #if defined(TWO_ARGS)
    233           mpfr_set_prec (x2, xprec);
    234 #elif defined(DOUBLE_ARG)
    235           mpfr_set_prec (x2, IEEE_DBL_MANT_DIG);
    236 #endif
    237 
    238 #ifdef MPFR_DEBUG_TGENERIC
    239           printf ("prec = %u, n = %u, xprec = %u\n",
    240                   (unsigned int) prec, n, (unsigned int) xprec);
    241 #endif
    242 
    243           /* Generate random arguments, even in the special cases
    244              (this may not be needed, but this is simpler).
    245              Note that if RAND_FUNCTION is defined, this specific
    246              random function is used for all arguments; this is
    247              typically mpfr_random2, which generates a positive
    248              random mpfr_t with long runs of consecutive ones and
    249              zeros in the binary representation. */
    250 
    251 #if defined(RAND_FUNCTION)
    252           RAND_FUNCTION (x);
    253 #if defined(TWO_ARGS_ALL)
    254           RAND_FUNCTION (x2);
    255 #endif
    256 #else  /* ! defined(RAND_FUNCTION) */
    257           tests_default_random (x, TEST_RANDOM_POS,
    258                                 TEST_RANDOM_EMIN, TEST_RANDOM_EMAX,
    259                                 TEST_RANDOM_ALWAYS_SCALE);
    260 #if defined(TWO_ARGS_ALL)
    261           tests_default_random (x2, TEST_RANDOM_POS2,
    262                                 TEST_RANDOM_EMIN, TEST_RANDOM_EMAX,
    263                                 TEST_RANDOM_ALWAYS_SCALE);
    264 #endif
    265 #endif  /* ! defined(RAND_FUNCTION) */
    266 
    267 #if defined(ULONG_ARG)
    268           /* FIXME: If MPFR_LIMB_MAX < ULONG_MAX, large values will
    269              never be tested. */
    270           u = randlimb ();
    271 #endif
    272 
    273           if (n < NSPEC && prec == p1)
    274             {
    275               /* Special cases tested in precision p1 if n < NSPEC. They are
    276                  useful really in the extended exponent range. */
    277               /* TODO: x2 is set even when it is associated with a double;
    278                  check whether this really makes sense. */
    279 #if defined(DOUBLE_ARG) && defined(MPFR_ERRDIVZERO)
    280               goto next_n;
    281 #endif
    282               set_emin (MPFR_EMIN_MIN);
    283               set_emax (MPFR_EMAX_MAX);
    284               if (n == 0)
    285                 {
    286                   mpfr_set_nan (x);
    287                 }
    288               else if (n <= 2)
    289                 {
    290                   MPFR_ASSERTN (n == 1 || n == 2);
    291                   mpfr_set_si (x, n == 1 ? 1 : -1, MPFR_RNDN);
    292                   mpfr_set_exp (x, REDUCE_EMIN);
    293 #if defined(TWO_ARGS_ALL)
    294                   mpfr_set_si (x2, RAND_BOOL () ? -1 : 1, MPFR_RNDN);
    295                   mpfr_set_exp (x2, REDUCE_EMIN);
    296 #endif
    297                 }
    298               else if (n <= 4)
    299                 {
    300                   MPFR_ASSERTN (n == 3 || n == 4);
    301                   mpfr_set_si (x, n == 3 ? 1 : -1, MPFR_RNDN);
    302                   mpfr_setmax (x, REDUCE_EMAX);
    303 #if defined(TWO_ARGS_ALL)
    304                   mpfr_set_si (x2, RAND_BOOL () ? -1 : 1, MPFR_RNDN);
    305                   mpfr_setmax (x2, REDUCE_EMAX);
    306 #endif
    307                 }
    308 #if defined(TWO_ARGS_ALL)
    309               else if (n <= 6)
    310                 {
    311                   MPFR_ASSERTN (n == 5 || n == 6);
    312                   mpfr_set_si (x, n == 5 ? 1 : -1, MPFR_RNDN);
    313                   mpfr_set_exp (x, REDUCE_EMIN);
    314                   mpfr_set_si (x2, RAND_BOOL () ? -1 : 1, MPFR_RNDN);
    315                   mpfr_setmax (x2, REDUCE_EMAX);
    316                 }
    317               else
    318                 {
    319                   MPFR_ASSERTN (n == 7 || n == 8);
    320                   mpfr_set_si (x, n == 7 ? 1 : -1, MPFR_RNDN);
    321                   mpfr_setmax (x, REDUCE_EMAX);
    322                   mpfr_set_si (x2, RAND_BOOL () ? -1 : 1, MPFR_RNDN);
    323                   mpfr_set_exp (x2, REDUCE_EMIN);
    324                 }
    325 #endif  /* two arguments */
    326             }
    327 
    328           /* Exponent range for the test. */
    329           oemin = mpfr_get_emin ();
    330           oemax = mpfr_get_emax ();
    331 
    332           rnd = RND_RAND ();
    333           mpfr_clear_flags ();
    334 #ifdef MPFR_DEBUG_TGENERIC
    335           TGENERIC_INFO (MPFR_PREC (y));
    336 #endif
    337 #if defined(THREE_ARGS)
    338           compare = TEST_FUNCTION (y, x, x2, u, rnd);
    339 #elif defined(TWO_ARGS)
    340           compare = TEST_FUNCTION (y, x, x2, rnd);
    341 #elif defined(DOUBLE_ARG)
    342           d = mpfr_get_d (x2, rnd);
    343 # if defined(DOUBLE_ARG1)
    344           compare = TEST_FUNCTION (y, d, x, rnd);
    345 # elif defined(DOUBLE_ARG2)
    346           compare = TEST_FUNCTION (y, x, d, rnd);
    347 # else
    348 #  error "cannot occur"
    349 # endif
    350           /* d can be infinite due to overflow in mpfr_get_d */
    351           infinite_input |= DOUBLE_ISINF (d);
    352 #elif defined(ULONG_ARG1) && defined(ONE_ARG)
    353           compare = TEST_FUNCTION (y, u, rnd);
    354 #elif defined(ULONG_ARG1)
    355           compare = TEST_FUNCTION (y, u, x, rnd);
    356 #elif defined(ULONG_ARG2)
    357           compare = TEST_FUNCTION (y, x, u, rnd);
    358 #else
    359           compare = TEST_FUNCTION (y, x, rnd);
    360 #endif
    361           flags = __gmpfr_flags;
    362           if (mpfr_get_emin () != oemin ||
    363               mpfr_get_emax () != oemax)
    364             {
    365               printf ("tgeneric: the exponent range has been modified"
    366                       " by the tested function!\n");
    367               exit (1);
    368             }
    369           if (rnd != MPFR_RNDF)
    370             TGENERIC_CHECK ("bad inexact flag",
    371                             (compare != 0) ^ (mpfr_inexflag_p () == 0));
    372           ctrt++;
    373 
    374           /* If rnd = RNDF, check that we obtain the same result as
    375              RNDD or RNDU. */
    376           if (rnd == MPFR_RNDF)
    377             {
    378 #if defined(THREE_ARGS)
    379               TEST_FUNCTION (yd, x, x2, u, MPFR_RNDD);
    380               TEST_FUNCTION (yu, x, x2, u, MPFR_RNDU);
    381 #elif defined(TWO_ARGS)
    382               TEST_FUNCTION (yd, x, x2, MPFR_RNDD);
    383               TEST_FUNCTION (yu, x, x2, MPFR_RNDU);
    384 #elif defined(DOUBLE_ARG1)
    385               d = mpfr_get_d (x2, MPFR_RNDD);
    386               TEST_FUNCTION (yd, d, x, MPFR_RNDD);
    387               d = mpfr_get_d (x2, MPFR_RNDU);
    388               TEST_FUNCTION (yu, d, x, MPFR_RNDU);
    389 #elif defined(DOUBLE_ARG2)
    390               d = mpfr_get_d (x2, MPFR_RNDD);
    391               TEST_FUNCTION (yd, x, d, MPFR_RNDD);
    392               d = mpfr_get_d (x2, MPFR_RNDU);
    393               TEST_FUNCTION (yu, x, d, MPFR_RNDU);
    394 #elif defined(ULONG_ARG1) && defined(ONE_ARG)
    395               TEST_FUNCTION (yd, u, MPFR_RNDD);
    396               TEST_FUNCTION (yu, u, MPFR_RNDU);
    397 #elif defined(ULONG_ARG1)
    398               TEST_FUNCTION (yd, u, x, MPFR_RNDD);
    399               TEST_FUNCTION (yu, u, x, MPFR_RNDU);
    400 #elif defined(ULONG_ARG2)
    401               TEST_FUNCTION (yd, x, u, MPFR_RNDD);
    402               TEST_FUNCTION (yu, x, u, MPFR_RNDU);
    403 #else
    404               TEST_FUNCTION (yd, x, MPFR_RNDD);
    405               TEST_FUNCTION (yu, x, MPFR_RNDU);
    406 #endif
    407               if (! (SAME_VAL (y, yd) || SAME_VAL (y, yu)))
    408                 {
    409                   printf ("tgeneric: error for" MAKE_STR(TEST_FUNCTION)
    410                           ", RNDF; result matches neither RNDD nor RNDU\n");
    411                   printf ("x1 = "); mpfr_dump (x);
    412 #ifdef TWO_ARGS_ALL
    413                   printf ("x2 = "); mpfr_dump (x2);
    414 #endif
    415 #ifdef ULONG_ARG
    416                   printf ("u = %lu\n", u);
    417 #endif
    418                   printf ("yd (RNDD) = "); mpfr_dump (yd);
    419                   printf ("yu (RNDU) = "); mpfr_dump (yu);
    420                   printf ("y  (RNDF) = "); mpfr_dump (y);
    421                   exit (1);
    422                 }
    423             }
    424 
    425           /* Tests in a reduced exponent range. */
    426           {
    427             mpfr_flags_t oldflags = flags;
    428             mpfr_exp_t e, emin, emax;
    429 
    430             /* Determine the smallest exponent range containing the
    431                exponents of the mpfr_t inputs (x, and u if TWO_ARGS)
    432                and output (y). */
    433             emin = MPFR_EMAX_MAX;
    434             emax = MPFR_EMIN_MIN;
    435             if (MPFR_IS_PURE_FP (x))
    436               {
    437                 e = MPFR_GET_EXP (x);
    438                 if (e < emin)
    439                   emin = e;
    440                 if (e > emax)
    441                   emax = e;
    442               }
    443 #if defined(TWO_ARGS)
    444             if (MPFR_IS_PURE_FP (x2))
    445               {
    446                 e = MPFR_GET_EXP (x2);
    447                 if (e < emin)
    448                   emin = e;
    449                 if (e > emax)
    450                   emax = e;
    451               }
    452 #endif
    453             if (MPFR_IS_PURE_FP (y))
    454               {
    455                 e = MPFR_GET_EXP (y);  /* exponent of the result */
    456 
    457                 if (test_of > 0 && e - 1 >= emax)  /* overflow test */
    458                   {
    459                     mpfr_flags_t ex_flags;
    460 
    461                     /* Exponent e of the result > exponents of the inputs;
    462                        let's set emax to e - 1, so that one should get an
    463                        overflow. */
    464                     set_emax (e - 1);
    465 #ifdef MPFR_DEBUG_TGENERIC
    466                     printf ("tgeneric: overflow test (emax = %"
    467                             MPFR_EXP_FSPEC "d)\n",
    468                             (mpfr_eexp_t) __gmpfr_emax);
    469 #endif
    470                     mpfr_clear_flags ();
    471 #if defined(THREE_ARGS)
    472                     inexact = TEST_FUNCTION (w, x, x2, u, rnd);
    473 #elif defined(TWO_ARGS)
    474                     inexact = TEST_FUNCTION (w, x, x2, rnd);
    475 #elif defined(DOUBLE_ARG1)
    476                     inexact = TEST_FUNCTION (w, d, x, rnd);
    477 #elif defined(DOUBLE_ARG2)
    478                     inexact = TEST_FUNCTION (w, x, d, rnd);
    479 #elif defined(ULONG_ARG1) && defined(ONE_ARG)
    480                     inexact = TEST_FUNCTION (w, u, rnd);
    481 #elif defined(ULONG_ARG1)
    482                     inexact = TEST_FUNCTION (w, u, x, rnd);
    483 #elif defined(ULONG_ARG2)
    484                     inexact = TEST_FUNCTION (w, x, u, rnd);
    485 #else
    486                     inexact = TEST_FUNCTION (w, x, rnd);
    487 #endif
    488                     flags = __gmpfr_flags;
    489                     set_emax (oemax);
    490                     ex_flags = MPFR_FLAGS_OVERFLOW | MPFR_FLAGS_INEXACT;
    491                     /* For RNDF, this test makes no sense, since RNDF
    492                        might return either the maximal floating-point
    493                        value or infinity, and the flags might differ in
    494                        those two cases. */
    495                     if (flags != ex_flags && rnd != MPFR_RNDF)
    496                       {
    497                         printf ("tgeneric: error for " MAKE_STR(TEST_FUNCTION)
    498                                 ", reduced exponent range [%"
    499                                 MPFR_EXP_FSPEC "d,%" MPFR_EXP_FSPEC
    500                                 "d] (overflow test) on:\n",
    501                                 (mpfr_eexp_t) oemin, (mpfr_eexp_t) e - 1);
    502                         printf ("x1 = "); mpfr_dump (x);
    503 #ifdef TWO_ARGS_ALL
    504                         printf ("x2 = "); mpfr_dump (x2);
    505 #endif
    506 #ifdef ULONG_ARG
    507                         printf ("u = %lu\n", u);
    508 #endif
    509                         printf ("yprec = %u, rnd_mode = %s\n",
    510                                 (unsigned int) yprec,
    511                                 mpfr_print_rnd_mode (rnd));
    512                         printf ("Expected flags =");
    513                         flags_out (ex_flags);
    514                         printf ("     got flags =");
    515                         flags_out (flags);
    516                         printf ("inex = %d, w = ", inexact);
    517                         mpfr_dump (w);
    518                         exit (1);
    519                       }
    520                     test_of--;
    521                   }
    522 
    523                 if (test_uf > 0 && e + 1 <= emin)  /* underflow test */
    524                   {
    525                     mpfr_flags_t ex_flags;
    526 
    527                     /* Exponent e of the result < exponents of the inputs;
    528                        let's set emin to e + 1, so that one should get an
    529                        underflow. */
    530                     set_emin (e + 1);
    531 #ifdef MPFR_DEBUG_TGENERIC
    532                     printf ("tgeneric: underflow test (emin = %"
    533                             MPFR_EXP_FSPEC "d)\n",
    534                             (mpfr_eexp_t) __gmpfr_emin);
    535 #endif
    536                     mpfr_clear_flags ();
    537 #if defined(THREE_ARGS)
    538                     inexact = TEST_FUNCTION (w, x, x2, u, rnd);
    539 #elif defined(TWO_ARGS)
    540                     inexact = TEST_FUNCTION (w, x, x2, rnd);
    541 #elif defined(DOUBLE_ARG1)
    542                     inexact = TEST_FUNCTION (w, d, x, rnd);
    543 #elif defined(DOUBLE_ARG2)
    544                     inexact = TEST_FUNCTION (w, x, d, rnd);
    545 #elif defined(ULONG_ARG1) && defined(ONE_ARG)
    546                     inexact = TEST_FUNCTION (w, u, rnd);
    547 #elif defined(ULONG_ARG1)
    548                     inexact = TEST_FUNCTION (w, u, x, rnd);
    549 #elif defined(ULONG_ARG2)
    550                     inexact = TEST_FUNCTION (w, x, u, rnd);
    551 #else
    552                     inexact = TEST_FUNCTION (w, x, rnd);
    553 #endif
    554                     flags = __gmpfr_flags;
    555                     set_emin (oemin);
    556                     ex_flags = MPFR_FLAGS_UNDERFLOW | MPFR_FLAGS_INEXACT;
    557                     /* For RNDF, this test makes no sense, since RNDF
    558                        might return either the maximal floating-point
    559                        value or infinity, and the flags might differ in
    560                        those two cases. */
    561                     if (flags != ex_flags && rnd != MPFR_RNDF)
    562                       {
    563                         printf ("tgeneric: error for " MAKE_STR(TEST_FUNCTION)
    564                                 ", reduced exponent range [%"
    565                                 MPFR_EXP_FSPEC "d,%" MPFR_EXP_FSPEC
    566                                 "d] (underflow test) on:\n",
    567                                 (mpfr_eexp_t) e + 1, (mpfr_eexp_t) oemax);
    568                         printf ("x1 = "); mpfr_dump (x);
    569 #ifdef TWO_ARGS_ALL
    570                         printf ("x2 = "); mpfr_dump (x2);
    571 #endif
    572 #ifdef ULONG_ARG
    573                         printf ("u = %lu\n", u);
    574 #endif
    575                         printf ("yprec = %u, rnd_mode = %s\n",
    576                                 (unsigned int) yprec,
    577                                 mpfr_print_rnd_mode (rnd));
    578                         printf ("Expected flags =");
    579                         flags_out (ex_flags);
    580                         printf ("     got flags =");
    581                         flags_out (flags);
    582                         printf ("inex = %d, w = ", inexact);
    583                         mpfr_dump (w);
    584                         exit (1);
    585                       }
    586                     test_uf--;
    587                   }
    588 
    589                 if (e < emin)
    590                   emin = e;
    591                 if (e > emax)
    592                   emax = e;
    593               }  /* MPFR_IS_PURE_FP (y) */
    594 
    595             if (emin > emax)
    596               emin = emax;  /* case where all values are singular */
    597 
    598             /* Consistency test in a reduced exponent range. Doing it
    599                for the first 10 samples and for prec == p1 (which has
    600                some special cases) should be sufficient. */
    601             if (ctrt <= 10 || prec == p1)
    602               {
    603                 set_emin (emin);
    604                 set_emax (emax);
    605 #ifdef MPFR_DEBUG_TGENERIC
    606                 /* Useful information in case of assertion failure. */
    607                 printf ("tgeneric: reduced exponent range [%"
    608                         MPFR_EXP_FSPEC "d,%" MPFR_EXP_FSPEC "d]\n",
    609                         (mpfr_eexp_t) emin, (mpfr_eexp_t) emax);
    610 #endif
    611                 mpfr_clear_flags ();
    612 #if defined(THREE_ARGS)
    613                 inexact = TEST_FUNCTION (w, x, x2, u, rnd);
    614 #elif defined(TWO_ARGS)
    615                 inexact = TEST_FUNCTION (w, x, x2, rnd);
    616 #elif defined(DOUBLE_ARG1)
    617                 inexact = TEST_FUNCTION (w, d, x, rnd);
    618 #elif defined(DOUBLE_ARG2)
    619                 inexact = TEST_FUNCTION (w, x, d, rnd);
    620 #elif defined(ULONG_ARG1) && defined(ONE_ARG)
    621                 inexact = TEST_FUNCTION (w, u, rnd);
    622 #elif defined(ULONG_ARG1)
    623                 inexact = TEST_FUNCTION (w, u, x, rnd);
    624 #elif defined(ULONG_ARG2)
    625                 inexact = TEST_FUNCTION (w, x, u, rnd);
    626 #else
    627                 inexact = TEST_FUNCTION (w, x, rnd);
    628 #endif
    629                 flags = __gmpfr_flags;
    630                 set_emin (oemin);
    631                 set_emax (oemax);
    632                 /* That test makes no sense for RNDF. */
    633                 if (rnd != MPFR_RNDF && ! (SAME_VAL (w, y) &&
    634                        SAME_SIGN (inexact, compare) &&
    635                        flags == oldflags))
    636                   {
    637                     printf ("tgeneric: error for " MAKE_STR(TEST_FUNCTION)
    638                             ", reduced exponent range [%"
    639                             MPFR_EXP_FSPEC "d,%" MPFR_EXP_FSPEC "d] on:\n",
    640                             (mpfr_eexp_t) emin, (mpfr_eexp_t) emax);
    641                     printf ("x1 = "); mpfr_dump (x);
    642 #ifdef TWO_ARGS_ALL
    643                     printf ("x2 = "); mpfr_dump (x2);
    644 #endif
    645 #ifdef ULONG_ARG
    646                     printf ("u = %lu\n", u);
    647 #endif
    648                     printf ("yprec = %u, rnd_mode = %s\n",
    649                             (unsigned int) yprec, mpfr_print_rnd_mode (rnd));
    650                     printf ("Expected:\n  y = ");
    651                     mpfr_dump (y);
    652                     printf ("  inex = %d, flags =", compare);
    653                     flags_out (oldflags);
    654                     printf ("Got:\n  w = ");
    655                     mpfr_dump (w);
    656                     printf ("  inex = %d, flags =", inexact);
    657                     flags_out (flags);
    658                     exit (1);
    659                   }
    660               }
    661 
    662             __gmpfr_flags = oldflags;  /* restore the flags */
    663           }  /* tests in a reduced exponent range */
    664 
    665           if (MPFR_IS_SINGULAR (y))
    666             {
    667               if (MPFR_IS_NAN (y) || mpfr_nanflag_p ())
    668                 TGENERIC_CHECK ("bad NaN flag",
    669                                 MPFR_IS_NAN (y) && mpfr_nanflag_p ());
    670               else if (MPFR_IS_INF (y))
    671                 {
    672                   TGENERIC_CHECK ("bad overflow flag",
    673                                   (compare != 0) ^ (mpfr_overflow_p () == 0));
    674                   TGENERIC_CHECK ("bad divide-by-zero flag",
    675                                   (compare == 0 && !infinite_input) ^
    676                                   (mpfr_divby0_p () == 0));
    677                 }
    678               else if (MPFR_IS_ZERO (y))
    679                 TGENERIC_CHECK ("bad underflow flag",
    680                                 (compare != 0) ^ (mpfr_underflow_p () == 0));
    681             }
    682           else if (mpfr_divby0_p ())
    683             {
    684               TGENERIC_CHECK ("both overflow and divide-by-zero",
    685                               ! mpfr_overflow_p ());
    686               TGENERIC_CHECK ("both underflow and divide-by-zero",
    687                               ! mpfr_underflow_p ());
    688               TGENERIC_CHECK ("bad compare value (divide-by-zero)",
    689                               compare == 0);
    690             }
    691           else if (mpfr_overflow_p ())
    692             {
    693               TGENERIC_CHECK ("both underflow and overflow",
    694                               ! mpfr_underflow_p ());
    695               TGENERIC_CHECK ("bad compare value (overflow)", compare != 0);
    696               mpfr_nexttoinf (y);
    697               TGENERIC_CHECK ("should have been max MPFR number (overflow)",
    698                               MPFR_IS_INF (y));
    699             }
    700           else if (mpfr_underflow_p ())
    701             {
    702               TGENERIC_CHECK ("bad compare value (underflow)", compare != 0);
    703               mpfr_nexttozero (y);
    704               TGENERIC_CHECK ("should have been min MPFR number (underflow)",
    705                               MPFR_IS_ZERO (y));
    706             }
    707           else if (compare == 0 || rnd == MPFR_RNDF ||
    708                    mpfr_can_round (y, yprec, rnd, rnd, prec))
    709             {
    710               ctrn++;
    711               mpfr_set (t, y, rnd);
    712               /* Risk of failures are known when some flags are already set
    713                  before the function call. Do not set the erange flag, as
    714                  it will remain set after the function call and no checks
    715                  are performed in such a case (see the mpfr_erangeflag_p
    716                  test below). */
    717               if (RAND_BOOL ())
    718                 __gmpfr_flags = MPFR_FLAGS_ALL ^ MPFR_FLAGS_ERANGE;
    719 #ifdef MPFR_DEBUG_TGENERIC
    720               TGENERIC_INFO (MPFR_PREC (z));
    721 #endif
    722               /* Let's increase the precision of the inputs in a random way.
    723                  In most cases, this doesn't make any difference, but for
    724                  the mpfr_fmod bug fixed in r6230, this triggers the bug. */
    725               mpfr_prec_round (x, mpfr_get_prec (x) + (randlimb () & 15),
    726                                MPFR_RNDN);
    727 #if defined(TWO_ARGS)
    728               mpfr_prec_round (x2, mpfr_get_prec (x2) + (randlimb () & 15),
    729                                MPFR_RNDN);
    730 #if defined(THREE_ARGS)
    731               inexact = TEST_FUNCTION (z, x, x2, u, rnd);
    732 #else
    733               inexact = TEST_FUNCTION (z, x, x2, rnd);
    734 #endif
    735 #elif defined(DOUBLE_ARG1)
    736               inexact = TEST_FUNCTION (z, d, x, rnd);
    737 #elif defined(DOUBLE_ARG2)
    738               inexact = TEST_FUNCTION (z, x, d, rnd);
    739 #elif defined(ULONG_ARG1) && defined(ONE_ARG)
    740               inexact = TEST_FUNCTION (z, u, rnd);
    741 #elif defined(ULONG_ARG1)
    742               inexact = TEST_FUNCTION (z, u, x, rnd);
    743 #elif defined(ULONG_ARG2)
    744               inexact = TEST_FUNCTION (z, x, u, rnd);
    745 #else
    746               inexact = TEST_FUNCTION (z, x, rnd);
    747 #endif
    748               if (mpfr_erangeflag_p ())
    749                 goto next_n;
    750               if (! mpfr_equal_p (t, z) && rnd != MPFR_RNDF)
    751                 {
    752                   printf ("tgeneric: results differ for "
    753                           MAKE_STR(TEST_FUNCTION) " on\n");
    754                   printf ("x1[%u] = ", (unsigned int) mpfr_get_prec (x));
    755                   mpfr_dump (x);
    756 #ifdef TWO_ARGS_ALL
    757                   printf ("x2[%u] = ", (unsigned int) mpfr_get_prec (x2));
    758                   mpfr_dump (x2);
    759 #endif
    760 #ifdef ULONG_ARG
    761                   printf ("u = %lu\n", u);
    762 #endif
    763                   printf ("prec = %u, rnd_mode = %s\n",
    764                           (unsigned int) prec, mpfr_print_rnd_mode (rnd));
    765                   printf ("Got      ");
    766                   mpfr_dump (z);
    767                   printf ("Expected ");
    768                   mpfr_dump (t);
    769                   printf ("Approx   ");
    770                   mpfr_dump (y);
    771                   exit (1);
    772                 }
    773               compare2 = mpfr_cmp (t, y);
    774               /* if rounding to nearest, cannot know the sign of t - f(x)
    775                  because of composed rounding: y = o(f(x)) and t = o(y) */
    776               if (compare * compare2 >= 0)
    777                 compare = compare + compare2;
    778               else
    779                 compare = inexact; /* cannot determine sign(t-f(x)) */
    780               if (! SAME_SIGN (inexact, compare) && rnd != MPFR_RNDF)
    781                 {
    782                   printf ("Wrong inexact flag for rnd=%s: expected %d, got %d"
    783                           "\n", mpfr_print_rnd_mode (rnd), compare, inexact);
    784                   printf ("x1[%u] = ", (unsigned int) mpfr_get_prec (x));
    785                   mpfr_dump (x);
    786 #ifdef TWO_ARGS_ALL
    787                   printf ("x2[%u] = ", (unsigned int) mpfr_get_prec (x2));
    788                   mpfr_dump (x2);
    789 #endif
    790 #ifdef ULONG_ARG
    791                   printf ("u = %lu\n", u);
    792 #endif
    793                   printf ("y = ");
    794                   mpfr_dump (y);
    795                   printf ("t = ");
    796                   mpfr_dump (t);
    797                   exit (1);
    798                 }
    799             }
    800           else if (getenv ("MPFR_SUSPICIOUS_OVERFLOW") != NULL)
    801             {
    802               /* For developers only! */
    803               MPFR_ASSERTN (MPFR_IS_PURE_FP (y));
    804               mpfr_nexttoinf (y);
    805               if (MPFR_IS_INF (y) && MPFR_IS_LIKE_RNDZ (rnd, MPFR_IS_NEG (y))
    806                   && !mpfr_overflow_p () && TGENERIC_SO_TEST)
    807                 {
    808                   printf ("Possible bug! |y| is the maximum finite number "
    809                           "(with yprec = %u) and has\nbeen obtained when "
    810                           "rounding toward zero (%s). Thus there is a very\n"
    811                           "probable overflow, but the overflow flag is not "
    812                           "set!\n",
    813                           (unsigned int) yprec, mpfr_print_rnd_mode (rnd));
    814                   printf ("x1[%u] = ", (unsigned int) mpfr_get_prec (x));
    815                   mpfr_dump (x);
    816 #ifdef TWO_ARGS_ALL
    817                   printf ("x2[%u] = ", (unsigned int) mpfr_get_prec (x2));
    818                   mpfr_dump (x2);
    819 #endif
    820 #ifdef ULONG_ARG
    821                   printf ("u = %lu\n", u);
    822 #endif
    823                   exit (1);
    824                 }
    825             }
    826 
    827         next_n:
    828           /* In case the exponent range has been changed by
    829              tests_default_random() or for special values... */
    830           set_emin (old_emin);
    831           set_emax (old_emax);
    832         }
    833     }
    834 
    835 if (getenv ("MPFR_TGENERIC_STAT") != NULL)
    836   printf ("tgeneric: normal cases / total = %lu / %lu\n", ctrn, ctrt);
    837 
    838 #ifndef TGENERIC_NOWARNING
    839   if (3 * ctrn < 2 * ctrt)
    840     printf ("Warning! Too few normal cases in generic tests (%lu / %lu)\n",
    841             ctrn, ctrt);
    842 #endif
    843 
    844   mpfr_clears (x, y, yd, yu, z, t, w, (mpfr_ptr) 0);
    845 #ifdef TWO_ARGS_ALL
    846   mpfr_clear (x2);
    847 #endif
    848 }
    849 
    850 #undef TEST_RANDOM_POS
    851 #undef TEST_RANDOM_POS2
    852 #undef TEST_RANDOM_EMIN
    853 #undef TEST_RANDOM_EMAX
    854 #undef TEST_RANDOM_ALWAYS_SCALE
    855 #undef RAND_FUNCTION
    856 #undef THREE_ARGS
    857 #undef TWO_ARGS
    858 #undef TWO_ARGS_ALL
    859 #undef ULONG_ARG
    860 #undef DOUBLE_ARG
    861 #undef DOUBLE_ARG1
    862 #undef DOUBLE_ARG2
    863 #undef ULONG_ARG1
    864 #undef ULONG_ARG2
    865 #undef TEST_FUNCTION
    866 #undef test_generic
    867 #undef NSPEC
    868