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