xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/tgeneric.c (revision cef8759bd76c1b621f8eab8faa6f208faabc2e15)
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-2018 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 http://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                           "and has been obtained when\nrounding toward zero"
766                           " (%s). Thus there is a very probable overflow,\n"
767                           "but the overflow flag is not set!\n",
768                           mpfr_print_rnd_mode (rnd));
769                   printf ("x = ");
770                   mpfr_dump (x);
771 #ifdef NEED_U
772                   printf ("u = ");
773                   mpfr_dump (u);
774 #endif
775                   exit (1);
776                 }
777             }
778 
779         next_n:
780           /* In case the exponent range has been changed by
781              tests_default_random() or for special values... */
782           mpfr_set_emin (old_emin);
783           mpfr_set_emax (old_emax);
784         }
785     }
786 
787 #ifndef TGENERIC_NOWARNING
788   if (3 * ctrn < 2 * ctrt)
789     printf ("Warning! Too few normal cases in generic tests (%lu / %lu)\n",
790             ctrn, ctrt);
791 #endif
792 
793   mpfr_clears (x, y, yd, yu, z, t, w, (mpfr_ptr) 0);
794 #ifdef NEED_U
795   mpfr_clear (u);
796 #endif
797 }
798 
799 #undef TEST_RANDOM_POS
800 #undef TEST_RANDOM_POS2
801 #undef TEST_RANDOM_EMIN
802 #undef TEST_RANDOM_EMAX
803 #undef TEST_RANDOM_ALWAYS_SCALE
804 #undef RAND_FUNCTION
805 #undef TWO_ARGS
806 #undef TWO_ARGS_ALL
807 #undef NEED_U
808 #undef DOUBLE_ARG1
809 #undef DOUBLE_ARG2
810 #undef ULONG_ARG1
811 #undef ULONG_ARG2
812 #undef TEST_FUNCTION
813 #undef test_generic
814 #undef NSPEC
815