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