1 1.1 mrg /* Test file for mpfr_fma. 2 1.1 mrg 3 1.1.1.6 mrg Copyright 2001-2023 Free Software Foundation, Inc. 4 1.1.1.3 mrg Contributed by the AriC and Caramba projects, INRIA. 5 1.1 mrg 6 1.1 mrg This file is part of the GNU MPFR Library. 7 1.1 mrg 8 1.1 mrg The GNU MPFR Library is free software; you can redistribute it and/or modify 9 1.1 mrg it under the terms of the GNU Lesser General Public License as published by 10 1.1 mrg the Free Software Foundation; either version 3 of the License, or (at your 11 1.1 mrg option) any later version. 12 1.1 mrg 13 1.1 mrg The GNU MPFR Library is distributed in the hope that it will be useful, but 14 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15 1.1 mrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16 1.1 mrg License for more details. 17 1.1 mrg 18 1.1 mrg You should have received a copy of the GNU Lesser General Public License 19 1.1 mrg along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see 20 1.1.1.5 mrg https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., 21 1.1 mrg 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ 22 1.1 mrg 23 1.1 mrg #include "mpfr-test.h" 24 1.1 mrg 25 1.1 mrg /* When a * b is exact, the FMA is equivalent to the separate operations. */ 26 1.1 mrg static void 27 1.1 mrg test_exact (void) 28 1.1 mrg { 29 1.1.1.2 mrg const char *val[] = 30 1.1 mrg { "@NaN@", "-@Inf@", "-2", "-1", "-0", "0", "1", "2", "@Inf@" }; 31 1.1.1.4 mrg int sv = numberof (val); 32 1.1 mrg int i, j, k; 33 1.1 mrg int rnd; 34 1.1 mrg mpfr_t a, b, c, r1, r2; 35 1.1 mrg 36 1.1 mrg mpfr_inits2 (8, a, b, c, r1, r2, (mpfr_ptr) 0); 37 1.1 mrg 38 1.1 mrg for (i = 0; i < sv; i++) 39 1.1 mrg for (j = 0; j < sv; j++) 40 1.1 mrg for (k = 0; k < sv; k++) 41 1.1 mrg RND_LOOP (rnd) 42 1.1 mrg { 43 1.1 mrg if (mpfr_set_str (a, val[i], 10, MPFR_RNDN) || 44 1.1 mrg mpfr_set_str (b, val[j], 10, MPFR_RNDN) || 45 1.1 mrg mpfr_set_str (c, val[k], 10, MPFR_RNDN) || 46 1.1 mrg mpfr_mul (r1, a, b, (mpfr_rnd_t) rnd) || 47 1.1 mrg mpfr_add (r1, r1, c, (mpfr_rnd_t) rnd)) 48 1.1 mrg { 49 1.1.1.4 mrg if (rnd == MPFR_RNDF) 50 1.1.1.5 mrg continue; 51 1.1.1.4 mrg printf ("test_exact internal error for (%d,%d,%d,%d,%s)\n", 52 1.1.1.4 mrg i, j, k, rnd, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); 53 1.1 mrg exit (1); 54 1.1 mrg } 55 1.1 mrg if (mpfr_fma (r2, a, b, c, (mpfr_rnd_t) rnd)) 56 1.1 mrg { 57 1.1 mrg printf ("test_exact(%d,%d,%d,%d): mpfr_fma should be exact\n", 58 1.1 mrg i, j, k, rnd); 59 1.1 mrg exit (1); 60 1.1 mrg } 61 1.1 mrg if (MPFR_IS_NAN (r1)) 62 1.1 mrg { 63 1.1 mrg if (MPFR_IS_NAN (r2)) 64 1.1 mrg continue; 65 1.1 mrg printf ("test_exact(%d,%d,%d,%d): mpfr_fma should be NaN\n", 66 1.1 mrg i, j, k, rnd); 67 1.1 mrg exit (1); 68 1.1 mrg } 69 1.1.1.3 mrg if (! mpfr_equal_p (r1, r2) || MPFR_SIGN (r1) != MPFR_SIGN (r2)) 70 1.1 mrg { 71 1.1 mrg printf ("test_exact(%d,%d,%d,%d):\nexpected ", i, j, k, rnd); 72 1.1 mrg mpfr_out_str (stdout, 10, 0, r1, MPFR_RNDN); 73 1.1 mrg printf ("\n got "); 74 1.1 mrg mpfr_out_str (stdout, 10, 0, r2, MPFR_RNDN); 75 1.1 mrg printf ("\n"); 76 1.1 mrg exit (1); 77 1.1 mrg } 78 1.1 mrg } 79 1.1 mrg 80 1.1 mrg mpfr_clears (a, b, c, r1, r2, (mpfr_ptr) 0); 81 1.1 mrg } 82 1.1 mrg 83 1.1 mrg static void 84 1.1 mrg test_overflow1 (void) 85 1.1 mrg { 86 1.1 mrg mpfr_t x, y, z, r; 87 1.1 mrg int inex; 88 1.1 mrg 89 1.1 mrg mpfr_inits2 (8, x, y, z, r, (mpfr_ptr) 0); 90 1.1 mrg MPFR_SET_POS (x); 91 1.1 mrg mpfr_setmax (x, mpfr_get_emax ()); /* x = 2^emax - ulp */ 92 1.1 mrg mpfr_set_ui (y, 2, MPFR_RNDN); /* y = 2 */ 93 1.1 mrg mpfr_neg (z, x, MPFR_RNDN); /* z = -x = -(2^emax - ulp) */ 94 1.1 mrg mpfr_clear_flags (); 95 1.1 mrg /* The intermediate multiplication x * y overflows, but x * y + z = x 96 1.1 mrg is representable. */ 97 1.1 mrg inex = mpfr_fma (r, x, y, z, MPFR_RNDN); 98 1.1 mrg if (inex || ! mpfr_equal_p (r, x)) 99 1.1 mrg { 100 1.1 mrg printf ("Error in test_overflow1\nexpected "); 101 1.1 mrg mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN); 102 1.1 mrg printf (" with inex = 0\n got "); 103 1.1 mrg mpfr_out_str (stdout, 2, 0, r, MPFR_RNDN); 104 1.1 mrg printf (" with inex = %d\n", inex); 105 1.1 mrg exit (1); 106 1.1 mrg } 107 1.1 mrg if (mpfr_overflow_p ()) 108 1.1 mrg { 109 1.1 mrg printf ("Error in test_overflow1: overflow flag set\n"); 110 1.1 mrg exit (1); 111 1.1 mrg } 112 1.1 mrg mpfr_clears (x, y, z, r, (mpfr_ptr) 0); 113 1.1 mrg } 114 1.1 mrg 115 1.1 mrg static void 116 1.1 mrg test_overflow2 (void) 117 1.1 mrg { 118 1.1 mrg mpfr_t x, y, z, r; 119 1.1 mrg int i, inex, rnd, err = 0; 120 1.1 mrg 121 1.1 mrg mpfr_inits2 (8, x, y, z, r, (mpfr_ptr) 0); 122 1.1 mrg 123 1.1 mrg MPFR_SET_POS (x); 124 1.1 mrg mpfr_setmin (x, mpfr_get_emax ()); /* x = 0.1@emax */ 125 1.1 mrg mpfr_set_si (y, -2, MPFR_RNDN); /* y = -2 */ 126 1.1 mrg /* The intermediate multiplication x * y will overflow. */ 127 1.1 mrg 128 1.1 mrg for (i = -9; i <= 9; i++) 129 1.1.1.4 mrg RND_LOOP_NO_RNDF (rnd) 130 1.1 mrg { 131 1.1 mrg int inf, overflow; 132 1.1 mrg 133 1.1 mrg inf = rnd == MPFR_RNDN || rnd == MPFR_RNDD || rnd == MPFR_RNDA; 134 1.1 mrg overflow = inf || i <= 0; 135 1.1 mrg 136 1.1 mrg inex = mpfr_set_si_2exp (z, i, mpfr_get_emin (), MPFR_RNDN); 137 1.1 mrg MPFR_ASSERTN (inex == 0); 138 1.1 mrg 139 1.1 mrg mpfr_clear_flags (); 140 1.1 mrg /* One has: x * y = -1@emax exactly (but not representable). */ 141 1.1 mrg inex = mpfr_fma (r, x, y, z, (mpfr_rnd_t) rnd); 142 1.1 mrg if (overflow ^ (mpfr_overflow_p () != 0)) 143 1.1 mrg { 144 1.1 mrg printf ("Error in test_overflow2 (i = %d, %s): wrong overflow" 145 1.1 mrg " flag (should be %d)\n", i, 146 1.1 mrg mpfr_print_rnd_mode ((mpfr_rnd_t) rnd), overflow); 147 1.1 mrg err = 1; 148 1.1 mrg } 149 1.1 mrg if (mpfr_nanflag_p ()) 150 1.1 mrg { 151 1.1 mrg printf ("Error in test_overflow2 (i = %d, %s): NaN flag should" 152 1.1 mrg " not be set\n", i, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); 153 1.1 mrg err = 1; 154 1.1 mrg } 155 1.1 mrg if (mpfr_nan_p (r)) 156 1.1 mrg { 157 1.1 mrg printf ("Error in test_overflow2 (i = %d, %s): got NaN\n", 158 1.1 mrg i, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); 159 1.1 mrg err = 1; 160 1.1 mrg } 161 1.1.1.4 mrg else if (MPFR_IS_POS (r)) 162 1.1 mrg { 163 1.1 mrg printf ("Error in test_overflow2 (i = %d, %s): wrong sign " 164 1.1 mrg "(+ instead of -)\n", i, 165 1.1 mrg mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); 166 1.1 mrg err = 1; 167 1.1 mrg } 168 1.1 mrg else if (inf && ! mpfr_inf_p (r)) 169 1.1 mrg { 170 1.1 mrg printf ("Error in test_overflow2 (i = %d, %s): expected -Inf," 171 1.1 mrg " got\n", i, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); 172 1.1 mrg mpfr_dump (r); 173 1.1 mrg err = 1; 174 1.1 mrg } 175 1.1 mrg else if (!inf && (mpfr_inf_p (r) || 176 1.1 mrg (mpfr_nextbelow (r), ! mpfr_inf_p (r)))) 177 1.1 mrg { 178 1.1 mrg printf ("Error in test_overflow2 (i = %d, %s): expected -MAX," 179 1.1 mrg " got\n", i, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); 180 1.1 mrg mpfr_dump (r); 181 1.1 mrg err = 1; 182 1.1 mrg } 183 1.1 mrg if (inf ? inex >= 0 : inex <= 0) 184 1.1 mrg { 185 1.1 mrg printf ("Error in test_overflow2 (i = %d, %s): wrong inexact" 186 1.1 mrg " flag (got %d)\n", i, 187 1.1 mrg mpfr_print_rnd_mode ((mpfr_rnd_t) rnd), inex); 188 1.1 mrg err = 1; 189 1.1 mrg } 190 1.1 mrg 191 1.1 mrg } 192 1.1 mrg 193 1.1 mrg if (err) 194 1.1 mrg exit (1); 195 1.1 mrg mpfr_clears (x, y, z, r, (mpfr_ptr) 0); 196 1.1 mrg } 197 1.1 mrg 198 1.1 mrg static void 199 1.1.1.5 mrg test_overflow3 (void) 200 1.1.1.5 mrg { 201 1.1.1.5 mrg mpfr_t x, y, z, r; 202 1.1.1.5 mrg int inex; 203 1.1.1.5 mrg mpfr_prec_t p = 8; 204 1.1.1.5 mrg mpfr_flags_t ex_flags = MPFR_FLAGS_OVERFLOW | MPFR_FLAGS_INEXACT, flags; 205 1.1.1.5 mrg int i, j, k; 206 1.1.1.5 mrg unsigned int neg; 207 1.1.1.5 mrg 208 1.1.1.5 mrg mpfr_inits2 (p, x, y, z, (mpfr_ptr) 0); 209 1.1.1.5 mrg for (i = 0; i < 2; i++) 210 1.1.1.5 mrg { 211 1.1.1.5 mrg mpfr_init2 (r, 2 * p + i); 212 1.1.1.5 mrg mpfr_set_ui_2exp (x, 1, mpfr_get_emax () - 1, MPFR_RNDN); 213 1.1.1.5 mrg mpfr_set_ui (y, 2, MPFR_RNDN); /* y = 2 */ 214 1.1.1.5 mrg for (j = 1; j <= 2; j++) 215 1.1.1.5 mrg for (k = 0; k <= 1; k++) 216 1.1.1.5 mrg { 217 1.1.1.5 mrg mpfr_set_si_2exp (z, -1, mpfr_get_emax () - mpfr_get_prec (r) - j, 218 1.1.1.5 mrg MPFR_RNDN); 219 1.1.1.5 mrg if (k) 220 1.1.1.5 mrg mpfr_nextabove (z); 221 1.1.1.5 mrg for (neg = 0; neg <= 3; neg++) 222 1.1.1.5 mrg { 223 1.1.1.5 mrg mpfr_clear_flags (); 224 1.1.1.5 mrg /* (The following applies for neg = 0 or 2, all the signs 225 1.1.1.5 mrg need to be reversed for neg = 1 or 3.) 226 1.1.1.5 mrg We have x*y = 2^emax and 227 1.1.1.5 mrg z = - 2^(emax-2p-i-j) * (1-k*2^(-p)), thus 228 1.1.1.5 mrg x*y+z = 2^emax - 2^(emax-2p-i-j) + k*2^(emax-3p-i-j) 229 1.1.1.5 mrg should overflow. Indeed it is >= the midpoint of 230 1.1.1.5 mrg 2^emax - 2^(emax-2p-i) and 2^emax, the midpoint 231 1.1.1.5 mrg being obtained for j = 1 and k = 0. */ 232 1.1.1.5 mrg inex = mpfr_fma (r, x, y, z, MPFR_RNDN); 233 1.1.1.5 mrg flags = __gmpfr_flags; 234 1.1.1.5 mrg if (! mpfr_inf_p (r) || flags != ex_flags || 235 1.1.1.5 mrg ((neg & 1) == 0 ? 236 1.1.1.5 mrg (inex <= 0 || MPFR_IS_NEG (r)) : 237 1.1.1.5 mrg (inex >= 0 || MPFR_IS_POS (r)))) 238 1.1.1.5 mrg { 239 1.1.1.5 mrg printf ("Error in test_overflow3 for " 240 1.1.1.5 mrg "i=%d j=%d k=%d neg=%u\n", i, j, k, neg); 241 1.1.1.5 mrg printf ("Expected %c@Inf@\n with inex %c 0 and flags:", 242 1.1.1.5 mrg (neg & 1) == 0 ? '+' : '-', 243 1.1.1.5 mrg (neg & 1) == 0 ? '>' : '<'); 244 1.1.1.5 mrg flags_out (ex_flags); 245 1.1.1.5 mrg printf ("Got "); 246 1.1.1.5 mrg mpfr_dump (r); 247 1.1.1.5 mrg printf (" with inex = %d and flags:", inex); 248 1.1.1.5 mrg flags_out (flags); 249 1.1.1.5 mrg exit (1); 250 1.1.1.5 mrg } 251 1.1.1.5 mrg if (neg == 0 || neg == 2) 252 1.1.1.5 mrg mpfr_neg (x, x, MPFR_RNDN); 253 1.1.1.5 mrg if (neg == 1 || neg == 3) 254 1.1.1.5 mrg mpfr_neg (y, y, MPFR_RNDN); 255 1.1.1.5 mrg mpfr_neg (z, z, MPFR_RNDN); 256 1.1.1.5 mrg } /* neg */ 257 1.1.1.5 mrg } /* k */ 258 1.1.1.5 mrg mpfr_clear (r); 259 1.1.1.5 mrg } /* i */ 260 1.1.1.5 mrg mpfr_clears (x, y, z, (mpfr_ptr) 0); 261 1.1.1.5 mrg } 262 1.1.1.5 mrg 263 1.1.1.5 mrg static void 264 1.1.1.5 mrg test_overflow4 (void) 265 1.1.1.5 mrg { 266 1.1.1.5 mrg mpfr_t x, y, z, r1, r2; 267 1.1.1.5 mrg mpfr_exp_t emax, e; 268 1.1.1.5 mrg mpfr_prec_t px; 269 1.1.1.5 mrg mpfr_flags_t flags1, flags2; 270 1.1.1.5 mrg int inex1, inex2; 271 1.1.1.5 mrg int ei, i, j; 272 1.1.1.5 mrg int below; 273 1.1.1.5 mrg unsigned int neg; 274 1.1.1.5 mrg 275 1.1.1.5 mrg emax = mpfr_get_emax (); 276 1.1.1.5 mrg 277 1.1.1.5 mrg mpfr_init2 (y, MPFR_PREC_MIN); 278 1.1.1.5 mrg mpfr_set_ui (y, 2, MPFR_RNDN); /* y = 2 */ 279 1.1.1.5 mrg 280 1.1.1.5 mrg mpfr_init2 (z, 8); 281 1.1.1.5 mrg 282 1.1.1.5 mrg for (px = 17; px < 256; px *= 2) 283 1.1.1.5 mrg { 284 1.1.1.5 mrg mpfr_init2 (x, px); 285 1.1.1.5 mrg mpfr_inits2 (px - 8, r1, r2, (mpfr_ptr) 0); 286 1.1.1.5 mrg for (ei = 0; ei <= 1; ei++) 287 1.1.1.5 mrg { 288 1.1.1.5 mrg e = ei ? emax : 0; 289 1.1.1.5 mrg mpfr_set_ui_2exp (x, 1, e - 1, MPFR_RNDN); 290 1.1.1.5 mrg mpfr_nextabove (x); /* x = 2^(e - 1) + 2^(e - px) */ 291 1.1.1.5 mrg /* x*y = 2^e + 2^(e - px + 1), which internally overflows 292 1.1.1.5 mrg when e = emax. */ 293 1.1.1.5 mrg for (i = -4; i <= 4; i++) 294 1.1.1.5 mrg for (j = 2; j <= 3; j++) 295 1.1.1.5 mrg { 296 1.1.1.5 mrg mpfr_set_si_2exp (z, -j, e - px + i, MPFR_RNDN); 297 1.1.1.5 mrg /* If |z| <= 2^(e - px + 1), then x*y + z >= 2^e and 298 1.1.1.5 mrg RZ(x*y + z) = 2^e with an unbounded exponent range. 299 1.1.1.5 mrg If |z| > 2^(e - px + 1), then RZ(x*y + z) is the 300 1.1.1.5 mrg predecessor of 2^e (since |z| < ulp(r)/2); this 301 1.1.1.5 mrg occurs when i > 0 and when i = 0 and j > 2 */ 302 1.1.1.5 mrg mpfr_set_ui_2exp (r1, 1, e - 1, MPFR_RNDN); 303 1.1.1.5 mrg below = i > 0 || (i == 0 && j > 2); 304 1.1.1.5 mrg if (below) 305 1.1.1.5 mrg mpfr_nextbelow (r1); 306 1.1.1.5 mrg mpfr_clear_flags (); 307 1.1.1.5 mrg inex1 = mpfr_mul_2ui (r1, r1, 1, MPFR_RNDZ); 308 1.1.1.5 mrg if (below || e < emax) 309 1.1.1.5 mrg { 310 1.1.1.5 mrg inex1 = i == 0 && j == 2 ? 0 : -1; 311 1.1.1.5 mrg flags1 = inex1 ? MPFR_FLAGS_INEXACT : 0; 312 1.1.1.5 mrg } 313 1.1.1.5 mrg else 314 1.1.1.5 mrg { 315 1.1.1.5 mrg MPFR_ASSERTN (inex1 < 0); 316 1.1.1.5 mrg flags1 = MPFR_FLAGS_INEXACT | MPFR_FLAGS_OVERFLOW; 317 1.1.1.5 mrg MPFR_ASSERTN (flags1 == __gmpfr_flags); 318 1.1.1.5 mrg } 319 1.1.1.5 mrg for (neg = 0; neg <= 3; neg++) 320 1.1.1.5 mrg { 321 1.1.1.5 mrg mpfr_clear_flags (); 322 1.1.1.5 mrg inex2 = mpfr_fma (r2, x, y, z, MPFR_RNDZ); 323 1.1.1.5 mrg flags2 = __gmpfr_flags; 324 1.1.1.5 mrg if (! (mpfr_equal_p (r1, r2) && 325 1.1.1.5 mrg SAME_SIGN (inex1, inex2) && 326 1.1.1.5 mrg flags1 == flags2)) 327 1.1.1.5 mrg { 328 1.1.1.5 mrg printf ("Error in test_overflow4 for " 329 1.1.1.5 mrg "px=%d ei=%d i=%d j=%d neg=%u\n", 330 1.1.1.5 mrg (int) px, ei, i, j, neg); 331 1.1.1.5 mrg printf ("Expected "); 332 1.1.1.5 mrg mpfr_dump (r1); 333 1.1.1.5 mrg printf ("with inex = %d and flags:", inex1); 334 1.1.1.5 mrg flags_out (flags1); 335 1.1.1.5 mrg printf ("Got "); 336 1.1.1.5 mrg mpfr_dump (r2); 337 1.1.1.5 mrg printf ("with inex = %d and flags:", inex2); 338 1.1.1.5 mrg flags_out (flags2); 339 1.1.1.5 mrg exit (1); 340 1.1.1.5 mrg } 341 1.1.1.5 mrg if (neg == 0 || neg == 2) 342 1.1.1.5 mrg mpfr_neg (x, x, MPFR_RNDN); 343 1.1.1.5 mrg if (neg == 1 || neg == 3) 344 1.1.1.5 mrg mpfr_neg (y, y, MPFR_RNDN); 345 1.1.1.5 mrg mpfr_neg (z, z, MPFR_RNDN); 346 1.1.1.5 mrg mpfr_neg (r1, r1, MPFR_RNDN); 347 1.1.1.5 mrg inex1 = - inex1; 348 1.1.1.5 mrg } 349 1.1.1.5 mrg } 350 1.1.1.5 mrg } 351 1.1.1.5 mrg mpfr_clears (x, r1, r2, (mpfr_ptr) 0); 352 1.1.1.5 mrg } 353 1.1.1.5 mrg 354 1.1.1.5 mrg mpfr_clears (y, z, (mpfr_ptr) 0); 355 1.1.1.5 mrg } 356 1.1.1.5 mrg 357 1.1.1.5 mrg static void 358 1.1.1.5 mrg test_overflow5 (void) 359 1.1.1.5 mrg { 360 1.1.1.5 mrg mpfr_t x, y, z, r1, r2; 361 1.1.1.5 mrg mpfr_exp_t emax; 362 1.1.1.5 mrg int inex1, inex2; 363 1.1.1.5 mrg int i, rnd; 364 1.1.1.5 mrg unsigned int neg, negr; 365 1.1.1.5 mrg 366 1.1.1.5 mrg emax = mpfr_get_emax (); 367 1.1.1.5 mrg 368 1.1.1.5 mrg mpfr_init2 (x, 123); 369 1.1.1.5 mrg mpfr_init2 (y, 45); 370 1.1.1.5 mrg mpfr_init2 (z, 67); 371 1.1.1.5 mrg mpfr_inits2 (89, r1, r2, (mpfr_ptr) 0); 372 1.1.1.5 mrg 373 1.1.1.5 mrg mpfr_set_ui_2exp (x, 1, emax - 1, MPFR_RNDN); 374 1.1.1.5 mrg 375 1.1.1.5 mrg for (i = 3; i <= 17; i++) 376 1.1.1.5 mrg { 377 1.1.1.5 mrg mpfr_set_ui (y, i, MPFR_RNDN); 378 1.1.1.5 mrg mpfr_set_ui_2exp (z, 1, emax - 1, MPFR_RNDN); 379 1.1.1.5 mrg for (neg = 0; neg < 8; neg++) 380 1.1.1.5 mrg { 381 1.1.1.5 mrg mpfr_setsign (x, x, neg & 1, MPFR_RNDN); 382 1.1.1.5 mrg mpfr_setsign (y, y, neg & 2, MPFR_RNDN); 383 1.1.1.5 mrg mpfr_setsign (z, z, neg & 4, MPFR_RNDN); 384 1.1.1.5 mrg 385 1.1.1.5 mrg /* |x*y + z| = (i +/- 1) * 2^(emax - 1) >= 2^emax (overflow) 386 1.1.1.5 mrg and x*y + z has the same sign as x*y. */ 387 1.1.1.5 mrg negr = (neg ^ (neg >> 1)) & 1; 388 1.1.1.5 mrg 389 1.1.1.5 mrg RND_LOOP (rnd) 390 1.1.1.5 mrg { 391 1.1.1.5 mrg mpfr_set_inf (r1, 1); 392 1.1.1.5 mrg if (MPFR_IS_LIKE_RNDZ ((mpfr_rnd_t) rnd, negr)) 393 1.1.1.5 mrg { 394 1.1.1.5 mrg mpfr_nextbelow (r1); 395 1.1.1.5 mrg inex1 = -1; 396 1.1.1.5 mrg } 397 1.1.1.5 mrg else 398 1.1.1.5 mrg inex1 = 1; 399 1.1.1.5 mrg 400 1.1.1.5 mrg if (negr) 401 1.1.1.5 mrg { 402 1.1.1.5 mrg mpfr_neg (r1, r1, MPFR_RNDN); 403 1.1.1.5 mrg inex1 = - inex1; 404 1.1.1.5 mrg } 405 1.1.1.5 mrg 406 1.1.1.5 mrg mpfr_clear_flags (); 407 1.1.1.5 mrg inex2 = mpfr_fma (r2, x, y, z, (mpfr_rnd_t) rnd); 408 1.1.1.5 mrg MPFR_ASSERTN (__gmpfr_flags == 409 1.1.1.5 mrg (MPFR_FLAGS_INEXACT | MPFR_FLAGS_OVERFLOW)); 410 1.1.1.5 mrg 411 1.1.1.5 mrg if (! (mpfr_equal_p (r1, r2) && SAME_SIGN (inex1, inex2))) 412 1.1.1.5 mrg { 413 1.1.1.5 mrg printf ("Error in test_overflow5 for i=%d neg=%u %s\n", 414 1.1.1.5 mrg i, neg, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); 415 1.1.1.5 mrg printf ("Expected "); 416 1.1.1.5 mrg mpfr_dump (r1); 417 1.1.1.5 mrg printf ("with inex = %d\n", inex1); 418 1.1.1.5 mrg printf ("Got "); 419 1.1.1.5 mrg mpfr_dump (r2); 420 1.1.1.5 mrg printf ("with inex = %d\n", inex2); 421 1.1.1.5 mrg exit (1); 422 1.1.1.5 mrg } 423 1.1.1.5 mrg } /* rnd */ 424 1.1.1.5 mrg } /* neg */ 425 1.1.1.5 mrg } /* i */ 426 1.1.1.5 mrg 427 1.1.1.5 mrg mpfr_clears (x, y, z, r1, r2, (mpfr_ptr) 0); 428 1.1.1.5 mrg } 429 1.1.1.5 mrg 430 1.1.1.5 mrg static void 431 1.1 mrg test_underflow1 (void) 432 1.1 mrg { 433 1.1 mrg mpfr_t x, y, z, r; 434 1.1 mrg int inex, signy, signz, rnd, err = 0; 435 1.1 mrg 436 1.1 mrg mpfr_inits2 (8, x, y, z, r, (mpfr_ptr) 0); 437 1.1 mrg 438 1.1 mrg MPFR_SET_POS (x); 439 1.1 mrg mpfr_setmin (x, mpfr_get_emin ()); /* x = 0.1@emin */ 440 1.1 mrg 441 1.1 mrg for (signy = -1; signy <= 1; signy += 2) 442 1.1 mrg { 443 1.1 mrg mpfr_set_si_2exp (y, signy, -1, MPFR_RNDN); /* |y| = 1/2 */ 444 1.1 mrg for (signz = -3; signz <= 3; signz += 2) 445 1.1 mrg { 446 1.1 mrg RND_LOOP (rnd) 447 1.1 mrg { 448 1.1 mrg mpfr_set_si (z, signz, MPFR_RNDN); 449 1.1 mrg if (ABS (signz) != 1) 450 1.1 mrg mpfr_setmax (z, mpfr_get_emax ()); 451 1.1 mrg /* |z| = 1 or 2^emax - ulp */ 452 1.1 mrg mpfr_clear_flags (); 453 1.1 mrg inex = mpfr_fma (r, x, y, z, (mpfr_rnd_t) rnd); 454 1.1.1.4 mrg #define STRTU1 "Error in test_underflow1 (signy = %d, signz = %d, %s)\n " 455 1.1 mrg if (mpfr_nanflag_p ()) 456 1.1 mrg { 457 1.1.1.4 mrg printf (STRTU1 "NaN flag is set\n", signy, signz, 458 1.1 mrg mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); 459 1.1 mrg err = 1; 460 1.1 mrg } 461 1.1 mrg if (signy < 0 && MPFR_IS_LIKE_RNDD(rnd, signz)) 462 1.1 mrg mpfr_nextbelow (z); 463 1.1 mrg if (signy > 0 && MPFR_IS_LIKE_RNDU(rnd, signz)) 464 1.1 mrg mpfr_nextabove (z); 465 1.1 mrg if ((mpfr_overflow_p () != 0) ^ (mpfr_inf_p (z) != 0)) 466 1.1 mrg { 467 1.1.1.4 mrg printf (STRTU1 "wrong overflow flag\n", signy, signz, 468 1.1 mrg mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); 469 1.1 mrg err = 1; 470 1.1 mrg } 471 1.1 mrg if (mpfr_underflow_p ()) 472 1.1 mrg { 473 1.1.1.4 mrg printf (STRTU1 "underflow flag is set\n", signy, signz, 474 1.1 mrg mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); 475 1.1 mrg err = 1; 476 1.1 mrg } 477 1.1 mrg if (! mpfr_equal_p (r, z)) 478 1.1 mrg { 479 1.1.1.4 mrg printf (STRTU1 "got ", signy, signz, 480 1.1 mrg mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); 481 1.1.1.4 mrg mpfr_dump (r); 482 1.1.1.4 mrg printf (" instead of "); 483 1.1.1.4 mrg mpfr_dump (z); 484 1.1 mrg err = 1; 485 1.1 mrg } 486 1.1 mrg if (inex >= 0 && (rnd == MPFR_RNDD || 487 1.1 mrg (rnd == MPFR_RNDZ && signz > 0) || 488 1.1 mrg (rnd == MPFR_RNDN && signy > 0))) 489 1.1 mrg { 490 1.1.1.4 mrg printf (STRTU1 "ternary value = %d instead of < 0\n", 491 1.1 mrg signy, signz, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd), 492 1.1 mrg inex); 493 1.1 mrg err = 1; 494 1.1 mrg } 495 1.1 mrg if (inex <= 0 && (rnd == MPFR_RNDU || 496 1.1 mrg (rnd == MPFR_RNDZ && signz < 0) || 497 1.1 mrg (rnd == MPFR_RNDN && signy < 0))) 498 1.1 mrg { 499 1.1.1.4 mrg printf (STRTU1 "ternary value = %d instead of > 0\n", 500 1.1 mrg signy, signz, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd), 501 1.1 mrg inex); 502 1.1 mrg err = 1; 503 1.1 mrg } 504 1.1 mrg } 505 1.1 mrg } 506 1.1 mrg } 507 1.1 mrg 508 1.1 mrg if (err) 509 1.1 mrg exit (1); 510 1.1 mrg mpfr_clears (x, y, z, r, (mpfr_ptr) 0); 511 1.1 mrg } 512 1.1 mrg 513 1.1 mrg static void 514 1.1 mrg test_underflow2 (void) 515 1.1 mrg { 516 1.1.1.5 mrg mpfr_t x, y, z, r1, r2; 517 1.1.1.5 mrg int e, b, i, prec = 32, pz, inex; 518 1.1.1.5 mrg unsigned int neg; 519 1.1 mrg 520 1.1.1.5 mrg mpfr_init2 (x, MPFR_PREC_MIN); 521 1.1.1.5 mrg mpfr_inits2 (prec, y, z, r1, r2, (mpfr_ptr) 0); 522 1.1 mrg 523 1.1.1.5 mrg mpfr_set_si_2exp (x, 1, mpfr_get_emin () - 1, MPFR_RNDN); 524 1.1.1.5 mrg /* x = 2^(emin-1) */ 525 1.1 mrg 526 1.1.1.5 mrg for (e = -1; e <= prec + 2; e++) 527 1.1 mrg { 528 1.1.1.5 mrg mpfr_set (z, x, MPFR_RNDN); 529 1.1.1.5 mrg /* z = x = 2^(emin+e) */ 530 1.1.1.5 mrg for (b = 0; b <= 1; b++) 531 1.1 mrg { 532 1.1.1.5 mrg for (pz = prec - 4 * (b == 0); pz <= prec + 4; pz++) 533 1.1 mrg { 534 1.1.1.5 mrg inex = mpfr_prec_round (z, pz, MPFR_RNDZ); 535 1.1.1.5 mrg MPFR_ASSERTN (inex == 0); 536 1.1.1.5 mrg for (i = 15; i <= 17; i++) 537 1.1.1.5 mrg { 538 1.1.1.5 mrg mpfr_flags_t flags1, flags2; 539 1.1.1.5 mrg int inex1, inex2; 540 1.1 mrg 541 1.1.1.5 mrg mpfr_set_si_2exp (y, i, -4 - prec, MPFR_RNDN); 542 1.1.1.5 mrg 543 1.1.1.5 mrg /* <--- r ---> 544 1.1.1.5 mrg * z = 1.000...00b with b = 0 or 1 545 1.1.1.5 mrg * xy = 01111 (i = 15) 546 1.1.1.5 mrg * or 10000 (i = 16) 547 1.1.1.5 mrg * or 10001 (i = 17) 548 1.1.1.5 mrg * 549 1.1.1.5 mrg * x, y, and z will be modified to test the different sign 550 1.1.1.5 mrg * combinations. In the case b = 0 (i.e. |z| is a power of 551 1.1.1.5 mrg * 2) and x*y has a different sign from z, then y will be 552 1.1.1.5 mrg * divided by 2, so that i = 16 corresponds to a midpoint. 553 1.1.1.5 mrg */ 554 1.1.1.5 mrg 555 1.1.1.5 mrg for (neg = 0; neg < 8; neg++) 556 1.1.1.5 mrg { 557 1.1.1.5 mrg int xyneg, prev_binade; 558 1.1.1.5 mrg 559 1.1.1.5 mrg mpfr_setsign (x, x, neg & 1, MPFR_RNDN); 560 1.1.1.5 mrg mpfr_setsign (y, y, neg & 2, MPFR_RNDN); 561 1.1.1.5 mrg mpfr_setsign (z, z, neg & 4, MPFR_RNDN); 562 1.1.1.5 mrg 563 1.1.1.5 mrg xyneg = (neg ^ (neg >> 1)) & 1; /* true iff x*y < 0 */ 564 1.1.1.5 mrg 565 1.1.1.5 mrg /* If a change of binade occurs by adding x*y to z 566 1.1.1.5 mrg exactly, then take into account the fact that the 567 1.1.1.5 mrg midpoint has a different exponent. */ 568 1.1.1.5 mrg prev_binade = b == 0 && (xyneg ^ MPFR_IS_NEG (z)); 569 1.1.1.5 mrg if (prev_binade) 570 1.1.1.5 mrg mpfr_div_2ui (y, y, 1, MPFR_RNDN); 571 1.1.1.5 mrg 572 1.1.1.5 mrg mpfr_set (r1, z, MPFR_RNDN); 573 1.1.1.5 mrg flags1 = MPFR_FLAGS_INEXACT; 574 1.1.1.5 mrg 575 1.1.1.5 mrg if (e == -1 && i == 17 && b == 0 && 576 1.1.1.5 mrg (xyneg ^ (neg >> 2)) != 0) 577 1.1.1.5 mrg { 578 1.1.1.5 mrg /* Special underflow case. */ 579 1.1.1.5 mrg flags1 |= MPFR_FLAGS_UNDERFLOW; 580 1.1.1.5 mrg inex1 = xyneg ? 1 : -1; 581 1.1.1.5 mrg } 582 1.1.1.5 mrg else if (i == 15 || (i == 16 && b == 0)) 583 1.1.1.5 mrg { 584 1.1.1.5 mrg /* round toward z */ 585 1.1.1.5 mrg inex1 = xyneg ? 1 : -1; 586 1.1.1.5 mrg } 587 1.1.1.5 mrg else if (xyneg) 588 1.1.1.5 mrg { 589 1.1.1.5 mrg /* round away from z, with x*y < 0 */ 590 1.1.1.5 mrg mpfr_nextbelow (r1); 591 1.1.1.5 mrg inex1 = -1; 592 1.1.1.5 mrg } 593 1.1.1.5 mrg else 594 1.1.1.5 mrg { 595 1.1.1.5 mrg /* round away from z, with x*y > 0 */ 596 1.1.1.5 mrg mpfr_nextabove (r1); 597 1.1.1.5 mrg inex1 = 1; 598 1.1.1.5 mrg } 599 1.1.1.5 mrg 600 1.1.1.5 mrg mpfr_clear_flags (); 601 1.1.1.5 mrg inex2 = mpfr_fma (r2, x, y, z, MPFR_RNDN); 602 1.1.1.5 mrg flags2 = __gmpfr_flags; 603 1.1.1.5 mrg 604 1.1.1.5 mrg if (! (mpfr_equal_p (r1, r2) && 605 1.1.1.5 mrg SAME_SIGN (inex1, inex2) && 606 1.1.1.5 mrg flags1 == flags2)) 607 1.1.1.5 mrg { 608 1.1.1.5 mrg printf ("Error in test_underflow2 for " 609 1.1.1.5 mrg "e=%d b=%d pz=%d i=%d neg=%u\n", 610 1.1.1.5 mrg e, b, pz, i, neg); 611 1.1.1.5 mrg printf ("Expected "); 612 1.1.1.5 mrg mpfr_dump (r1); 613 1.1.1.5 mrg printf ("with inex = %d and flags:", inex1); 614 1.1.1.5 mrg flags_out (flags1); 615 1.1.1.5 mrg printf ("Got "); 616 1.1.1.5 mrg mpfr_dump (r2); 617 1.1.1.5 mrg printf ("with inex = %d and flags:", inex2); 618 1.1.1.5 mrg flags_out (flags2); 619 1.1.1.5 mrg exit (1); 620 1.1.1.5 mrg } 621 1.1.1.5 mrg 622 1.1.1.5 mrg /* Restore y. */ 623 1.1.1.5 mrg if (prev_binade) 624 1.1.1.5 mrg mpfr_mul_2ui (y, y, 1, MPFR_RNDN); 625 1.1.1.5 mrg } /* neg */ 626 1.1.1.5 mrg } /* i */ 627 1.1.1.5 mrg } /* pz */ 628 1.1.1.5 mrg 629 1.1.1.5 mrg inex = mpfr_prec_round (z, prec, MPFR_RNDZ); 630 1.1.1.5 mrg MPFR_ASSERTN (inex == 0); 631 1.1.1.5 mrg MPFR_SET_POS (z); 632 1.1.1.5 mrg mpfr_nextabove (z); 633 1.1.1.5 mrg } /* b */ 634 1.1.1.5 mrg mpfr_mul_2ui (x, x, 1, MPFR_RNDN); 635 1.1.1.5 mrg } /* e */ 636 1.1.1.5 mrg 637 1.1.1.5 mrg mpfr_clears (x, y, z, r1, r2, (mpfr_ptr) 0); 638 1.1 mrg } 639 1.1 mrg 640 1.1 mrg static void 641 1.1.1.3 mrg test_underflow3 (int n) 642 1.1.1.3 mrg { 643 1.1.1.3 mrg mpfr_t x, y, z, t1, t2; 644 1.1.1.3 mrg int sign, k, s, rnd, inex1, inex2; 645 1.1.1.3 mrg mpfr_exp_t e; 646 1.1.1.4 mrg mpfr_flags_t flags1, flags2; 647 1.1.1.3 mrg 648 1.1.1.3 mrg mpfr_inits2 (4, x, z, t1, t2, (mpfr_ptr) 0); 649 1.1.1.3 mrg mpfr_init2 (y, 6); 650 1.1.1.3 mrg 651 1.1.1.3 mrg e = mpfr_get_emin () - 1; 652 1.1.1.3 mrg 653 1.1.1.3 mrg for (sign = 1; sign >= -1; sign -= 2) 654 1.1.1.3 mrg for (k = 1; k <= 7; k++) 655 1.1.1.3 mrg for (s = -1; s <= 1; s++) 656 1.1.1.3 mrg { 657 1.1.1.3 mrg mpfr_set_si_2exp (x, sign, e, MPFR_RNDN); 658 1.1.1.3 mrg mpfr_set_si_2exp (y, 8*k+s, -6, MPFR_RNDN); 659 1.1.1.3 mrg mpfr_neg (z, x, MPFR_RNDN); 660 1.1.1.3 mrg /* x = sign * 2^(emin-1) 661 1.1.1.3 mrg y = (8 * k + s) * 2^(-6) = k / 8 + s * 2^(-6) 662 1.1.1.3 mrg z = -x = -sign * 2^(emin-1) 663 1.1.1.3 mrg FMA(x,y,z) = sign * ((k-8) * 2^(emin-4) + s * 2^(emin-7)) exactly. 664 1.1.1.3 mrg Note: The purpose of the s * 2^(emin-7) term is to yield 665 1.1.1.3 mrg double rounding when scaling for k = 4, s != 0, MPFR_RNDN. */ 666 1.1.1.3 mrg 667 1.1.1.5 mrg RND_LOOP_NO_RNDF (rnd) 668 1.1.1.3 mrg { 669 1.1.1.3 mrg mpfr_clear_flags (); 670 1.1.1.3 mrg inex1 = mpfr_set_si_2exp (t1, sign * (8*k+s-64), e-6, 671 1.1.1.3 mrg (mpfr_rnd_t) rnd); 672 1.1.1.3 mrg flags1 = __gmpfr_flags; 673 1.1.1.3 mrg 674 1.1.1.3 mrg mpfr_clear_flags (); 675 1.1.1.3 mrg inex2 = mpfr_fma (t2, x, y, z, (mpfr_rnd_t) rnd); 676 1.1.1.3 mrg flags2 = __gmpfr_flags; 677 1.1.1.3 mrg 678 1.1.1.3 mrg if (! (mpfr_equal_p (t1, t2) && 679 1.1.1.3 mrg SAME_SIGN (inex1, inex2) && 680 1.1.1.3 mrg flags1 == flags2)) 681 1.1.1.3 mrg { 682 1.1.1.3 mrg printf ("Error in test_underflow3, n = %d, sign = %d," 683 1.1.1.3 mrg " k = %d, s = %d, %s\n", n, sign, k, s, 684 1.1.1.3 mrg mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); 685 1.1.1.3 mrg printf ("Expected "); 686 1.1.1.3 mrg mpfr_dump (t1); 687 1.1.1.3 mrg printf (" with inex ~ %d, flags =", inex1); 688 1.1.1.3 mrg flags_out (flags1); 689 1.1.1.3 mrg printf ("Got "); 690 1.1.1.3 mrg mpfr_dump (t2); 691 1.1.1.3 mrg printf (" with inex ~ %d, flags =", inex2); 692 1.1.1.3 mrg flags_out (flags2); 693 1.1.1.3 mrg exit (1); 694 1.1.1.3 mrg } 695 1.1.1.3 mrg } 696 1.1.1.3 mrg } 697 1.1.1.3 mrg 698 1.1.1.3 mrg mpfr_clears (x, y, z, t1, t2, (mpfr_ptr) 0); 699 1.1.1.3 mrg } 700 1.1.1.3 mrg 701 1.1.1.5 mrg /* Test s = x*y + z with PREC(z) > PREC(s) + 1, x*y underflows, where 702 1.1.1.5 mrg z + x*y and z + sign(x*y) * 2^(emin-1) do not give the same result. 703 1.1.1.5 mrg x = 2^emin 704 1.1.1.5 mrg y = 2^(-8) 705 1.1.1.5 mrg z = 2^emin * (2^PREC(s) + k - 2^(-1)) 706 1.1.1.5 mrg with k = 3 for MPFR_RNDN and k = 2 for the directed rounding modes. 707 1.1.1.5 mrg Also test the opposite versions with neg != 0. 708 1.1.1.5 mrg */ 709 1.1.1.5 mrg static void 710 1.1.1.5 mrg test_underflow4 (void) 711 1.1.1.5 mrg { 712 1.1.1.5 mrg mpfr_t x, y, z, s1, s2; 713 1.1.1.5 mrg mpfr_prec_t ps = 32; 714 1.1.1.5 mrg int inex, rnd; 715 1.1.1.5 mrg 716 1.1.1.5 mrg mpfr_inits2 (MPFR_PREC_MIN, x, y, (mpfr_ptr) 0); 717 1.1.1.5 mrg mpfr_inits2 (ps, s1, s2, (mpfr_ptr) 0); 718 1.1.1.5 mrg mpfr_init2 (z, ps + 2); 719 1.1.1.5 mrg 720 1.1.1.5 mrg inex = mpfr_set_si_2exp (x, 1, mpfr_get_emin (), MPFR_RNDN); 721 1.1.1.5 mrg MPFR_ASSERTN (inex == 0); 722 1.1.1.5 mrg inex = mpfr_set_si_2exp (y, 1, -8, MPFR_RNDN); 723 1.1.1.5 mrg MPFR_ASSERTN (inex == 0); 724 1.1.1.5 mrg 725 1.1.1.5 mrg RND_LOOP_NO_RNDF (rnd) 726 1.1.1.5 mrg { 727 1.1.1.5 mrg mpfr_flags_t flags1, flags2; 728 1.1.1.5 mrg int inex1, inex2; 729 1.1.1.5 mrg unsigned int neg; 730 1.1.1.5 mrg 731 1.1.1.5 mrg inex = mpfr_set_si_2exp (z, 1 << 1, ps, MPFR_RNDN); 732 1.1.1.5 mrg MPFR_ASSERTN (inex == 0); 733 1.1.1.5 mrg inex = mpfr_sub_ui (z, z, 1, MPFR_RNDN); 734 1.1.1.5 mrg MPFR_ASSERTN (inex == 0); 735 1.1.1.5 mrg inex = mpfr_div_2ui (z, z, 1, MPFR_RNDN); 736 1.1.1.5 mrg MPFR_ASSERTN (inex == 0); 737 1.1.1.5 mrg inex = mpfr_add_ui (z, z, rnd == MPFR_RNDN ? 3 : 2, MPFR_RNDN); 738 1.1.1.5 mrg MPFR_ASSERTN (inex == 0); 739 1.1.1.5 mrg inex = mpfr_mul (z, z, x, MPFR_RNDN); 740 1.1.1.5 mrg MPFR_ASSERTN (inex == 0); 741 1.1.1.5 mrg 742 1.1.1.5 mrg for (neg = 0; neg <= 3; neg++) 743 1.1.1.5 mrg { 744 1.1.1.5 mrg inex1 = mpfr_set (s1, z, (mpfr_rnd_t) rnd); 745 1.1.1.5 mrg flags1 = MPFR_FLAGS_INEXACT; 746 1.1.1.5 mrg 747 1.1.1.5 mrg mpfr_clear_flags (); 748 1.1.1.5 mrg inex2 = mpfr_fma (s2, x, y, z, (mpfr_rnd_t) rnd); 749 1.1.1.5 mrg flags2 = __gmpfr_flags; 750 1.1.1.5 mrg 751 1.1.1.5 mrg if (! (mpfr_equal_p (s1, s2) && 752 1.1.1.5 mrg SAME_SIGN (inex1, inex2) && 753 1.1.1.5 mrg flags1 == flags2)) 754 1.1.1.5 mrg { 755 1.1.1.5 mrg printf ("Error in test_underflow4 for neg=%u %s\n", 756 1.1.1.5 mrg neg, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); 757 1.1.1.5 mrg printf ("Expected "); 758 1.1.1.5 mrg mpfr_dump (s1); 759 1.1.1.5 mrg printf (" with inex ~ %d, flags =", inex1); 760 1.1.1.5 mrg flags_out (flags1); 761 1.1.1.5 mrg printf ("Got "); 762 1.1.1.5 mrg mpfr_dump (s2); 763 1.1.1.5 mrg printf (" with inex ~ %d, flags =", inex2); 764 1.1.1.5 mrg flags_out (flags2); 765 1.1.1.5 mrg exit (1); 766 1.1.1.5 mrg } 767 1.1.1.5 mrg 768 1.1.1.5 mrg if (neg == 0 || neg == 2) 769 1.1.1.5 mrg mpfr_neg (x, x, MPFR_RNDN); 770 1.1.1.5 mrg if (neg == 1 || neg == 3) 771 1.1.1.5 mrg mpfr_neg (y, y, MPFR_RNDN); 772 1.1.1.5 mrg mpfr_neg (z, z, MPFR_RNDN); 773 1.1.1.5 mrg } 774 1.1.1.5 mrg } 775 1.1.1.5 mrg 776 1.1.1.5 mrg mpfr_clears (x, y, z, s1, s2, (mpfr_ptr) 0); 777 1.1.1.5 mrg } 778 1.1.1.5 mrg 779 1.1.1.5 mrg /* Test s = x*y + z on: 780 1.1.1.5 mrg x = +/- 2^emin 781 1.1.1.5 mrg y = +/- 2^(-3) 782 1.1.1.5 mrg z = +/- 2^(emin + PREC(s)) and MPFR numbers close to this value. 783 1.1.1.5 mrg with PREC(z) from PREC(s) - 2 to PREC(s) + 8. 784 1.1.1.5 mrg */ 785 1.1.1.5 mrg static void 786 1.1.1.5 mrg test_underflow5 (void) 787 1.1.1.5 mrg { 788 1.1.1.5 mrg mpfr_t w, x, y, z, s1, s2, t; 789 1.1.1.5 mrg mpfr_exp_t emin; 790 1.1.1.5 mrg mpfr_prec_t ps = 32; 791 1.1.1.5 mrg int inex, i, j, rnd; 792 1.1.1.5 mrg unsigned int neg; 793 1.1.1.5 mrg 794 1.1.1.5 mrg mpfr_inits2 (MPFR_PREC_MIN, w, x, y, (mpfr_ptr) 0); 795 1.1.1.5 mrg mpfr_inits2 (ps, s1, s2, (mpfr_ptr) 0); 796 1.1.1.5 mrg mpfr_init2 (t, ps + 9); 797 1.1.1.5 mrg 798 1.1.1.5 mrg emin = mpfr_get_emin (); 799 1.1.1.5 mrg 800 1.1.1.5 mrg inex = mpfr_set_si_2exp (w, 1, emin, MPFR_RNDN); /* w = 2^emin */ 801 1.1.1.5 mrg MPFR_ASSERTN (inex == 0); 802 1.1.1.5 mrg inex = mpfr_set_si (x, 1, MPFR_RNDN); 803 1.1.1.5 mrg MPFR_ASSERTN (inex == 0); 804 1.1.1.5 mrg inex = mpfr_set_si_2exp (y, 1, -3, MPFR_RNDN); 805 1.1.1.5 mrg MPFR_ASSERTN (inex == 0); 806 1.1.1.5 mrg 807 1.1.1.5 mrg for (i = -2; i <= 8; i++) 808 1.1.1.5 mrg { 809 1.1.1.5 mrg mpfr_init2 (z, ps + i); 810 1.1.1.5 mrg inex = mpfr_set_si_2exp (z, 1, ps, MPFR_RNDN); 811 1.1.1.5 mrg MPFR_ASSERTN (inex == 0); 812 1.1.1.5 mrg 813 1.1.1.5 mrg for (j = 1; j <= 32; j++) 814 1.1.1.5 mrg mpfr_nextbelow (z); 815 1.1.1.5 mrg 816 1.1.1.5 mrg for (j = -32; j <= 32; j++) 817 1.1.1.5 mrg { 818 1.1.1.5 mrg for (neg = 0; neg < 8; neg++) 819 1.1.1.5 mrg { 820 1.1.1.5 mrg mpfr_setsign (x, x, neg & 1, MPFR_RNDN); 821 1.1.1.5 mrg mpfr_setsign (y, y, neg & 2, MPFR_RNDN); 822 1.1.1.5 mrg mpfr_setsign (z, z, neg & 4, MPFR_RNDN); 823 1.1.1.5 mrg 824 1.1.1.5 mrg inex = mpfr_fma (t, x, y, z, MPFR_RNDN); 825 1.1.1.5 mrg MPFR_ASSERTN (inex == 0); 826 1.1.1.5 mrg 827 1.1.1.5 mrg inex = mpfr_mul (x, x, w, MPFR_RNDN); 828 1.1.1.5 mrg MPFR_ASSERTN (inex == 0); 829 1.1.1.5 mrg inex = mpfr_mul (z, z, w, MPFR_RNDN); 830 1.1.1.5 mrg MPFR_ASSERTN (inex == 0); 831 1.1.1.5 mrg 832 1.1.1.5 mrg RND_LOOP_NO_RNDF (rnd) 833 1.1.1.5 mrg { 834 1.1.1.5 mrg mpfr_flags_t flags1, flags2; 835 1.1.1.5 mrg int inex1, inex2; 836 1.1.1.5 mrg 837 1.1.1.5 mrg mpfr_clear_flags (); 838 1.1.1.5 mrg inex1 = mpfr_mul (s1, w, t, (mpfr_rnd_t) rnd); 839 1.1.1.5 mrg flags1 = __gmpfr_flags; 840 1.1.1.5 mrg 841 1.1.1.5 mrg mpfr_clear_flags (); 842 1.1.1.5 mrg inex2 = mpfr_fma (s2, x, y, z, (mpfr_rnd_t) rnd); 843 1.1.1.5 mrg flags2 = __gmpfr_flags; 844 1.1.1.5 mrg 845 1.1.1.5 mrg if (! (mpfr_equal_p (s1, s2) && 846 1.1.1.5 mrg SAME_SIGN (inex1, inex2) && 847 1.1.1.5 mrg flags1 == flags2)) 848 1.1.1.5 mrg { 849 1.1.1.5 mrg printf ("Error in test_underflow5 on " 850 1.1.1.5 mrg "i=%d j=%d neg=%u %s\n", i, j, neg, 851 1.1.1.5 mrg mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); 852 1.1.1.5 mrg printf ("Expected "); 853 1.1.1.5 mrg mpfr_dump (s1); 854 1.1.1.5 mrg printf (" with inex ~ %d, flags =", inex1); 855 1.1.1.5 mrg flags_out (flags1); 856 1.1.1.5 mrg printf ("Got "); 857 1.1.1.5 mrg mpfr_dump (s2); 858 1.1.1.5 mrg printf (" with inex ~ %d, flags =", inex2); 859 1.1.1.5 mrg flags_out (flags2); 860 1.1.1.5 mrg exit (1); 861 1.1.1.5 mrg } 862 1.1.1.5 mrg } /* rnd */ 863 1.1.1.5 mrg 864 1.1.1.5 mrg inex = mpfr_div (x, x, w, MPFR_RNDN); 865 1.1.1.5 mrg MPFR_ASSERTN (inex == 0); 866 1.1.1.5 mrg inex = mpfr_div (z, z, w, MPFR_RNDN); 867 1.1.1.5 mrg MPFR_ASSERTN (inex == 0); 868 1.1.1.5 mrg } /* neg */ 869 1.1.1.5 mrg 870 1.1.1.5 mrg MPFR_SET_POS (z); /* restore the value before the loop on neg */ 871 1.1.1.5 mrg mpfr_nextabove (z); 872 1.1.1.5 mrg } /* j */ 873 1.1.1.5 mrg 874 1.1.1.5 mrg mpfr_clear (z); 875 1.1.1.5 mrg } /* i */ 876 1.1.1.5 mrg 877 1.1.1.5 mrg mpfr_clears (w, x, y, s1, s2, t, (mpfr_ptr) 0); 878 1.1.1.5 mrg } 879 1.1.1.5 mrg 880 1.1.1.3 mrg static void 881 1.1 mrg bug20101018 (void) 882 1.1 mrg { 883 1.1 mrg mpfr_t x, y, z, t, u; 884 1.1 mrg int i; 885 1.1 mrg 886 1.1 mrg mpfr_init2 (x, 64); 887 1.1 mrg mpfr_init2 (y, 64); 888 1.1 mrg mpfr_init2 (z, 64); 889 1.1 mrg mpfr_init2 (t, 64); 890 1.1 mrg mpfr_init2 (u, 64); 891 1.1 mrg 892 1.1 mrg mpfr_set_str (x, "0xf.fffffffffffffffp-14766", 16, MPFR_RNDN); 893 1.1 mrg mpfr_set_str (y, "-0xf.fffffffffffffffp+317", 16, MPFR_RNDN); 894 1.1 mrg mpfr_set_str (z, "0x8.3ffffffffffe3ffp-14443", 16, MPFR_RNDN); 895 1.1 mrg mpfr_set_str (t, "0x8.7ffffffffffc7ffp-14444", 16, MPFR_RNDN); 896 1.1 mrg i = mpfr_fma (u, x, y, z, MPFR_RNDN); 897 1.1.1.3 mrg if (! mpfr_equal_p (u, t)) 898 1.1 mrg { 899 1.1 mrg printf ("Wrong result in bug20101018 (a)\n"); 900 1.1 mrg printf ("Expected "); 901 1.1 mrg mpfr_out_str (stdout, 16, 0, t, MPFR_RNDN); 902 1.1 mrg printf ("\nGot "); 903 1.1 mrg mpfr_out_str (stdout, 16, 0, u, MPFR_RNDN); 904 1.1 mrg printf ("\n"); 905 1.1 mrg exit (1); 906 1.1 mrg } 907 1.1 mrg if (i <= 0) 908 1.1 mrg { 909 1.1 mrg printf ("Wrong ternary value in bug20101018 (a)\n"); 910 1.1 mrg printf ("Expected > 0\n"); 911 1.1 mrg printf ("Got %d\n", i); 912 1.1 mrg exit (1); 913 1.1 mrg } 914 1.1 mrg 915 1.1 mrg mpfr_set_str (x, "-0xf.fffffffffffffffp-11420", 16, MPFR_RNDN); 916 1.1 mrg mpfr_set_str (y, "0xf.fffffffffffffffp+9863", 16, MPFR_RNDN); 917 1.1 mrg mpfr_set_str (z, "0x8.fffff80ffffffffp-1551", 16, MPFR_RNDN); 918 1.1 mrg mpfr_set_str (t, "0x9.fffff01ffffffffp-1552", 16, MPFR_RNDN); 919 1.1 mrg i = mpfr_fma (u, x, y, z, MPFR_RNDN); 920 1.1.1.3 mrg if (! mpfr_equal_p (u, t)) 921 1.1 mrg { 922 1.1 mrg printf ("Wrong result in bug20101018 (b)\n"); 923 1.1 mrg printf ("Expected "); 924 1.1 mrg mpfr_out_str (stdout, 16, 0, t, MPFR_RNDN); 925 1.1 mrg printf ("\nGot "); 926 1.1 mrg mpfr_out_str (stdout, 16, 0, u, MPFR_RNDN); 927 1.1 mrg printf ("\n"); 928 1.1 mrg exit (1); 929 1.1 mrg } 930 1.1 mrg if (i <= 0) 931 1.1 mrg { 932 1.1 mrg printf ("Wrong ternary value in bug20101018 (b)\n"); 933 1.1 mrg printf ("Expected > 0\n"); 934 1.1 mrg printf ("Got %d\n", i); 935 1.1 mrg exit (1); 936 1.1 mrg } 937 1.1 mrg 938 1.1 mrg mpfr_set_str (x, "0xf.fffffffffffffffp-2125", 16, MPFR_RNDN); 939 1.1 mrg mpfr_set_str (y, "-0xf.fffffffffffffffp-6000", 16, MPFR_RNDN); 940 1.1 mrg mpfr_set_str (z, "0x8p-8119", 16, MPFR_RNDN); 941 1.1 mrg mpfr_set_str (t, "0x8.000000000000001p-8120", 16, MPFR_RNDN); 942 1.1 mrg i = mpfr_fma (u, x, y, z, MPFR_RNDN); 943 1.1.1.3 mrg if (! mpfr_equal_p (u, t)) 944 1.1 mrg { 945 1.1 mrg printf ("Wrong result in bug20101018 (c)\n"); 946 1.1 mrg printf ("Expected "); 947 1.1 mrg mpfr_out_str (stdout, 16, 0, t, MPFR_RNDN); 948 1.1 mrg printf ("\nGot "); 949 1.1 mrg mpfr_out_str (stdout, 16, 0, u, MPFR_RNDN); 950 1.1 mrg printf ("\n"); 951 1.1 mrg exit (1); 952 1.1 mrg } 953 1.1 mrg if (i <= 0) 954 1.1 mrg { 955 1.1 mrg printf ("Wrong ternary value in bug20101018 (c)\n"); 956 1.1 mrg printf ("Expected > 0\n"); 957 1.1 mrg printf ("Got %d\n", i); 958 1.1 mrg exit (1); 959 1.1 mrg } 960 1.1 mrg 961 1.1 mrg mpfr_clear (x); 962 1.1 mrg mpfr_clear (y); 963 1.1 mrg mpfr_clear (z); 964 1.1 mrg mpfr_clear (t); 965 1.1 mrg mpfr_clear (u); 966 1.1 mrg } 967 1.1 mrg 968 1.1.1.4 mrg /* bug found with GMP_CHECK_RANDOMIZE=1514407719 */ 969 1.1.1.4 mrg static void 970 1.1.1.4 mrg bug20171219 (void) 971 1.1.1.4 mrg { 972 1.1.1.4 mrg mpfr_t x, y, z, t, u; 973 1.1.1.4 mrg int i; 974 1.1.1.4 mrg 975 1.1.1.4 mrg mpfr_init2 (x, 60); 976 1.1.1.4 mrg mpfr_init2 (y, 60); 977 1.1.1.4 mrg mpfr_init2 (z, 60); 978 1.1.1.4 mrg mpfr_init2 (t, 68); 979 1.1.1.4 mrg mpfr_init2 (u, 68); 980 1.1.1.4 mrg 981 1.1.1.4 mrg mpfr_set_ui (x, 1, MPFR_RNDN); 982 1.1.1.4 mrg mpfr_set_ui (y, 1, MPFR_RNDN); 983 1.1.1.4 mrg mpfr_set_ui (z, 1, MPFR_RNDN); 984 1.1.1.4 mrg mpfr_set_ui (t, 2, MPFR_RNDN); 985 1.1.1.4 mrg i = mpfr_fma (u, x, y, z, MPFR_RNDA); 986 1.1.1.4 mrg if (! mpfr_equal_p (u, t)) 987 1.1.1.4 mrg { 988 1.1.1.4 mrg printf ("Wrong result in bug20171219 (a)\n"); 989 1.1.1.4 mrg printf ("Expected "); 990 1.1.1.4 mrg mpfr_out_str (stdout, 16, 0, t, MPFR_RNDN); 991 1.1.1.4 mrg printf ("\nGot "); 992 1.1.1.4 mrg mpfr_out_str (stdout, 16, 0, u, MPFR_RNDN); 993 1.1.1.4 mrg printf ("\n"); 994 1.1.1.4 mrg exit (1); 995 1.1.1.4 mrg } 996 1.1.1.4 mrg if (i != 0) 997 1.1.1.4 mrg { 998 1.1.1.4 mrg printf ("Wrong ternary value in bug20171219\n"); 999 1.1.1.4 mrg printf ("Expected 0\n"); 1000 1.1.1.4 mrg printf ("Got %d\n", i); 1001 1.1.1.4 mrg exit (1); 1002 1.1.1.4 mrg } 1003 1.1.1.4 mrg 1004 1.1.1.4 mrg mpfr_clear (x); 1005 1.1.1.4 mrg mpfr_clear (y); 1006 1.1.1.4 mrg mpfr_clear (z); 1007 1.1.1.4 mrg mpfr_clear (t); 1008 1.1.1.4 mrg mpfr_clear (u); 1009 1.1.1.4 mrg } 1010 1.1.1.4 mrg 1011 1.1.1.5 mrg /* coverage test for mpfr_set_1_2, case prec < GMP_NUMB_BITS, 1012 1.1.1.5 mrg inex > 0, rb <> 0, sb = 0 */ 1013 1.1.1.5 mrg static void 1014 1.1.1.5 mrg coverage (void) 1015 1.1.1.5 mrg { 1016 1.1.1.5 mrg mpfr_t x, y, z, s; 1017 1.1.1.5 mrg int inex; 1018 1.1.1.5 mrg mpfr_exp_t emax; 1019 1.1.1.5 mrg 1020 1.1.1.5 mrg mpfr_inits2 (GMP_NUMB_BITS - 1, x, y, z, s, (mpfr_ptr) 0); 1021 1.1.1.5 mrg 1022 1.1.1.5 mrg /* set x to 2^(GMP_NUMB_BITS/2) + 1, y to 2^(GMP_NUMB_BITS/2) - 1 */ 1023 1.1.1.5 mrg MPFR_ASSERTN((GMP_NUMB_BITS % 2) == 0); 1024 1.1.1.5 mrg mpfr_set_ui_2exp (x, 1, GMP_NUMB_BITS / 2, MPFR_RNDN); 1025 1.1.1.5 mrg mpfr_sub_ui (y, x, 1, MPFR_RNDN); 1026 1.1.1.5 mrg mpfr_add_ui (x, x, 1, MPFR_RNDN); 1027 1.1.1.5 mrg /* we have x*y = 2^GMP_NUMB_BITS - 1, thus has exponent GMP_NUMB_BITS */ 1028 1.1.1.5 mrg /* set z to 2^(1-GMP_NUMB_BITS), with exponent 2-GMP_NUMB_BITS */ 1029 1.1.1.5 mrg mpfr_set_ui_2exp (z, 1, 1 - GMP_NUMB_BITS, MPFR_RNDN); 1030 1.1.1.5 mrg inex = mpfr_fms (s, x, y, z, MPFR_RNDN); 1031 1.1.1.5 mrg /* s should be 2^GMP_NUMB_BITS-2 */ 1032 1.1.1.5 mrg MPFR_ASSERTN(inex < 0); 1033 1.1.1.5 mrg inex = mpfr_add_ui (s, s, 2, MPFR_RNDN); 1034 1.1.1.5 mrg MPFR_ASSERTN(mpfr_cmp_ui_2exp (s, 1, GMP_NUMB_BITS) == 0); 1035 1.1.1.5 mrg 1036 1.1.1.5 mrg /* same example, but with overflow */ 1037 1.1.1.5 mrg emax = mpfr_get_emax (); 1038 1.1.1.6 mrg set_emax (GMP_NUMB_BITS + 1); 1039 1.1.1.5 mrg mpfr_set_ui_2exp (z, 1, mpfr_get_emax () - 1, MPFR_RNDZ); 1040 1.1.1.5 mrg mpfr_clear_flags (); 1041 1.1.1.5 mrg inex = mpfr_fma (s, x, y, z, MPFR_RNDN); 1042 1.1.1.5 mrg /* x*y = 2^GMP_NUMB_BITS - 1, z = 2^GMP_NUMB_BITS, thus 1043 1.1.1.5 mrg x*y+z = 2^(GMP_NUMB_BITS+1) - 1 should round to 2^(GMP_NUMB_BITS+1), 1044 1.1.1.5 mrg thus give an overflow */ 1045 1.1.1.5 mrg MPFR_ASSERTN(inex > 0); 1046 1.1.1.5 mrg MPFR_ASSERTN(mpfr_inf_p (s) && mpfr_sgn (s) > 0); 1047 1.1.1.5 mrg MPFR_ASSERTN(mpfr_overflow_p ()); 1048 1.1.1.6 mrg set_emax (emax); 1049 1.1.1.5 mrg 1050 1.1.1.5 mrg mpfr_clear (x); 1051 1.1.1.5 mrg mpfr_clear (y); 1052 1.1.1.5 mrg mpfr_clear (z); 1053 1.1.1.5 mrg mpfr_clear (s); 1054 1.1.1.5 mrg } 1055 1.1.1.5 mrg 1056 1.1 mrg int 1057 1.1 mrg main (int argc, char *argv[]) 1058 1.1 mrg { 1059 1.1 mrg mpfr_t x, y, z, s; 1060 1.1.1.3 mrg mpfr_exp_t emin, emax; 1061 1.1.1.5 mrg int i; 1062 1.1 mrg 1063 1.1 mrg tests_start_mpfr (); 1064 1.1 mrg 1065 1.1.1.5 mrg coverage (); 1066 1.1.1.5 mrg 1067 1.1.1.3 mrg emin = mpfr_get_emin (); 1068 1.1.1.3 mrg emax = mpfr_get_emax (); 1069 1.1.1.3 mrg 1070 1.1.1.4 mrg bug20171219 (); 1071 1.1 mrg bug20101018 (); 1072 1.1 mrg 1073 1.1 mrg mpfr_init (x); 1074 1.1 mrg mpfr_init (s); 1075 1.1 mrg mpfr_init (y); 1076 1.1 mrg mpfr_init (z); 1077 1.1 mrg 1078 1.1 mrg /* check special cases */ 1079 1.1 mrg mpfr_set_prec (x, 2); 1080 1.1 mrg mpfr_set_prec (y, 2); 1081 1.1 mrg mpfr_set_prec (z, 2); 1082 1.1 mrg mpfr_set_prec (s, 2); 1083 1.1 mrg mpfr_set_str (x, "-0.75", 10, MPFR_RNDN); 1084 1.1 mrg mpfr_set_str (y, "0.5", 10, MPFR_RNDN); 1085 1.1 mrg mpfr_set_str (z, "0.375", 10, MPFR_RNDN); 1086 1.1 mrg mpfr_fma (s, x, y, z, MPFR_RNDU); /* result is 0 */ 1087 1.1.1.4 mrg if (mpfr_cmp_ui (s, 0)) 1088 1.1 mrg { 1089 1.1.1.4 mrg printf ("Error: -0.75 * 0.5 + 0.375 should be equal to 0 for prec=2\n"); 1090 1.1.1.4 mrg printf ("got instead "); 1091 1.1.1.4 mrg mpfr_dump (s); 1092 1.1.1.4 mrg exit (1); 1093 1.1 mrg } 1094 1.1 mrg 1095 1.1 mrg mpfr_set_prec (x, 27); 1096 1.1 mrg mpfr_set_prec (y, 27); 1097 1.1 mrg mpfr_set_prec (z, 27); 1098 1.1 mrg mpfr_set_prec (s, 27); 1099 1.1 mrg mpfr_set_str_binary (x, "1.11111111111111111111111111e-1"); 1100 1.1 mrg mpfr_set (y, x, MPFR_RNDN); 1101 1.1 mrg mpfr_set_str_binary (z, "-1.00011110100011001011001001e-1"); 1102 1.1 mrg if (mpfr_fma (s, x, y, z, MPFR_RNDN) >= 0) 1103 1.1 mrg { 1104 1.1 mrg printf ("Wrong inexact flag for x=y=1-2^(-27)\n"); 1105 1.1 mrg exit (1); 1106 1.1 mrg } 1107 1.1 mrg 1108 1.1 mrg mpfr_set_nan (x); 1109 1.1 mrg mpfr_urandomb (y, RANDS); 1110 1.1 mrg mpfr_urandomb (z, RANDS); 1111 1.1 mrg mpfr_fma (s, x, y, z, MPFR_RNDN); 1112 1.1 mrg if (!mpfr_nan_p (s)) 1113 1.1 mrg { 1114 1.1.1.4 mrg printf ("evaluation of function in x=NAN does not return NAN\n"); 1115 1.1 mrg exit (1); 1116 1.1 mrg } 1117 1.1 mrg 1118 1.1 mrg mpfr_set_nan (y); 1119 1.1 mrg mpfr_urandomb (x, RANDS); 1120 1.1 mrg mpfr_urandomb (z, RANDS); 1121 1.1 mrg mpfr_fma (s, x, y, z, MPFR_RNDN); 1122 1.1 mrg if (!mpfr_nan_p(s)) 1123 1.1 mrg { 1124 1.1.1.4 mrg printf ("evaluation of function in y=NAN does not return NAN\n"); 1125 1.1 mrg exit (1); 1126 1.1 mrg } 1127 1.1 mrg 1128 1.1 mrg mpfr_set_nan (z); 1129 1.1 mrg mpfr_urandomb (y, RANDS); 1130 1.1 mrg mpfr_urandomb (x, RANDS); 1131 1.1 mrg mpfr_fma (s, x, y, z, MPFR_RNDN); 1132 1.1 mrg if (!mpfr_nan_p (s)) 1133 1.1 mrg { 1134 1.1.1.4 mrg printf ("evaluation of function in z=NAN does not return NAN\n"); 1135 1.1 mrg exit (1); 1136 1.1 mrg } 1137 1.1 mrg 1138 1.1 mrg mpfr_set_inf (x, 1); 1139 1.1 mrg mpfr_set_inf (y, 1); 1140 1.1 mrg mpfr_set_inf (z, 1); 1141 1.1 mrg mpfr_fma (s, x, y, z, MPFR_RNDN); 1142 1.1 mrg if (!mpfr_inf_p (s) || mpfr_sgn (s) < 0) 1143 1.1 mrg { 1144 1.1 mrg printf ("Error for (+inf) * (+inf) + (+inf)\n"); 1145 1.1 mrg exit (1); 1146 1.1 mrg } 1147 1.1 mrg 1148 1.1 mrg mpfr_set_inf (x, -1); 1149 1.1 mrg mpfr_set_inf (y, -1); 1150 1.1 mrg mpfr_set_inf (z, 1); 1151 1.1 mrg mpfr_fma (s, x, y, z, MPFR_RNDN); 1152 1.1 mrg if (!mpfr_inf_p (s) || mpfr_sgn (s) < 0) 1153 1.1 mrg { 1154 1.1 mrg printf ("Error for (-inf) * (-inf) + (+inf)\n"); 1155 1.1 mrg exit (1); 1156 1.1 mrg } 1157 1.1 mrg 1158 1.1 mrg mpfr_set_inf (x, 1); 1159 1.1 mrg mpfr_set_inf (y, -1); 1160 1.1 mrg mpfr_set_inf (z, -1); 1161 1.1 mrg mpfr_fma (s, x, y, z, MPFR_RNDN); 1162 1.1 mrg if (!mpfr_inf_p (s) || mpfr_sgn (s) > 0) 1163 1.1 mrg { 1164 1.1 mrg printf ("Error for (+inf) * (-inf) + (-inf)\n"); 1165 1.1 mrg exit (1); 1166 1.1 mrg } 1167 1.1 mrg 1168 1.1 mrg mpfr_set_inf (x, -1); 1169 1.1 mrg mpfr_set_inf (y, 1); 1170 1.1 mrg mpfr_set_inf (z, -1); 1171 1.1 mrg mpfr_fma (s, x, y, z, MPFR_RNDN); 1172 1.1 mrg if (!mpfr_inf_p (s) || mpfr_sgn (s) > 0) 1173 1.1 mrg { 1174 1.1 mrg printf ("Error for (-inf) * (+inf) + (-inf)\n"); 1175 1.1 mrg exit (1); 1176 1.1 mrg } 1177 1.1 mrg 1178 1.1 mrg mpfr_set_inf (x, 1); 1179 1.1 mrg mpfr_set_ui (y, 0, MPFR_RNDN); 1180 1.1 mrg mpfr_urandomb (z, RANDS); 1181 1.1 mrg mpfr_fma (s, x, y, z, MPFR_RNDN); 1182 1.1 mrg if (!mpfr_nan_p (s)) 1183 1.1 mrg { 1184 1.1.1.4 mrg printf ("evaluation of function in x=INF y=0 does not return NAN\n"); 1185 1.1 mrg exit (1); 1186 1.1 mrg } 1187 1.1 mrg 1188 1.1 mrg mpfr_set_inf (y, 1); 1189 1.1 mrg mpfr_set_ui (x, 0, MPFR_RNDN); 1190 1.1 mrg mpfr_urandomb (z, RANDS); 1191 1.1 mrg mpfr_fma (s, x, y, z, MPFR_RNDN); 1192 1.1 mrg if (!mpfr_nan_p (s)) 1193 1.1 mrg { 1194 1.1.1.4 mrg printf ("evaluation of function in x=0 y=INF does not return NAN\n"); 1195 1.1 mrg exit (1); 1196 1.1 mrg } 1197 1.1 mrg 1198 1.1 mrg mpfr_set_inf (x, 1); 1199 1.1 mrg mpfr_urandomb (y, RANDS); /* always positive */ 1200 1.1 mrg mpfr_set_inf (z, -1); 1201 1.1 mrg mpfr_fma (s, x, y, z, MPFR_RNDN); 1202 1.1 mrg if (!mpfr_nan_p (s)) 1203 1.1 mrg { 1204 1.1.1.4 mrg printf ("evaluation of function in x=INF y>0 z=-INF does not return NAN\n"); 1205 1.1 mrg exit (1); 1206 1.1 mrg } 1207 1.1 mrg 1208 1.1 mrg mpfr_set_inf (y, 1); 1209 1.1 mrg mpfr_urandomb (x, RANDS); 1210 1.1 mrg mpfr_set_inf (z, -1); 1211 1.1 mrg mpfr_fma (s, x, y, z, MPFR_RNDN); 1212 1.1 mrg if (!mpfr_nan_p (s)) 1213 1.1 mrg { 1214 1.1.1.4 mrg printf ("evaluation of function in x>0 y=INF z=-INF does not return NAN\n"); 1215 1.1 mrg exit (1); 1216 1.1 mrg } 1217 1.1 mrg 1218 1.1 mrg mpfr_set_inf (x, 1); 1219 1.1.1.4 mrg do mpfr_urandomb (y, RANDS); while (MPFR_IS_ZERO(y)); 1220 1.1 mrg mpfr_urandomb (z, RANDS); 1221 1.1 mrg mpfr_fma (s, x, y, z, MPFR_RNDN); 1222 1.1 mrg if (!mpfr_inf_p (s) || mpfr_sgn (s) < 0) 1223 1.1 mrg { 1224 1.1.1.4 mrg printf ("evaluation of function in x=INF does not return INF\n"); 1225 1.1 mrg exit (1); 1226 1.1 mrg } 1227 1.1 mrg 1228 1.1 mrg mpfr_set_inf (y, 1); 1229 1.1.1.4 mrg do mpfr_urandomb (x, RANDS); while (MPFR_IS_ZERO(x)); 1230 1.1 mrg mpfr_urandomb (z, RANDS); 1231 1.1 mrg mpfr_fma (s, x, y, z, MPFR_RNDN); 1232 1.1 mrg if (!mpfr_inf_p (s) || mpfr_sgn (s) < 0) 1233 1.1 mrg { 1234 1.1.1.4 mrg printf ("evaluation of function at y=INF does not return INF\n"); 1235 1.1 mrg exit (1); 1236 1.1 mrg } 1237 1.1 mrg 1238 1.1 mrg mpfr_set_inf (z, 1); 1239 1.1 mrg mpfr_urandomb (x, RANDS); 1240 1.1 mrg mpfr_urandomb (y, RANDS); 1241 1.1 mrg mpfr_fma (s, x, y, z, MPFR_RNDN); 1242 1.1 mrg if (!mpfr_inf_p (s) || mpfr_sgn (s) < 0) 1243 1.1 mrg { 1244 1.1.1.4 mrg printf ("evaluation of function in z=INF does not return INF\n"); 1245 1.1 mrg exit (1); 1246 1.1 mrg } 1247 1.1 mrg 1248 1.1 mrg mpfr_set_ui (x, 0, MPFR_RNDN); 1249 1.1 mrg mpfr_urandomb (y, RANDS); 1250 1.1 mrg mpfr_urandomb (z, RANDS); 1251 1.1 mrg mpfr_fma (s, x, y, z, MPFR_RNDN); 1252 1.1.1.3 mrg if (! mpfr_equal_p (s, z)) 1253 1.1 mrg { 1254 1.1 mrg printf ("evaluation of function in x=0 does not return z\n"); 1255 1.1 mrg exit (1); 1256 1.1 mrg } 1257 1.1 mrg 1258 1.1 mrg mpfr_set_ui (y, 0, MPFR_RNDN); 1259 1.1 mrg mpfr_urandomb (x, RANDS); 1260 1.1 mrg mpfr_urandomb (z, RANDS); 1261 1.1 mrg mpfr_fma (s, x, y, z, MPFR_RNDN); 1262 1.1.1.3 mrg if (! mpfr_equal_p (s, z)) 1263 1.1 mrg { 1264 1.1 mrg printf ("evaluation of function in y=0 does not return z\n"); 1265 1.1 mrg exit (1); 1266 1.1 mrg } 1267 1.1 mrg 1268 1.1 mrg { 1269 1.1 mrg mpfr_prec_t prec; 1270 1.1 mrg mpfr_t t, slong; 1271 1.1 mrg mpfr_rnd_t rnd; 1272 1.1 mrg int inexact, compare; 1273 1.1 mrg unsigned int n; 1274 1.1 mrg 1275 1.1.1.3 mrg mpfr_prec_t p0 = 2, p1 = 200; 1276 1.1.1.3 mrg unsigned int N = 200; 1277 1.1 mrg 1278 1.1 mrg mpfr_init (t); 1279 1.1 mrg mpfr_init (slong); 1280 1.1 mrg 1281 1.1 mrg /* generic test */ 1282 1.1 mrg for (prec = p0; prec <= p1; prec++) 1283 1.1.1.3 mrg { 1284 1.1.1.3 mrg mpfr_set_prec (x, prec); 1285 1.1.1.3 mrg mpfr_set_prec (y, prec); 1286 1.1.1.3 mrg mpfr_set_prec (z, prec); 1287 1.1.1.3 mrg mpfr_set_prec (s, prec); 1288 1.1.1.3 mrg mpfr_set_prec (t, prec); 1289 1.1 mrg 1290 1.1.1.3 mrg for (n = 0; n < N; n++) 1291 1.1.1.3 mrg { 1292 1.1.1.3 mrg mpfr_urandomb (x, RANDS); 1293 1.1.1.3 mrg mpfr_urandomb (y, RANDS); 1294 1.1.1.3 mrg mpfr_urandomb (z, RANDS); 1295 1.1.1.3 mrg 1296 1.1.1.6 mrg if (RAND_BOOL ()) 1297 1.1.1.3 mrg mpfr_neg (x, x, MPFR_RNDN); 1298 1.1.1.6 mrg if (RAND_BOOL ()) 1299 1.1.1.3 mrg mpfr_neg (y, y, MPFR_RNDN); 1300 1.1.1.6 mrg if (RAND_BOOL ()) 1301 1.1.1.3 mrg mpfr_neg (z, z, MPFR_RNDN); 1302 1.1.1.3 mrg 1303 1.1.1.4 mrg rnd = RND_RAND_NO_RNDF (); 1304 1.1.1.3 mrg mpfr_set_prec (slong, 2 * prec); 1305 1.1.1.3 mrg if (mpfr_mul (slong, x, y, rnd)) 1306 1.1.1.3 mrg { 1307 1.1.1.3 mrg printf ("x*y should be exact\n"); 1308 1.1.1.3 mrg exit (1); 1309 1.1.1.3 mrg } 1310 1.1.1.3 mrg compare = mpfr_add (t, slong, z, rnd); 1311 1.1.1.3 mrg inexact = mpfr_fma (s, x, y, z, rnd); 1312 1.1.1.3 mrg if (! mpfr_equal_p (s, t)) 1313 1.1.1.3 mrg { 1314 1.1.1.4 mrg printf ("results differ for\n"); 1315 1.1.1.4 mrg printf (" x="); 1316 1.1.1.4 mrg mpfr_dump (x); 1317 1.1.1.3 mrg printf (" y="); 1318 1.1.1.4 mrg mpfr_dump (y); 1319 1.1.1.3 mrg printf (" z="); 1320 1.1.1.4 mrg mpfr_dump (z); 1321 1.1.1.4 mrg printf (" with prec=%u rnd_mode=%s\n", (unsigned int) prec, 1322 1.1.1.3 mrg mpfr_print_rnd_mode (rnd)); 1323 1.1.1.3 mrg printf ("got "); 1324 1.1.1.4 mrg mpfr_dump (s); 1325 1.1.1.3 mrg printf ("expected "); 1326 1.1.1.4 mrg mpfr_dump (t); 1327 1.1.1.4 mrg printf ("approx "); 1328 1.1.1.4 mrg mpfr_dump (slong); 1329 1.1.1.3 mrg exit (1); 1330 1.1.1.3 mrg } 1331 1.1.1.3 mrg if (! SAME_SIGN (inexact, compare)) 1332 1.1.1.3 mrg { 1333 1.1.1.3 mrg printf ("Wrong inexact flag for rnd=%s: expected %d, got %d\n", 1334 1.1.1.3 mrg mpfr_print_rnd_mode (rnd), compare, inexact); 1335 1.1.1.4 mrg printf (" x="); mpfr_dump (x); 1336 1.1.1.4 mrg printf (" y="); mpfr_dump (y); 1337 1.1.1.4 mrg printf (" z="); mpfr_dump (z); 1338 1.1.1.4 mrg printf (" s="); mpfr_dump (s); 1339 1.1.1.3 mrg exit (1); 1340 1.1.1.3 mrg } 1341 1.1.1.3 mrg } 1342 1.1.1.3 mrg } 1343 1.1.1.3 mrg mpfr_clear (t); 1344 1.1.1.3 mrg mpfr_clear (slong); 1345 1.1 mrg 1346 1.1 mrg } 1347 1.1 mrg mpfr_clear (x); 1348 1.1 mrg mpfr_clear (y); 1349 1.1 mrg mpfr_clear (z); 1350 1.1 mrg mpfr_clear (s); 1351 1.1 mrg 1352 1.1 mrg test_exact (); 1353 1.1 mrg 1354 1.1.1.5 mrg for (i = 0; i <= 2; i++) 1355 1.1.1.5 mrg { 1356 1.1.1.5 mrg if (i == 0) 1357 1.1.1.5 mrg { 1358 1.1.1.5 mrg /* corresponds to the generic code + mpfr_check_range */ 1359 1.1.1.5 mrg set_emin (-1024); 1360 1.1.1.5 mrg set_emax (1024); 1361 1.1.1.5 mrg } 1362 1.1.1.5 mrg else if (i == 1) 1363 1.1.1.5 mrg { 1364 1.1.1.5 mrg set_emin (MPFR_EMIN_MIN); 1365 1.1.1.5 mrg set_emax (MPFR_EMAX_MAX); 1366 1.1.1.5 mrg } 1367 1.1.1.5 mrg else 1368 1.1.1.5 mrg { 1369 1.1.1.5 mrg MPFR_ASSERTN (i == 2); 1370 1.1.1.5 mrg if (emin == MPFR_EMIN_MIN && emax == MPFR_EMAX_MAX) 1371 1.1.1.5 mrg break; 1372 1.1.1.5 mrg set_emin (emin); 1373 1.1.1.5 mrg set_emax (emax); 1374 1.1.1.5 mrg } 1375 1.1.1.5 mrg 1376 1.1.1.5 mrg test_overflow1 (); 1377 1.1.1.5 mrg test_overflow2 (); 1378 1.1.1.5 mrg test_overflow3 (); 1379 1.1.1.5 mrg test_overflow4 (); 1380 1.1.1.5 mrg test_overflow5 (); 1381 1.1.1.5 mrg test_underflow1 (); 1382 1.1.1.5 mrg test_underflow2 (); 1383 1.1.1.5 mrg test_underflow3 (i); 1384 1.1.1.5 mrg test_underflow4 (); 1385 1.1.1.5 mrg test_underflow5 (); 1386 1.1.1.5 mrg } 1387 1.1 mrg 1388 1.1 mrg tests_end_mpfr (); 1389 1.1 mrg return 0; 1390 1.1 mrg } 1391