tgeneric.c revision 1.1.1.1.2.1 1 /* Generic test file for functions with one or two arguments (the second being
2 either mpfr_t or double).
3
4 Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
5 Contributed by the AriC and Caramel 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
28 #ifndef TEST_RANDOM_POS
29 /* For the random function: one number on two is negative. */
30 #define TEST_RANDOM_POS 256
31 #endif
32
33 #ifndef TEST_RANDOM_POS2
34 /* For the random function: one number on two is negative. */
35 #define TEST_RANDOM_POS2 256
36 #endif
37
38 #ifndef TEST_RANDOM_EMIN
39 #define TEST_RANDOM_EMIN -256
40 #endif
41
42 #ifndef TEST_RANDOM_EMAX
43 #define TEST_RANDOM_EMAX 255
44 #endif
45
46 /* If the MPFR_SUSPICIOUS_OVERFLOW test fails but this is not a bug,
47 then define TGENERIC_SO_TEST with an adequate test (possibly 0) to
48 omit this particular case. */
49 #ifndef TGENERIC_SO_TEST
50 #define TGENERIC_SO_TEST 1
51 #endif
52
53 #define STR(F) #F
54 #define MAKE_STR(S) STR(S)
55
56 /* The (void *) below is needed to avoid a warning with gcc 4.2+ and functions
57 * with 2 arguments. See <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36299>.
58 */
59 #define TGENERIC_FAIL(S, X, U) \
60 do \
61 { \
62 printf ("%s\nx = ", (S)); \
63 mpfr_out_str (stdout, 2, 0, (X), MPFR_RNDN); \
64 printf ("\n"); \
65 if ((void *) U != 0) \
66 { \
67 printf ("u = "); \
68 mpfr_out_str (stdout, 2, 0, (U), MPFR_RNDN); \
69 printf ("\n"); \
70 } \
71 printf ("yprec = %u, rnd_mode = %s, inexact = %d, flags = %u\n", \
72 (unsigned int) yprec, mpfr_print_rnd_mode (rnd), compare, \
73 (unsigned int) __gmpfr_flags); \
74 exit (1); \
75 } \
76 while (0)
77
78 #define TGENERIC_CHECK_AUX(S, EXPR, U) \
79 do \
80 if (!(EXPR)) \
81 TGENERIC_FAIL (S " in " MAKE_STR(TEST_FUNCTION), x, U); \
82 while (0)
83
84 #undef TGENERIC_CHECK
85 #if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
86 #define TGENERIC_CHECK(S, EXPR) TGENERIC_CHECK_AUX(S, EXPR, u)
87 #else
88 #define TGENERIC_CHECK(S, EXPR) TGENERIC_CHECK_AUX(S, EXPR, 0)
89 #endif
90
91 #ifdef DEBUG_TGENERIC
92 #define TGENERIC_IAUX(F,P,X,U) \
93 do \
94 { \
95 printf ("tgeneric: testing function " STR(F) \
96 ", %s, target prec = %lu\nx = ", \
97 mpfr_print_rnd_mode (rnd), (unsigned long) (P)); \
98 mpfr_out_str (stdout, 2, 0, (X), MPFR_RNDN); \
99 printf ("\n"); \
100 if (U) \
101 { \
102 printf ("u = "); \
103 mpfr_out_str (stdout, 2, 0, (U), MPFR_RNDN); \
104 printf ("\n"); \
105 } \
106 } \
107 while (0)
108 #undef TGENERIC_INFO
109 #if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
110 #define TGENERIC_INFO(F,P) TGENERIC_IAUX(F,P,x,u)
111 #else
112 #define TGENERIC_INFO(F,P) TGENERIC_IAUX(F,P,x,0)
113 #endif
114 #endif
115
116 /* For some functions (for example cos), the argument reduction is too
117 expensive when using mpfr_get_emax(). Then simply define REDUCE_EMAX
118 to some reasonable value before including tgeneric.c. */
119 #ifndef REDUCE_EMAX
120 #define REDUCE_EMAX mpfr_get_emax ()
121 #endif
122
123 static void
124 test_generic (mpfr_prec_t p0, mpfr_prec_t p1, unsigned int nmax)
125 {
126 mpfr_prec_t prec, xprec, yprec;
127 mpfr_t x, y, z, t, w;
128 #ifdef TWO_ARGS
129 mpfr_t u;
130 #elif defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
131 mpfr_t u;
132 double d;
133 #endif
134 mpfr_rnd_t rnd;
135 int inexact, compare, compare2;
136 unsigned int n;
137 unsigned long ctrt = 0, ctrn = 0;
138 mpfr_exp_t old_emin, old_emax;
139
140 old_emin = mpfr_get_emin ();
141 old_emax = mpfr_get_emax ();
142
143 mpfr_inits2 (MPFR_PREC_MIN, x, y, z, t, w, (mpfr_ptr) 0);
144 #if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
145 mpfr_init2 (u, MPFR_PREC_MIN);
146 #endif
147
148 /* generic test */
149 for (prec = p0; prec <= p1; prec++)
150 {
151 mpfr_set_prec (z, prec);
152 mpfr_set_prec (t, prec);
153 yprec = prec + 10;
154 mpfr_set_prec (y, yprec);
155 mpfr_set_prec (w, yprec);
156
157 /* Note: in precision p1, we test 4 special cases. */
158 for (n = 0; n < (prec == p1 ? nmax + 4 : nmax); n++)
159 {
160 int infinite_input = 0;
161
162 xprec = prec;
163 if (randlimb () & 1)
164 {
165 xprec *= (double) randlimb () / MP_LIMB_T_MAX;
166 if (xprec < MPFR_PREC_MIN)
167 xprec = MPFR_PREC_MIN;
168 }
169 mpfr_set_prec (x, xprec);
170 #ifdef TWO_ARGS
171 mpfr_set_prec (u, xprec);
172 #elif defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
173 mpfr_set_prec (u, IEEE_DBL_MANT_DIG);
174 #endif
175
176 if (n > 3 || prec < p1)
177 {
178 #if defined(RAND_FUNCTION)
179 RAND_FUNCTION (x);
180 #if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
181 RAND_FUNCTION (u);
182 #endif
183 #else
184 tests_default_random (x, TEST_RANDOM_POS,
185 TEST_RANDOM_EMIN, TEST_RANDOM_EMAX);
186 #if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
187 tests_default_random (u, TEST_RANDOM_POS2,
188 TEST_RANDOM_EMIN, TEST_RANDOM_EMAX);
189 #endif
190 #endif
191 }
192 else
193 {
194 /* Special cases tested in precision p1 if n <= 3. They are
195 useful really in the extended exponent range. */
196 #if (defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)) && defined(MPFR_ERRDIVZERO)
197 goto next_n;
198 #endif
199 set_emin (MPFR_EMIN_MIN);
200 set_emax (MPFR_EMAX_MAX);
201 if (n <= 1)
202 {
203 mpfr_set_si (x, n == 0 ? 1 : -1, MPFR_RNDN);
204 mpfr_set_exp (x, mpfr_get_emin ());
205 #if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
206 mpfr_set_si (u, randlimb () % 2 == 0 ? 1 : -1, MPFR_RNDN);
207 mpfr_set_exp (u, mpfr_get_emin ());
208 #endif
209 }
210 else /* 2 <= n <= 3 */
211 {
212 if (getenv ("MPFR_CHECK_MAX") == NULL)
213 goto next_n;
214 mpfr_set_si (x, n == 0 ? 1 : -1, MPFR_RNDN);
215 mpfr_setmax (x, REDUCE_EMAX);
216 #if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
217 mpfr_set_si (u, randlimb () % 2 == 0 ? 1 : -1, MPFR_RNDN);
218 mpfr_setmax (u, mpfr_get_emax ());
219 #endif
220 }
221 }
222
223 rnd = RND_RAND ();
224 mpfr_clear_flags ();
225 #ifdef DEBUG_TGENERIC
226 TGENERIC_INFO (TEST_FUNCTION, MPFR_PREC (y));
227 #endif
228 #if defined(TWO_ARGS)
229 compare = TEST_FUNCTION (y, x, u, rnd);
230 #elif defined(DOUBLE_ARG1)
231 d = mpfr_get_d (u, rnd);
232 compare = TEST_FUNCTION (y, d, x, rnd);
233 /* d can be infinite due to overflow in mpfr_get_d */
234 infinite_input |= DOUBLE_ISINF (d);
235 #elif defined(DOUBLE_ARG2)
236 d = mpfr_get_d (u, rnd);
237 compare = TEST_FUNCTION (y, x, d, rnd);
238 /* d can be infinite due to overflow in mpfr_get_d */
239 infinite_input |= DOUBLE_ISINF (d);
240 #else
241 compare = TEST_FUNCTION (y, x, rnd);
242 #endif
243 TGENERIC_CHECK ("Bad inexact flag",
244 (compare != 0) ^ (mpfr_inexflag_p () == 0));
245 ctrt++;
246 /* Consistency test in a reduced exponent range. Doing it
247 for the first 10 samples and for prec == p1 (which has
248 some special cases) should be sufficient. */
249 if (ctrt <= 10 || prec == p1)
250 {
251 unsigned int flags, oldflags = __gmpfr_flags;
252 mpfr_exp_t e, emin, emax, oemin, oemax;
253
254 /* Determine the smallest exponent range containing the
255 exponents of the mpfr_t inputs (x, and u if TWO_ARGS)
256 and output (y). */
257 emin = MPFR_EMAX_MAX;
258 emax = MPFR_EMIN_MIN;
259 if (MPFR_IS_PURE_FP (x))
260 {
261 e = MPFR_GET_EXP (x);
262 if (e < emin)
263 emin = e;
264 if (e > emax)
265 emax = e;
266 }
267 if (MPFR_IS_PURE_FP (y))
268 {
269 e = MPFR_GET_EXP (y);
270 if (e < emin)
271 emin = e;
272 if (e > emax)
273 emax = e;
274 }
275 #if defined(TWO_ARGS)
276 if (MPFR_IS_PURE_FP (u))
277 {
278 e = MPFR_GET_EXP (u);
279 if (e < emin)
280 emin = e;
281 if (e > emax)
282 emax = e;
283 }
284 #endif
285 if (emin > emax)
286 emin = emax; /* case where all values are singular */
287 oemin = mpfr_get_emin ();
288 oemax = mpfr_get_emax ();
289 mpfr_set_emin (emin);
290 mpfr_set_emax (emax);
291 #ifdef DEBUG_TGENERIC
292 /* Useful information in case of assertion failure. */
293 printf ("tgeneric: reduced exponent range [%"
294 MPFR_EXP_FSPEC "d,%" MPFR_EXP_FSPEC "d]\n",
295 (mpfr_eexp_t) emin, (mpfr_eexp_t) emax);
296 #endif
297 mpfr_clear_flags ();
298 #if defined(TWO_ARGS)
299 inexact = TEST_FUNCTION (w, x, u, rnd);
300 #elif defined(DOUBLE_ARG1)
301 inexact = TEST_FUNCTION (w, d, x, rnd);
302 #elif defined(DOUBLE_ARG2)
303 inexact = TEST_FUNCTION (w, x, d, rnd);
304 #else
305 inexact = TEST_FUNCTION (w, x, rnd);
306 #endif
307 flags = __gmpfr_flags;
308 mpfr_set_emin (oemin);
309 mpfr_set_emax (oemax);
310 if (! (SAME_VAL (w, y) &&
311 SAME_SIGN (inexact, compare) &&
312 flags == oldflags))
313 {
314 printf ("Error in " MAKE_STR(TEST_FUNCTION)
315 ", reduced exponent range [%"
316 MPFR_EXP_FSPEC "d,%" MPFR_EXP_FSPEC "d] on:\n",
317 (mpfr_eexp_t) emin, (mpfr_eexp_t) emax);
318 printf ("x = ");
319 mpfr_dump (x);
320 #if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
321 printf ("u = ");
322 mpfr_dump (u);
323 #endif
324 printf ("yprec = %u, rnd_mode = %s\n",
325 (unsigned int) yprec, mpfr_print_rnd_mode (rnd));
326 printf ("Expected:\n y = ");
327 mpfr_dump (y);
328 printf (" inex = %d, flags = %u\n",
329 SIGN (compare), oldflags);
330 printf ("Got:\n w = ");
331 mpfr_dump (w);
332 printf (" inex = %d, flags = %u\n",
333 SIGN (inexact), flags);
334 exit (1);
335 }
336 }
337 if (MPFR_IS_SINGULAR (y))
338 {
339 if (MPFR_IS_NAN (y) || mpfr_nanflag_p ())
340 TGENERIC_CHECK ("Bad NaN flag",
341 MPFR_IS_NAN (y) && mpfr_nanflag_p ());
342 else if (MPFR_IS_INF (y))
343 {
344 TGENERIC_CHECK ("Bad overflow flag",
345 (compare != 0) ^ (mpfr_overflow_p () == 0));
346 TGENERIC_CHECK ("Bad divide-by-zero flag",
347 (compare == 0 && !infinite_input) ^
348 (mpfr_divby0_p () == 0));
349 }
350 else if (MPFR_IS_ZERO (y))
351 TGENERIC_CHECK ("Bad underflow flag",
352 (compare != 0) ^ (mpfr_underflow_p () == 0));
353 }
354 else if (mpfr_divby0_p ())
355 {
356 TGENERIC_CHECK ("Both overflow and divide-by-zero",
357 ! mpfr_overflow_p ());
358 TGENERIC_CHECK ("Both underflow and divide-by-zero",
359 ! mpfr_underflow_p ());
360 TGENERIC_CHECK ("Bad compare value (divide-by-zero)",
361 compare == 0);
362 }
363 else if (mpfr_overflow_p ())
364 {
365 TGENERIC_CHECK ("Both underflow and overflow",
366 ! mpfr_underflow_p ());
367 TGENERIC_CHECK ("Bad compare value (overflow)", compare != 0);
368 mpfr_nexttoinf (y);
369 TGENERIC_CHECK ("Should have been max MPFR number",
370 MPFR_IS_INF (y));
371 }
372 else if (mpfr_underflow_p ())
373 {
374 TGENERIC_CHECK ("Bad compare value (underflow)", compare != 0);
375 mpfr_nexttozero (y);
376 TGENERIC_CHECK ("Should have been min MPFR number",
377 MPFR_IS_ZERO (y));
378 }
379 else if (mpfr_can_round (y, yprec, rnd, rnd, prec))
380 {
381 ctrn++;
382 mpfr_set (t, y, rnd);
383 /* Risk of failures are known when some flags are already set
384 before the function call. Do not set the erange flag, as
385 it will remain set after the function call and no checks
386 are performed in such a case (see the mpfr_erangeflag_p
387 test below). */
388 if (randlimb () & 1)
389 __gmpfr_flags = MPFR_FLAGS_ALL ^ MPFR_FLAGS_ERANGE;
390 #ifdef DEBUG_TGENERIC
391 TGENERIC_INFO (TEST_FUNCTION, MPFR_PREC (z));
392 #endif
393 /* Let's increase the precision of the inputs in a random way.
394 In most cases, this doesn't make any difference, but for
395 the mpfr_fmod bug fixed in r6230, this triggers the bug. */
396 mpfr_prec_round (x, mpfr_get_prec (x) + (randlimb () & 15),
397 MPFR_RNDN);
398 #if defined(TWO_ARGS)
399 mpfr_prec_round (u, mpfr_get_prec (u) + (randlimb () & 15),
400 MPFR_RNDN);
401 inexact = TEST_FUNCTION (z, x, u, rnd);
402 #elif defined(DOUBLE_ARG1)
403 inexact = TEST_FUNCTION (z, d, x, rnd);
404 #elif defined(DOUBLE_ARG2)
405 inexact = TEST_FUNCTION (z, x, d, rnd);
406 #else
407 inexact = TEST_FUNCTION (z, x, rnd);
408 #endif
409 if (mpfr_erangeflag_p ())
410 goto next_n;
411 if (mpfr_nan_p (z) || mpfr_cmp (t, z) != 0)
412 {
413 printf ("results differ for x=");
414 mpfr_out_str (stdout, 2, xprec, x, MPFR_RNDN);
415 #ifdef TWO_ARGS
416 printf ("\nu=");
417 mpfr_out_str (stdout, 2, xprec, u, MPFR_RNDN);
418 #elif defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
419 printf ("\nu=");
420 mpfr_out_str (stdout, 2, IEEE_DBL_MANT_DIG, u, MPFR_RNDN);
421 #endif
422 printf (" prec=%u rnd_mode=%s\n", (unsigned) prec,
423 mpfr_print_rnd_mode (rnd));
424 printf ("got ");
425 mpfr_out_str (stdout, 2, prec, z, MPFR_RNDN);
426 puts ("");
427 printf ("expected ");
428 mpfr_out_str (stdout, 2, prec, t, MPFR_RNDN);
429 puts ("");
430 printf ("approx ");
431 mpfr_print_binary (y);
432 puts ("");
433 exit (1);
434 }
435 compare2 = mpfr_cmp (t, y);
436 /* if rounding to nearest, cannot know the sign of t - f(x)
437 because of composed rounding: y = o(f(x)) and t = o(y) */
438 if (compare * compare2 >= 0)
439 compare = compare + compare2;
440 else
441 compare = inexact; /* cannot determine sign(t-f(x)) */
442 if (((inexact == 0) && (compare != 0)) ||
443 ((inexact > 0) && (compare <= 0)) ||
444 ((inexact < 0) && (compare >= 0)))
445 {
446 printf ("Wrong inexact flag for rnd=%s: expected %d, got %d"
447 "\n", mpfr_print_rnd_mode (rnd), compare, inexact);
448 printf ("x="); mpfr_print_binary (x); puts ("");
449 #if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
450 printf ("u="); mpfr_print_binary (u); puts ("");
451 #endif
452 printf ("y="); mpfr_print_binary (y); puts ("");
453 printf ("t="); mpfr_print_binary (t); puts ("");
454 exit (1);
455 }
456 }
457 else if (getenv ("MPFR_SUSPICIOUS_OVERFLOW") != NULL)
458 {
459 /* For developers only! */
460 MPFR_ASSERTN (MPFR_IS_PURE_FP (y));
461 mpfr_nexttoinf (y);
462 if (MPFR_IS_INF (y) && MPFR_IS_LIKE_RNDZ (rnd, MPFR_IS_NEG (y))
463 && !mpfr_overflow_p () && TGENERIC_SO_TEST)
464 {
465 printf ("Possible bug! |y| is the maximum finite number "
466 "and has been obtained when\nrounding toward zero"
467 " (%s). Thus there is a very probable overflow,\n"
468 "but the overflow flag is not set!\n",
469 mpfr_print_rnd_mode (rnd));
470 printf ("x="); mpfr_print_binary (x); puts ("");
471 #if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
472 printf ("u="); mpfr_print_binary (u); puts ("");
473 #endif
474 exit (1);
475 }
476 }
477
478 next_n:
479 /* In case the exponent range has been changed by
480 tests_default_random() or for special values... */
481 mpfr_set_emin (old_emin);
482 mpfr_set_emax (old_emax);
483 }
484 }
485
486 #ifndef TGENERIC_NOWARNING
487 if (3 * ctrn < 2 * ctrt)
488 printf ("Warning! Too few normal cases in generic tests (%lu / %lu)\n",
489 ctrn, ctrt);
490 #endif
491
492 mpfr_clears (x, y, z, t, w, (mpfr_ptr) 0);
493 #if defined(TWO_ARGS) || defined(DOUBLE_ARG1) || defined(DOUBLE_ARG2)
494 mpfr_clear (u);
495 #endif
496 }
497
498 #undef TEST_RANDOM_POS
499 #undef TEST_RANDOM_POS2
500 #undef TEST_RANDOM_EMIN
501 #undef TEST_RANDOM_EMAX
502 #undef RAND_FUNCTION
503 #undef TWO_ARGS
504 #undef TWO_ARGS_UI
505 #undef TEST_FUNCTION
506 #undef test_generic
507