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