xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/tgeneric.c (revision ba125506a622fe649968631a56eba5d42ff57863)
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
test_generic(mpfr_prec_t p0,mpfr_prec_t p1,unsigned int nmax)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