1 /* Test file for round away. 2 3 Copyright 2000-2020 Free Software Foundation, Inc. 4 Contributed by the AriC and Caramba projects, INRIA. 5 6 This file is part of the GNU MPFR Library. 7 8 The GNU MPFR Library is free software; you can redistribute it and/or modify 9 it under the terms of the GNU Lesser General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or (at your 11 option) any later version. 12 13 The GNU MPFR Library is distributed in the hope that it will be useful, but 14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16 License for more details. 17 18 You should have received a copy of the GNU Lesser General Public License 19 along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see 20 https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., 21 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ 22 23 #include "mpfr-test.h" 24 25 #define DISP(s,t) \ 26 do \ 27 { \ 28 printf (s); \ 29 mpfr_out_str (stdout, 2, 0, t, MPFR_RNDN); \ 30 } \ 31 while (0) 32 33 #define DISP2(s,t) do { DISP(s,t); putchar ('\n'); } while (0) 34 35 #define SPECIAL_MAX 12 36 37 static void 38 set_special (mpfr_ptr x, unsigned int select) 39 { 40 MPFR_ASSERTN (select < SPECIAL_MAX); 41 switch (select) 42 { 43 case 0: 44 MPFR_SET_NAN (x); 45 break; 46 case 1: 47 MPFR_SET_INF (x); 48 MPFR_SET_POS (x); 49 break; 50 case 2: 51 MPFR_SET_INF (x); 52 MPFR_SET_NEG (x); 53 break; 54 case 3: 55 MPFR_SET_ZERO (x); 56 MPFR_SET_POS (x); 57 break; 58 case 4: 59 MPFR_SET_ZERO (x); 60 MPFR_SET_NEG (x); 61 break; 62 case 5: 63 mpfr_set_str_binary (x, "1"); 64 break; 65 case 6: 66 mpfr_set_str_binary (x, "-1"); 67 break; 68 case 7: 69 mpfr_set_str_binary (x, "1e-1"); 70 break; 71 case 8: 72 mpfr_set_str_binary (x, "1e+1"); 73 break; 74 case 9: 75 mpfr_const_pi (x, MPFR_RNDN); 76 break; 77 case 10: 78 mpfr_const_pi (x, MPFR_RNDN); 79 MPFR_SET_EXP (x, MPFR_GET_EXP (x)-1); 80 break; 81 default: 82 mpfr_urandomb (x, RANDS); 83 break; 84 } 85 } 86 /* same than mpfr_cmp, but returns 0 for both NaN's */ 87 static int 88 mpfr_compare (mpfr_srcptr a, mpfr_srcptr b) 89 { 90 return (MPFR_IS_NAN(a)) ? !MPFR_IS_NAN(b) : 91 (MPFR_IS_NAN(b) || mpfr_cmp(a, b)); 92 } 93 94 static void 95 test3 (int (*testfunc)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_rnd_t), 96 const char *foo) 97 { 98 mpfr_t ref1, ref2, ref3; 99 mpfr_t res1; 100 mpfr_prec_t p1, p2, p3; 101 int i, inexa, inexd; 102 mpfr_rnd_t r; 103 104 p1 = (randlimb () % 200) + MPFR_PREC_MIN; 105 p2 = (randlimb () % 200) + MPFR_PREC_MIN; 106 p3 = (randlimb () % 200) + MPFR_PREC_MIN; 107 108 mpfr_init2 (ref1, p1); 109 mpfr_init2 (ref2, p2); 110 mpfr_init2 (ref3, p3); 111 mpfr_init2 (res1, p1); 112 113 /* for each variable, consider each of the following 6 possibilities: 114 NaN, +Infinity, -Infinity, +0, -0 or a random number */ 115 for (i = 0; i < SPECIAL_MAX * SPECIAL_MAX; i++) 116 { 117 set_special (ref2, i%SPECIAL_MAX); 118 set_special (ref3, i/SPECIAL_MAX); 119 120 inexa = testfunc (res1, ref2, ref3, MPFR_RNDA); 121 r = MPFR_IS_POS (res1) ? MPFR_RNDU : MPFR_RNDD; 122 inexd = testfunc (ref1, ref2, ref3, r); 123 124 if (mpfr_compare (res1, ref1) || inexa != inexd) 125 { 126 printf ("Error with RNDA for %s with ", foo); 127 DISP("x=",ref2); DISP2(", y=",ref3); 128 printf ("inexa=%d inexd=%d\n", inexa, inexd); 129 printf ("expected "); mpfr_dump (ref1); 130 printf ("got "); mpfr_dump (res1); 131 exit (1); 132 } 133 } 134 135 mpfr_clear (ref1); 136 mpfr_clear (ref2); 137 mpfr_clear (ref3); 138 mpfr_clear (res1); 139 } 140 141 static void 142 test4 (int (*testfunc)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_srcptr, 143 mpfr_rnd_t), const char *foo) 144 { 145 mpfr_t ref, op1, op2, op3; 146 mpfr_prec_t pout, p1, p2, p3; 147 mpfr_t res; 148 int i, j, k, inexa, inexd; 149 mpfr_rnd_t r; 150 151 pout = (randlimb () % 200) + MPFR_PREC_MIN; 152 p1 = (randlimb () % 200) + MPFR_PREC_MIN; 153 p2 = (randlimb () % 200) + MPFR_PREC_MIN; 154 p3 = (randlimb () % 200) + MPFR_PREC_MIN; 155 156 mpfr_init2 (ref, pout); 157 mpfr_init2 (res, pout); 158 mpfr_init2 (op1, p1); 159 mpfr_init2 (op2, p2); 160 mpfr_init2 (op3, p3); 161 162 /* for each variable, consider each of the following 6 possibilities: 163 NaN, +Infinity, -Infinity, +0, -0 or a random number */ 164 165 for (i = 0; i < SPECIAL_MAX; i++) 166 { 167 set_special (op1, i); 168 for (j = 0; j < SPECIAL_MAX; j++) 169 { 170 set_special (op2, j); 171 for (k = 0; k < SPECIAL_MAX; k++) 172 { 173 set_special (op3, k); 174 175 inexa = testfunc (res, op1, op2, op3, MPFR_RNDA); 176 r = MPFR_IS_POS (res) ? MPFR_RNDU : MPFR_RNDD; 177 inexd = testfunc (ref, op1, op2, op3, r); 178 179 if (mpfr_compare (res, ref) || inexa != inexd) 180 { 181 printf ("Error with RNDA for %s with ", foo); 182 DISP("a=", op1); DISP(", b=", op2); DISP2(", c=", op3); 183 printf ("inexa=%d inexd=%d\n", inexa, inexd); 184 DISP("expected ", ref); DISP2(", got ", res); 185 exit (1); 186 } 187 } 188 } 189 } 190 191 mpfr_clear (ref); 192 mpfr_clear (op1); 193 mpfr_clear (op2); 194 mpfr_clear (op3); 195 mpfr_clear (res); 196 } 197 198 static void 199 test2ui (int (*testfunc)(mpfr_ptr, mpfr_srcptr, unsigned long int, mpfr_rnd_t), 200 const char *foo) 201 { 202 mpfr_t ref1, ref2; 203 unsigned int ref3; 204 mpfr_t res1; 205 mpfr_prec_t p1, p2; 206 int i, inexa, inexd; 207 mpfr_rnd_t r; 208 209 p1 = (randlimb () % 200) + MPFR_PREC_MIN; 210 p2 = (randlimb () % 200) + MPFR_PREC_MIN; 211 212 mpfr_init2 (ref1, p1); 213 mpfr_init2 (ref2, p2); 214 mpfr_init2 (res1, p1); 215 216 /* ref2 can be NaN, +Inf, -Inf, +0, -0 or any number 217 ref3 can be 0 or any number */ 218 for (i = 0; i < SPECIAL_MAX * 2; i++) 219 { 220 set_special (ref2, i % SPECIAL_MAX); 221 ref3 = i / SPECIAL_MAX == 0 ? 0 : randlimb (); 222 223 inexa = testfunc (res1, ref2, ref3, MPFR_RNDA); 224 r = MPFR_IS_POS (res1) ? MPFR_RNDU : MPFR_RNDD; 225 inexd = testfunc (ref1, ref2, ref3, r); 226 227 if (mpfr_compare (res1, ref1) || inexa != inexd) 228 { 229 printf ("Error with RNDA for %s for c=%u\n", foo, ref3); 230 DISP2("a=",ref2); 231 printf ("inexa=%d inexd=%d\n", inexa, inexd); 232 printf ("expected "); mpfr_dump (ref1); 233 printf ("got "); mpfr_dump (res1); 234 exit (1); 235 } 236 } 237 238 mpfr_clear (ref1); 239 mpfr_clear (ref2); 240 mpfr_clear (res1); 241 } 242 243 static void 244 testui2 (int (*testfunc)(mpfr_ptr, unsigned long int, mpfr_srcptr, mpfr_rnd_t), 245 const char *foo) 246 { 247 mpfr_t ref1, ref3; 248 unsigned int ref2; 249 mpfr_t res1; 250 mpfr_prec_t p1, p3; 251 int i, inexa, inexd; 252 mpfr_rnd_t r; 253 254 p1 = (randlimb () % 200) + MPFR_PREC_MIN; 255 p3 = (randlimb () % 200) + MPFR_PREC_MIN; 256 257 mpfr_init2 (ref1, p1); 258 mpfr_init2 (ref3, p3); 259 mpfr_init2 (res1, p1); 260 261 for (i = 0; i < SPECIAL_MAX * 2; i++) 262 { 263 set_special (ref3, i % SPECIAL_MAX); 264 ref2 = i / SPECIAL_MAX == 0 ? 0 : randlimb (); 265 266 inexa = testfunc (res1, ref2, ref3, MPFR_RNDA); 267 r = MPFR_IS_POS (res1) ? MPFR_RNDU : MPFR_RNDD; 268 inexd = testfunc (ref1, ref2, ref3, r); 269 270 if (mpfr_compare (res1, ref1) || inexa != inexd) 271 { 272 printf ("Error with RNDA for %s for b=%u\n", foo, ref2); 273 DISP2("a=", ref3); 274 printf ("inexa=%d inexd=%d\n", inexa, inexd); 275 DISP("expected ", ref1); DISP2(", got ", res1); 276 exit (1); 277 } 278 } 279 280 mpfr_clear (ref1); 281 mpfr_clear (ref3); 282 mpfr_clear (res1); 283 } 284 285 /* foo(mpfr_ptr, mpfr_srcptr, mp_rndt) */ 286 static void 287 test2 (int (*testfunc)(mpfr_ptr, mpfr_srcptr, mpfr_rnd_t), const char *foo) 288 { 289 mpfr_t ref1, ref2; 290 mpfr_t res1; 291 mpfr_prec_t p1, p2; 292 int i, inexa, inexd; 293 mpfr_rnd_t r; 294 295 p1 = (randlimb () % 200) + MPFR_PREC_MIN; 296 p2 = (randlimb () % 200) + MPFR_PREC_MIN; 297 298 mpfr_init2 (ref1, p1); 299 mpfr_init2 (ref2, p2); 300 mpfr_init2 (res1, p1); 301 302 for (i = 0; i < SPECIAL_MAX; i++) 303 { 304 set_special (ref2, i); 305 306 /* first round to away */ 307 inexa = testfunc (res1, ref2, MPFR_RNDA); 308 309 r = MPFR_IS_POS (res1) ? MPFR_RNDU : MPFR_RNDD; 310 inexd = testfunc (ref1, ref2, r); 311 if (mpfr_compare (res1, ref1) || inexa != inexd) 312 { 313 printf ("Error with RNDA for %s with ", foo); 314 DISP2("x=", ref2); 315 printf ("inexa=%d inexd=%d\n", inexa, inexd); 316 DISP("expected ", ref1); DISP2(", got ", res1); 317 exit (1); 318 } 319 } 320 321 mpfr_clear (ref1); 322 mpfr_clear (ref2); 323 mpfr_clear (res1); 324 } 325 326 /* one operand, two results, like mpfr_sin_cos */ 327 static void 328 test3a (int (*testfunc)(mpfr_ptr, mpfr_ptr, mpfr_srcptr, mpfr_rnd_t), 329 const char *foo) 330 { 331 mpfr_t ref1, ref2, ref3; 332 mpfr_t res1, res2; 333 mpfr_prec_t p1, p2, p3; 334 int i, inexa, inexd; 335 mpfr_rnd_t r; 336 337 p1 = (randlimb () % 200) + MPFR_PREC_MIN; 338 p2 = (randlimb () % 200) + MPFR_PREC_MIN; 339 p3 = (randlimb () % 200) + MPFR_PREC_MIN; 340 341 mpfr_init2 (ref1, p1); 342 mpfr_init2 (ref2, p2); 343 mpfr_init2 (ref3, p3); 344 mpfr_init2 (res1, p1); 345 mpfr_init2 (res2, p2); 346 347 for (i = 0; i < SPECIAL_MAX; i++) 348 { 349 set_special (ref3, i); 350 351 inexa = testfunc (res1, res2, ref3, MPFR_RNDA); 352 353 /* first check wrt the first operand */ 354 r = MPFR_IS_POS (res1) ? MPFR_RNDU : MPFR_RNDD; 355 inexd = testfunc (ref1, ref2, ref3, r); 356 /* the low 2 bits of the inexact flag concern the 1st operand */ 357 if (mpfr_compare (res1, ref1) || (inexa & 3) != (inexd & 3)) 358 { 359 printf ("Error with RNDA for %s (1st operand)\n", foo); 360 DISP2("a=",ref3); 361 DISP("expected ", ref1); printf ("\n"); 362 DISP("got ", res1); printf ("\n"); 363 printf ("inexa=%d inexd=%d\n", inexa & 3, inexd & 3); 364 exit (1); 365 } 366 367 /* now check wrt the second operand */ 368 r = MPFR_IS_POS (res2) ? MPFR_RNDU : MPFR_RNDD; 369 inexd = testfunc (ref1, ref2, ref3, r); 370 /* bits 2..3 of the inexact flag concern the 2nd operand */ 371 if (mpfr_compare (res2, ref2) || (inexa >> 2) != (inexd >> 2)) 372 { 373 printf ("Error with RNDA for %s (2nd operand)\n", foo); 374 DISP2("a=",ref3); 375 DISP("expected ", ref2); printf ("\n"); 376 DISP("got ", res2); printf ("\n"); 377 printf ("inexa=%d inexd=%d\n", inexa >> 2, inexd >> 2); 378 exit (1); 379 } 380 381 } 382 383 mpfr_clear (ref1); 384 mpfr_clear (ref2); 385 mpfr_clear (ref3); 386 mpfr_clear (res1); 387 mpfr_clear (res2); 388 } 389 390 int 391 main (void) 392 { 393 int N = 20; 394 395 tests_start_mpfr (); 396 397 while (N--) 398 { 399 /* no need to test mpfr_round, mpfr_ceil, mpfr_floor, mpfr_trunc since 400 they take no rounding mode */ 401 402 test2ui (mpfr_add_ui, "mpfr_add_ui"); 403 test2ui (mpfr_div_2exp, "mpfr_div_2exp"); 404 test2ui (mpfr_div_2ui, "mpfr_div_2ui"); 405 test2ui (mpfr_div_ui, "mpfr_div_ui"); 406 test2ui (mpfr_mul_2exp, "mpfr_mul_2exp"); 407 test2ui (mpfr_mul_2ui, "mpfr_mul_2ui"); 408 test2ui (mpfr_mul_ui, "mpfr_mul_ui"); 409 test2ui (mpfr_pow_ui, "mpfr_pow_ui"); 410 test2ui (mpfr_sub_ui, "mpfr_sub_ui"); 411 412 testui2 (mpfr_ui_div, "mpfr_ui_div"); 413 testui2 (mpfr_ui_sub, "mpfr_ui_sub"); 414 testui2 (mpfr_ui_pow, "mpfr_ui_pow"); 415 416 test2 (mpfr_sqr, "mpfr_sqr"); 417 test2 (mpfr_sqrt, "mpfr_sqrt"); 418 test2 (mpfr_abs, "mpfr_abs"); 419 test2 (mpfr_neg, "mpfr_neg"); 420 421 test2 (mpfr_log, "mpfr_log"); 422 test2 (mpfr_log2, "mpfr_log2"); 423 test2 (mpfr_log10, "mpfr_log10"); 424 test2 (mpfr_log1p, "mpfr_log1p"); 425 426 test2 (mpfr_exp, "mpfr_exp"); 427 test2 (mpfr_exp2, "mpfr_exp2"); 428 test2 (mpfr_exp10, "mpfr_exp10"); 429 test2 (mpfr_expm1, "mpfr_expm1"); 430 test2 (mpfr_eint, "mpfr_eint"); 431 432 test2 (mpfr_sinh, "mpfr_sinh"); 433 test2 (mpfr_cosh, "mpfr_cosh"); 434 test2 (mpfr_tanh, "mpfr_tanh"); 435 test2 (mpfr_asinh, "mpfr_asinh"); 436 test2 (mpfr_acosh, "mpfr_acosh"); 437 test2 (mpfr_atanh, "mpfr_atanh"); 438 test2 (mpfr_sech, "mpfr_sech"); 439 test2 (mpfr_csch, "mpfr_csch"); 440 test2 (mpfr_coth, "mpfr_coth"); 441 442 test2 (mpfr_asin, "mpfr_asin"); 443 test2 (mpfr_acos, "mpfr_acos"); 444 test2 (mpfr_atan, "mpfr_atan"); 445 test2 (mpfr_cos, "mpfr_cos"); 446 test2 (mpfr_sin, "mpfr_sin"); 447 test2 (mpfr_tan, "mpfr_tan"); 448 test2 (mpfr_sec, "mpfr_sec"); 449 test2 (mpfr_csc, "mpfr_csc"); 450 test2 (mpfr_cot, "mpfr_cot"); 451 452 test2 (mpfr_erf, "mpfr_erf"); 453 test2 (mpfr_erfc, "mpfr_erfc"); 454 test2 (mpfr_j0, "mpfr_j0"); 455 test2 (mpfr_j1, "mpfr_j1"); 456 test2 (mpfr_y0, "mpfr_y0"); 457 test2 (mpfr_y1, "mpfr_y1"); 458 test2 (mpfr_zeta, "mpfr_zeta"); 459 test2 (mpfr_gamma, "mpfr_gamma"); 460 test2 (mpfr_lngamma, "mpfr_lngamma"); 461 462 test2 (mpfr_rint, "mpfr_rint"); 463 test2 (mpfr_rint_ceil, "mpfr_rint_ceil"); 464 test2 (mpfr_rint_floor, "mpfr_rint_floor"); 465 test2 (mpfr_rint_round, "mpfr_rint_round"); 466 test2 (mpfr_rint_trunc, "mpfr_rint_trunc"); 467 test2 (mpfr_frac, "mpfr_frac"); 468 469 test3 (mpfr_add, "mpfr_add"); 470 test3 (mpfr_sub, "mpfr_sub"); 471 test3 (mpfr_mul, "mpfr_mul"); 472 test3 (mpfr_div, "mpfr_div"); 473 474 test3 (mpfr_agm, "mpfr_agm"); 475 test3 (mpfr_min, "mpfr_min"); 476 test3 (mpfr_max, "mpfr_max"); 477 478 /* we don't test reldiff since it does not guarantee correct rounding, 479 thus we can get different results with RNDA and RNDU or RNDD. */ 480 test3 (mpfr_dim, "mpfr_dim"); 481 482 test3 (mpfr_remainder, "mpfr_remainder"); 483 test3 (mpfr_pow, "mpfr_pow"); 484 test3 (mpfr_atan2, "mpfr_atan2"); 485 test3 (mpfr_hypot, "mpfr_hypot"); 486 487 test3a (mpfr_sin_cos, "mpfr_sin_cos"); 488 489 test4 (mpfr_fma, "mpfr_fma"); 490 test4 (mpfr_fms, "mpfr_fms"); 491 492 test2 (mpfr_li2, "mpfr_li2"); 493 test2 (mpfr_rec_sqrt, "mpfr_rec_sqrt"); 494 test3 (mpfr_fmod, "mpfr_fmod"); 495 test3a (mpfr_modf, "mpfr_modf"); 496 test3a (mpfr_sinh_cosh, "mpfr_sinh_cosh"); 497 498 #if MPFR_VERSION >= MPFR_VERSION_NUM(3,0,0) 499 test2 (mpfr_ai, "mpfr_ai"); 500 test2 (mpfr_digamma, "mpfr_digamma"); 501 #endif 502 } 503 504 tests_end_mpfr (); 505 return 0; 506 } 507