1 1.1 mrg /* Test file for mpfr_mul. 2 1.1 mrg 3 1.1.1.6 mrg Copyright 1999, 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 #ifdef CHECK_EXTERNAL 26 1.1 mrg static int 27 1.1 mrg test_mul (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) 28 1.1 mrg { 29 1.1 mrg int res; 30 1.1 mrg int ok = rnd_mode == MPFR_RNDN && mpfr_number_p (b) && mpfr_number_p (c); 31 1.1 mrg if (ok) 32 1.1 mrg { 33 1.1 mrg mpfr_print_raw (b); 34 1.1 mrg printf (" "); 35 1.1 mrg mpfr_print_raw (c); 36 1.1 mrg } 37 1.1 mrg res = mpfr_mul (a, b, c, rnd_mode); 38 1.1 mrg if (ok) 39 1.1 mrg { 40 1.1 mrg printf (" "); 41 1.1 mrg mpfr_print_raw (a); 42 1.1 mrg printf ("\n"); 43 1.1 mrg } 44 1.1 mrg return res; 45 1.1 mrg } 46 1.1 mrg #else 47 1.1 mrg #define test_mul mpfr_mul 48 1.1 mrg #endif 49 1.1 mrg 50 1.1 mrg /* checks that xs * ys gives the expected result res */ 51 1.1 mrg static void 52 1.1 mrg check (const char *xs, const char *ys, mpfr_rnd_t rnd_mode, 53 1.1 mrg unsigned int px, unsigned int py, unsigned int pz, const char *res) 54 1.1 mrg { 55 1.1 mrg mpfr_t xx, yy, zz; 56 1.1 mrg 57 1.1 mrg mpfr_init2 (xx, px); 58 1.1 mrg mpfr_init2 (yy, py); 59 1.1 mrg mpfr_init2 (zz, pz); 60 1.1 mrg mpfr_set_str1 (xx, xs); 61 1.1 mrg mpfr_set_str1 (yy, ys); 62 1.1 mrg test_mul(zz, xx, yy, rnd_mode); 63 1.1 mrg if (mpfr_cmp_str1 (zz, res) ) 64 1.1 mrg { 65 1.1.1.4 mrg printf ("(1) mpfr_mul failed for x=%s y=%s with rnd=%s\n", 66 1.1 mrg xs, ys, mpfr_print_rnd_mode (rnd_mode)); 67 1.1 mrg printf ("correct is %s, mpfr_mul gives ", res); 68 1.1.1.4 mrg mpfr_out_str (stdout, 10, 0, zz, MPFR_RNDN); 69 1.1.1.4 mrg putchar ('\n'); 70 1.1 mrg exit (1); 71 1.1 mrg } 72 1.1.1.4 mrg mpfr_clear (xx); 73 1.1.1.4 mrg mpfr_clear (yy); 74 1.1.1.4 mrg mpfr_clear (zz); 75 1.1 mrg } 76 1.1 mrg 77 1.1 mrg static void 78 1.1 mrg check53 (const char *xs, const char *ys, mpfr_rnd_t rnd_mode, const char *zs) 79 1.1 mrg { 80 1.1 mrg mpfr_t xx, yy, zz; 81 1.1 mrg 82 1.1 mrg mpfr_inits2 (53, xx, yy, zz, (mpfr_ptr) 0); 83 1.1 mrg mpfr_set_str1 (xx, xs); 84 1.1 mrg mpfr_set_str1 (yy, ys); 85 1.1 mrg test_mul (zz, xx, yy, rnd_mode); 86 1.1 mrg if (mpfr_cmp_str1 (zz, zs) ) 87 1.1 mrg { 88 1.1 mrg printf ("(2) mpfr_mul failed for x=%s y=%s with rnd=%s\n", 89 1.1 mrg xs, ys, mpfr_print_rnd_mode(rnd_mode)); 90 1.1 mrg printf ("correct result is %s,\n mpfr_mul gives ", zs); 91 1.1.1.4 mrg mpfr_out_str (stdout, 10, 0, zz, MPFR_RNDN); 92 1.1.1.4 mrg putchar ('\n'); 93 1.1 mrg exit (1); 94 1.1 mrg } 95 1.1 mrg mpfr_clears (xx, yy, zz, (mpfr_ptr) 0); 96 1.1 mrg } 97 1.1 mrg 98 1.1 mrg /* checks that x*y gives the right result with 24 bits of precision */ 99 1.1 mrg static void 100 1.1 mrg check24 (const char *xs, const char *ys, mpfr_rnd_t rnd_mode, const char *zs) 101 1.1 mrg { 102 1.1 mrg mpfr_t xx, yy, zz; 103 1.1 mrg 104 1.1 mrg mpfr_inits2 (24, xx, yy, zz, (mpfr_ptr) 0); 105 1.1 mrg mpfr_set_str1 (xx, xs); 106 1.1 mrg mpfr_set_str1 (yy, ys); 107 1.1 mrg test_mul (zz, xx, yy, rnd_mode); 108 1.1 mrg if (mpfr_cmp_str1 (zz, zs) ) 109 1.1 mrg { 110 1.1 mrg printf ("(3) mpfr_mul failed for x=%s y=%s with " 111 1.1 mrg "rnd=%s\n", xs, ys, mpfr_print_rnd_mode(rnd_mode)); 112 1.1 mrg printf ("correct result is gives %s, mpfr_mul gives ", zs); 113 1.1.1.4 mrg mpfr_out_str (stdout, 10, 0, zz, MPFR_RNDN); 114 1.1.1.4 mrg putchar ('\n'); 115 1.1 mrg exit (1); 116 1.1 mrg } 117 1.1 mrg mpfr_clears (xx, yy, zz, (mpfr_ptr) 0); 118 1.1 mrg } 119 1.1 mrg 120 1.1 mrg /* the following examples come from the paper "Number-theoretic Test 121 1.1 mrg Generation for Directed Rounding" from Michael Parks, Table 1 */ 122 1.1 mrg static void 123 1.1 mrg check_float (void) 124 1.1 mrg { 125 1.1 mrg check24("8388609.0", "8388609.0", MPFR_RNDN, "70368760954880.0"); 126 1.1 mrg check24("16777213.0", "8388609.0", MPFR_RNDN, "140737479966720.0"); 127 1.1 mrg check24("8388611.0", "8388609.0", MPFR_RNDN, "70368777732096.0"); 128 1.1 mrg check24("12582911.0", "8388610.0", MPFR_RNDN, "105553133043712.0"); 129 1.1 mrg check24("12582914.0", "8388610.0", MPFR_RNDN, "105553158209536.0"); 130 1.1 mrg check24("13981013.0", "8388611.0", MPFR_RNDN, "117281279442944.0"); 131 1.1 mrg check24("11184811.0", "8388611.0", MPFR_RNDN, "93825028587520.0"); 132 1.1 mrg check24("11184810.0", "8388611.0", MPFR_RNDN, "93825020198912.0"); 133 1.1 mrg check24("13981014.0", "8388611.0", MPFR_RNDN, "117281287831552.0"); 134 1.1 mrg 135 1.1 mrg check24("8388609.0", "8388609.0", MPFR_RNDZ, "70368760954880.0"); 136 1.1 mrg check24("16777213.0", "8388609.0", MPFR_RNDZ, "140737471578112.0"); 137 1.1 mrg check24("8388611.0", "8388609.0", MPFR_RNDZ, "70368777732096.0"); 138 1.1 mrg check24("12582911.0", "8388610.0", MPFR_RNDZ, "105553124655104.0"); 139 1.1 mrg check24("12582914.0", "8388610.0", MPFR_RNDZ, "105553158209536.0"); 140 1.1 mrg check24("13981013.0", "8388611.0", MPFR_RNDZ, "117281271054336.0"); 141 1.1 mrg check24("11184811.0", "8388611.0", MPFR_RNDZ, "93825028587520.0"); 142 1.1 mrg check24("11184810.0", "8388611.0", MPFR_RNDZ, "93825011810304.0"); 143 1.1 mrg check24("13981014.0", "8388611.0", MPFR_RNDZ, "117281287831552.0"); 144 1.1 mrg 145 1.1 mrg check24("8388609.0", "8388609.0", MPFR_RNDU, "70368769343488.0"); 146 1.1 mrg check24("16777213.0", "8388609.0", MPFR_RNDU, "140737479966720.0"); 147 1.1 mrg check24("8388611.0", "8388609.0", MPFR_RNDU, "70368786120704.0"); 148 1.1 mrg check24("12582911.0", "8388610.0", MPFR_RNDU, "105553133043712.0"); 149 1.1 mrg check24("12582914.0", "8388610.0", MPFR_RNDU, "105553166598144.0"); 150 1.1 mrg check24("13981013.0", "8388611.0", MPFR_RNDU, "117281279442944.0"); 151 1.1 mrg check24("11184811.0", "8388611.0", MPFR_RNDU, "93825036976128.0"); 152 1.1 mrg check24("11184810.0", "8388611.0", MPFR_RNDU, "93825020198912.0"); 153 1.1 mrg check24("13981014.0", "8388611.0", MPFR_RNDU, "117281296220160.0"); 154 1.1 mrg 155 1.1 mrg check24("8388609.0", "8388609.0", MPFR_RNDD, "70368760954880.0"); 156 1.1 mrg check24("16777213.0", "8388609.0", MPFR_RNDD, "140737471578112.0"); 157 1.1 mrg check24("8388611.0", "8388609.0", MPFR_RNDD, "70368777732096.0"); 158 1.1 mrg check24("12582911.0", "8388610.0", MPFR_RNDD, "105553124655104.0"); 159 1.1 mrg check24("12582914.0", "8388610.0", MPFR_RNDD, "105553158209536.0"); 160 1.1 mrg check24("13981013.0", "8388611.0", MPFR_RNDD, "117281271054336.0"); 161 1.1 mrg check24("11184811.0", "8388611.0", MPFR_RNDD, "93825028587520.0"); 162 1.1 mrg check24("11184810.0", "8388611.0", MPFR_RNDD, "93825011810304.0"); 163 1.1 mrg check24("13981014.0", "8388611.0", MPFR_RNDD, "117281287831552.0"); 164 1.1 mrg } 165 1.1 mrg 166 1.1 mrg /* check sign of result */ 167 1.1 mrg static void 168 1.1 mrg check_sign (void) 169 1.1 mrg { 170 1.1 mrg mpfr_t a, b; 171 1.1 mrg 172 1.1 mrg mpfr_init2 (a, 53); 173 1.1 mrg mpfr_init2 (b, 53); 174 1.1 mrg mpfr_set_si (a, -1, MPFR_RNDN); 175 1.1 mrg mpfr_set_ui (b, 2, MPFR_RNDN); 176 1.1 mrg test_mul(a, b, b, MPFR_RNDN); 177 1.1 mrg if (mpfr_cmp_ui (a, 4) ) 178 1.1 mrg { 179 1.1 mrg printf ("2.0*2.0 gives \n"); 180 1.1.1.4 mrg mpfr_out_str (stdout, 10, 0, a, MPFR_RNDN); 181 1.1.1.4 mrg putchar ('\n'); 182 1.1 mrg exit (1); 183 1.1 mrg } 184 1.1 mrg mpfr_clear(a); mpfr_clear(b); 185 1.1 mrg } 186 1.1 mrg 187 1.1 mrg /* checks that the inexact return value is correct */ 188 1.1 mrg static void 189 1.1 mrg check_exact (void) 190 1.1 mrg { 191 1.1 mrg mpfr_t a, b, c, d; 192 1.1 mrg mpfr_prec_t prec; 193 1.1 mrg int i, inexact; 194 1.1 mrg mpfr_rnd_t rnd; 195 1.1 mrg 196 1.1 mrg mpfr_init (a); 197 1.1 mrg mpfr_init (b); 198 1.1 mrg mpfr_init (c); 199 1.1 mrg mpfr_init (d); 200 1.1 mrg 201 1.1 mrg mpfr_set_prec (a, 17); 202 1.1 mrg mpfr_set_prec (b, 17); 203 1.1 mrg mpfr_set_prec (c, 32); 204 1.1 mrg mpfr_set_str_binary (a, "1.1000111011000100e-1"); 205 1.1 mrg mpfr_set_str_binary (b, "1.0010001111100111e-1"); 206 1.1 mrg if (test_mul (c, a, b, MPFR_RNDZ)) 207 1.1 mrg { 208 1.1 mrg printf ("wrong return value (1)\n"); 209 1.1 mrg exit (1); 210 1.1 mrg } 211 1.1 mrg 212 1.1.1.4 mrg for (prec = MPFR_PREC_MIN; prec < 100; prec++) 213 1.1 mrg { 214 1.1 mrg mpfr_set_prec (a, prec); 215 1.1 mrg mpfr_set_prec (b, prec); 216 1.1.1.4 mrg /* for prec=1, ensure PREC(c) >= 1 */ 217 1.1.1.4 mrg mpfr_set_prec (c, 2 * prec - 2 + (prec == 1)); 218 1.1 mrg mpfr_set_prec (d, 2 * prec); 219 1.1 mrg for (i = 0; i < 1000; i++) 220 1.1 mrg { 221 1.1 mrg mpfr_urandomb (a, RANDS); 222 1.1 mrg mpfr_urandomb (b, RANDS); 223 1.1 mrg rnd = RND_RAND (); 224 1.1 mrg inexact = test_mul (c, a, b, rnd); 225 1.1 mrg if (test_mul (d, a, b, rnd)) /* should be always exact */ 226 1.1 mrg { 227 1.1 mrg printf ("unexpected inexact return value\n"); 228 1.1 mrg exit (1); 229 1.1 mrg } 230 1.1.1.4 mrg if ((inexact == 0) && mpfr_cmp (c, d) && rnd != MPFR_RNDF) 231 1.1 mrg { 232 1.1.1.4 mrg printf ("rnd=%s: inexact=0 but results differ\n", 233 1.1.1.4 mrg mpfr_print_rnd_mode (rnd)); 234 1.1.1.4 mrg printf ("a="); 235 1.1.1.4 mrg mpfr_out_str (stdout, 2, 0, a, rnd); 236 1.1.1.4 mrg printf ("\nb="); 237 1.1.1.4 mrg mpfr_out_str (stdout, 2, 0, b, rnd); 238 1.1.1.4 mrg printf ("\nc="); 239 1.1.1.4 mrg mpfr_out_str (stdout, 2, 0, c, rnd); 240 1.1.1.4 mrg printf ("\nd="); 241 1.1.1.4 mrg mpfr_out_str (stdout, 2, 0, d, rnd); 242 1.1.1.4 mrg printf ("\n"); 243 1.1 mrg exit (1); 244 1.1 mrg } 245 1.1.1.4 mrg else if (inexact && (mpfr_cmp (c, d) == 0) && rnd != MPFR_RNDF) 246 1.1 mrg { 247 1.1 mrg printf ("inexact!=0 but results agree\n"); 248 1.1 mrg printf ("prec=%u rnd=%s a=", (unsigned int) prec, 249 1.1 mrg mpfr_print_rnd_mode (rnd)); 250 1.1 mrg mpfr_out_str (stdout, 2, 0, a, rnd); 251 1.1 mrg printf ("\nb="); 252 1.1 mrg mpfr_out_str (stdout, 2, 0, b, rnd); 253 1.1 mrg printf ("\nc="); 254 1.1 mrg mpfr_out_str (stdout, 2, 0, c, rnd); 255 1.1 mrg printf ("\nd="); 256 1.1 mrg mpfr_out_str (stdout, 2, 0, d, rnd); 257 1.1 mrg printf ("\n"); 258 1.1 mrg exit (1); 259 1.1 mrg } 260 1.1 mrg } 261 1.1 mrg } 262 1.1 mrg 263 1.1 mrg mpfr_clear (a); 264 1.1 mrg mpfr_clear (b); 265 1.1 mrg mpfr_clear (c); 266 1.1 mrg mpfr_clear (d); 267 1.1 mrg } 268 1.1 mrg 269 1.1 mrg static void 270 1.1.1.5 mrg check_max (void) 271 1.1 mrg { 272 1.1 mrg mpfr_t xx, yy, zz; 273 1.1 mrg mpfr_exp_t emin; 274 1.1.1.5 mrg int inex; 275 1.1 mrg 276 1.1 mrg mpfr_init2(xx, 4); 277 1.1 mrg mpfr_init2(yy, 4); 278 1.1 mrg mpfr_init2(zz, 4); 279 1.1 mrg mpfr_set_str1 (xx, "0.68750"); 280 1.1 mrg mpfr_mul_2si(xx, xx, MPFR_EMAX_DEFAULT/2, MPFR_RNDN); 281 1.1 mrg mpfr_set_str1 (yy, "0.68750"); 282 1.1 mrg mpfr_mul_2si(yy, yy, MPFR_EMAX_DEFAULT - MPFR_EMAX_DEFAULT/2 + 1, MPFR_RNDN); 283 1.1 mrg mpfr_clear_flags(); 284 1.1 mrg test_mul(zz, xx, yy, MPFR_RNDU); 285 1.1 mrg if (!(mpfr_overflow_p() && MPFR_IS_INF(zz))) 286 1.1 mrg { 287 1.1 mrg printf("check_max failed (should be an overflow)\n"); 288 1.1 mrg exit(1); 289 1.1 mrg } 290 1.1 mrg 291 1.1 mrg mpfr_clear_flags(); 292 1.1 mrg test_mul(zz, xx, yy, MPFR_RNDD); 293 1.1 mrg if (mpfr_overflow_p() || MPFR_IS_INF(zz)) 294 1.1 mrg { 295 1.1 mrg printf("check_max failed (should NOT be an overflow)\n"); 296 1.1 mrg exit(1); 297 1.1 mrg } 298 1.1 mrg mpfr_set_str1 (xx, "0.93750"); 299 1.1 mrg mpfr_mul_2si(xx, xx, MPFR_EMAX_DEFAULT, MPFR_RNDN); 300 1.1 mrg if (!(MPFR_IS_FP(xx) && MPFR_IS_FP(zz))) 301 1.1 mrg { 302 1.1 mrg printf("check_max failed (internal error)\n"); 303 1.1 mrg exit(1); 304 1.1 mrg } 305 1.1 mrg if (mpfr_cmp(xx, zz) != 0) 306 1.1 mrg { 307 1.1 mrg printf("check_max failed: got "); 308 1.1 mrg mpfr_out_str(stdout, 2, 0, zz, MPFR_RNDZ); 309 1.1 mrg printf(" instead of "); 310 1.1 mrg mpfr_out_str(stdout, 2, 0, xx, MPFR_RNDZ); 311 1.1 mrg printf("\n"); 312 1.1 mrg exit(1); 313 1.1 mrg } 314 1.1 mrg 315 1.1 mrg /* check underflow */ 316 1.1 mrg emin = mpfr_get_emin (); 317 1.1 mrg set_emin (0); 318 1.1 mrg mpfr_set_str_binary (xx, "0.1E0"); 319 1.1 mrg mpfr_set_str_binary (yy, "0.1E0"); 320 1.1 mrg test_mul (zz, xx, yy, MPFR_RNDN); 321 1.1 mrg /* exact result is 0.1E-1, which should round to 0 */ 322 1.1 mrg MPFR_ASSERTN(mpfr_cmp_ui (zz, 0) == 0 && MPFR_IS_POS(zz)); 323 1.1 mrg set_emin (emin); 324 1.1 mrg 325 1.1 mrg /* coverage test for mpfr_powerof2_raw */ 326 1.1 mrg emin = mpfr_get_emin (); 327 1.1 mrg set_emin (0); 328 1.1 mrg mpfr_set_prec (xx, mp_bits_per_limb + 1); 329 1.1 mrg mpfr_set_str_binary (xx, "0.1E0"); 330 1.1 mrg mpfr_nextabove (xx); 331 1.1 mrg mpfr_set_str_binary (yy, "0.1E0"); 332 1.1 mrg test_mul (zz, xx, yy, MPFR_RNDN); 333 1.1 mrg /* exact result is just above 0.1E-1, which should round to minfloat */ 334 1.1 mrg MPFR_ASSERTN(mpfr_cmp (zz, yy) == 0); 335 1.1 mrg set_emin (emin); 336 1.1 mrg 337 1.1.1.5 mrg /* coverage test for mulders.c, case n > MUL_FFT_THRESHOLD */ 338 1.1.1.5 mrg mpfr_set_prec (xx, (MUL_FFT_THRESHOLD + 1) * GMP_NUMB_BITS); 339 1.1.1.5 mrg mpfr_set_prec (yy, (MUL_FFT_THRESHOLD + 1) * GMP_NUMB_BITS); 340 1.1.1.5 mrg mpfr_set_prec (zz, (MUL_FFT_THRESHOLD + 1) * GMP_NUMB_BITS); 341 1.1.1.5 mrg mpfr_set_ui (xx, 1, MPFR_RNDN); 342 1.1.1.5 mrg mpfr_nextbelow (xx); 343 1.1.1.5 mrg mpfr_set_ui (yy, 1, MPFR_RNDN); 344 1.1.1.5 mrg mpfr_nextabove (yy); 345 1.1.1.5 mrg /* xx = 1 - 2^(-p), yy = 1 + 2^(1-p), where p = PREC(x), 346 1.1.1.5 mrg thus xx * yy should be rounded to 1 */ 347 1.1.1.5 mrg inex = mpfr_mul (zz, xx, yy, MPFR_RNDN); 348 1.1.1.5 mrg MPFR_ASSERTN(inex < 0); 349 1.1.1.5 mrg MPFR_ASSERTN(mpfr_cmp_ui (zz, 1) == 0); 350 1.1.1.5 mrg 351 1.1 mrg mpfr_clear(xx); 352 1.1 mrg mpfr_clear(yy); 353 1.1 mrg mpfr_clear(zz); 354 1.1 mrg } 355 1.1 mrg 356 1.1 mrg static void 357 1.1 mrg check_min(void) 358 1.1 mrg { 359 1.1 mrg mpfr_t xx, yy, zz; 360 1.1 mrg 361 1.1 mrg mpfr_init2(xx, 4); 362 1.1 mrg mpfr_init2(yy, 4); 363 1.1 mrg mpfr_init2(zz, 3); 364 1.1 mrg mpfr_set_str1(xx, "0.9375"); 365 1.1 mrg mpfr_mul_2si(xx, xx, MPFR_EMIN_DEFAULT/2, MPFR_RNDN); 366 1.1 mrg mpfr_set_str1(yy, "0.9375"); 367 1.1 mrg mpfr_mul_2si(yy, yy, MPFR_EMIN_DEFAULT - MPFR_EMIN_DEFAULT/2 - 1, MPFR_RNDN); 368 1.1 mrg test_mul(zz, xx, yy, MPFR_RNDD); 369 1.1.1.4 mrg if (MPFR_NOTZERO (zz)) 370 1.1 mrg { 371 1.1 mrg printf("check_min failed: got "); 372 1.1 mrg mpfr_out_str(stdout, 2, 0, zz, MPFR_RNDZ); 373 1.1 mrg printf(" instead of 0\n"); 374 1.1 mrg exit(1); 375 1.1 mrg } 376 1.1 mrg 377 1.1 mrg test_mul(zz, xx, yy, MPFR_RNDU); 378 1.1 mrg mpfr_set_str1 (xx, "0.5"); 379 1.1 mrg mpfr_mul_2si(xx, xx, MPFR_EMIN_DEFAULT, MPFR_RNDN); 380 1.1 mrg if (mpfr_sgn(xx) <= 0) 381 1.1 mrg { 382 1.1 mrg printf("check_min failed (internal error)\n"); 383 1.1 mrg exit(1); 384 1.1 mrg } 385 1.1 mrg if (mpfr_cmp(xx, zz) != 0) 386 1.1 mrg { 387 1.1 mrg printf("check_min failed: got "); 388 1.1 mrg mpfr_out_str(stdout, 2, 0, zz, MPFR_RNDZ); 389 1.1 mrg printf(" instead of "); 390 1.1 mrg mpfr_out_str(stdout, 2, 0, xx, MPFR_RNDZ); 391 1.1 mrg printf("\n"); 392 1.1 mrg exit(1); 393 1.1 mrg } 394 1.1 mrg 395 1.1 mrg mpfr_clear(xx); 396 1.1 mrg mpfr_clear(yy); 397 1.1 mrg mpfr_clear(zz); 398 1.1 mrg } 399 1.1 mrg 400 1.1 mrg static void 401 1.1 mrg check_nans (void) 402 1.1 mrg { 403 1.1 mrg mpfr_t p, x, y; 404 1.1 mrg 405 1.1 mrg mpfr_init2 (x, 123L); 406 1.1 mrg mpfr_init2 (y, 123L); 407 1.1 mrg mpfr_init2 (p, 123L); 408 1.1 mrg 409 1.1 mrg /* nan * 0 == nan */ 410 1.1 mrg mpfr_set_nan (x); 411 1.1 mrg mpfr_set_ui (y, 0L, MPFR_RNDN); 412 1.1 mrg test_mul (p, x, y, MPFR_RNDN); 413 1.1 mrg MPFR_ASSERTN (mpfr_nan_p (p)); 414 1.1 mrg 415 1.1 mrg /* 1 * nan == nan */ 416 1.1 mrg mpfr_set_ui (x, 1L, MPFR_RNDN); 417 1.1 mrg mpfr_set_nan (y); 418 1.1 mrg test_mul (p, x, y, MPFR_RNDN); 419 1.1 mrg MPFR_ASSERTN (mpfr_nan_p (p)); 420 1.1 mrg 421 1.1 mrg /* 0 * +inf == nan */ 422 1.1 mrg mpfr_set_ui (x, 0L, MPFR_RNDN); 423 1.1 mrg mpfr_set_nan (y); 424 1.1 mrg test_mul (p, x, y, MPFR_RNDN); 425 1.1 mrg MPFR_ASSERTN (mpfr_nan_p (p)); 426 1.1 mrg 427 1.1 mrg /* +1 * +inf == +inf */ 428 1.1 mrg mpfr_set_ui (x, 1L, MPFR_RNDN); 429 1.1 mrg mpfr_set_inf (y, 1); 430 1.1 mrg test_mul (p, x, y, MPFR_RNDN); 431 1.1 mrg MPFR_ASSERTN (mpfr_inf_p (p)); 432 1.1 mrg MPFR_ASSERTN (mpfr_sgn (p) > 0); 433 1.1 mrg 434 1.1 mrg /* -1 * +inf == -inf */ 435 1.1 mrg mpfr_set_si (x, -1L, MPFR_RNDN); 436 1.1 mrg mpfr_set_inf (y, 1); 437 1.1 mrg test_mul (p, x, y, MPFR_RNDN); 438 1.1 mrg MPFR_ASSERTN (mpfr_inf_p (p)); 439 1.1 mrg MPFR_ASSERTN (mpfr_sgn (p) < 0); 440 1.1 mrg 441 1.1 mrg mpfr_clear (x); 442 1.1 mrg mpfr_clear (y); 443 1.1 mrg mpfr_clear (p); 444 1.1 mrg } 445 1.1 mrg 446 1.1 mrg #define BUFSIZE 1552 447 1.1 mrg 448 1.1 mrg static void 449 1.1 mrg get_string (char *s, FILE *fp) 450 1.1 mrg { 451 1.1 mrg int c, n = BUFSIZE; 452 1.1 mrg 453 1.1 mrg while ((c = getc (fp)) != '\n') 454 1.1 mrg { 455 1.1 mrg if (c == EOF) 456 1.1 mrg { 457 1.1 mrg printf ("Error in get_string: end of file\n"); 458 1.1 mrg exit (1); 459 1.1 mrg } 460 1.1 mrg *(unsigned char *)s++ = c; 461 1.1 mrg if (--n == 0) 462 1.1 mrg { 463 1.1 mrg printf ("Error in get_string: buffer is too small\n"); 464 1.1 mrg exit (1); 465 1.1 mrg } 466 1.1 mrg } 467 1.1 mrg *s = '\0'; 468 1.1 mrg } 469 1.1 mrg 470 1.1 mrg static void 471 1.1 mrg check_regression (void) 472 1.1 mrg { 473 1.1 mrg mpfr_t x, y, z; 474 1.1 mrg int i; 475 1.1 mrg FILE *fp; 476 1.1 mrg char s[BUFSIZE]; 477 1.1 mrg 478 1.1 mrg mpfr_inits2 (6177, x, y, z, (mpfr_ptr) 0); 479 1.1 mrg /* we read long strings from a file since ISO C90 does not support strings of 480 1.1 mrg length > 509 */ 481 1.1 mrg fp = src_fopen ("tmul.dat", "r"); 482 1.1 mrg if (fp == NULL) 483 1.1 mrg { 484 1.1 mrg fprintf (stderr, "Error, cannot open tmul.dat in srcdir\n"); 485 1.1 mrg exit (1); 486 1.1 mrg } 487 1.1 mrg get_string (s, fp); 488 1.1 mrg mpfr_set_str (y, s, 16, MPFR_RNDN); 489 1.1 mrg get_string (s, fp); 490 1.1 mrg mpfr_set_str (z, s, 16, MPFR_RNDN); 491 1.1 mrg i = mpfr_mul (x, y, z, MPFR_RNDN); 492 1.1 mrg get_string (s, fp); 493 1.1 mrg if (mpfr_cmp_str (x, s, 16, MPFR_RNDN) != 0 || i != -1) 494 1.1 mrg { 495 1.1 mrg printf ("Regression test 1 failed (i=%d, expected -1)\nx=", i); 496 1.1 mrg mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); putchar ('\n'); 497 1.1 mrg exit (1); 498 1.1 mrg } 499 1.1 mrg fclose (fp); 500 1.1 mrg 501 1.1 mrg mpfr_set_prec (x, 606); 502 1.1 mrg mpfr_set_prec (y, 606); 503 1.1 mrg mpfr_set_prec (z, 606); 504 1.1 mrg 505 1.1 mrg mpfr_set_str (y, "-f.ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff92daefc3f8052ca9f58736564d9e93e62d324@-1", 16, MPFR_RNDN); 506 1.1 mrg mpfr_set_str (z, "-f.ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff92daefc3f8052ca9f58736564d9e93e62d324@-1", 16, MPFR_RNDN); 507 1.1 mrg i = mpfr_mul (x, y, z, MPFR_RNDU); 508 1.1 mrg mpfr_set_str (y, "f.ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff25b5df87f00a5953eb0e6cac9b3d27cc5a64c@-1", 16, MPFR_RNDN); 509 1.1 mrg if (mpfr_cmp (x, y) || i <= 0) 510 1.1 mrg { 511 1.1 mrg printf ("Regression test (2) failed! (i=%d - Expected 1)\n", i); 512 1.1 mrg mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); putchar ('\n'); 513 1.1 mrg exit (1); 514 1.1 mrg } 515 1.1 mrg 516 1.1 mrg mpfr_set_prec (x, 184); 517 1.1 mrg mpfr_set_prec (y, 92); 518 1.1 mrg mpfr_set_prec (z, 1023); 519 1.1 mrg 520 1.1 mrg mpfr_set_str (y, "6.9b8c8498882770d8038c3b0@-1", 16, MPFR_RNDN); 521 1.1 mrg mpfr_set_str (z, "7.44e24b986e7fb296f1e936ce749fec3504cbf0d5ba769466b1c9f1578115efd5d29b4c79271191a920a99280c714d3a657ad6e3afbab77ffce9d697e9bb9110e26d676069afcea8b69f1d1541f2365042d80a97c21dcccd8ace4f1bb58b49922003e738e6f37bb82ef653cb2e87f763974e6ae50ae54e7724c38b80653e3289@255", 16, MPFR_RNDN); 522 1.1 mrg i = mpfr_mul (x, y, z, MPFR_RNDU); 523 1.1 mrg mpfr_set_prec (y, 184); 524 1.1 mrg mpfr_set_str (y, "3.0080038f2ac5054e3e71ccbb95f76aaab2221715025a28@255", 525 1.1 mrg 16, MPFR_RNDN); 526 1.1 mrg if (mpfr_cmp (x, y) || i <= 0) 527 1.1 mrg { 528 1.1 mrg printf ("Regression test (4) failed! (i=%d - expected 1)\n", i); 529 1.1 mrg printf ("Ref: 3.0080038f2ac5054e3e71ccbb95f76aaab2221715025a28@255\n" 530 1.1 mrg "Got: "); 531 1.1 mrg mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); 532 1.1 mrg printf ("\n"); 533 1.1 mrg exit (1); 534 1.1 mrg } 535 1.1 mrg 536 1.1 mrg mpfr_set_prec (x, 908); 537 1.1 mrg mpfr_set_prec (y, 908); 538 1.1 mrg mpfr_set_prec (z, 908); 539 1.1 mrg mpfr_set_str (y, "-f.fffffffffffffffffffffffffffffffffffffffffffffffffffffff" 540 1.1 mrg "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" 541 1.1 mrg "ffffffffffffffffffffffffffffffffffffffffffffffffffffff99be91f83ec6f0ed28a3d42" 542 1.1 mrg "e6e9a327230345ea6@-1", 16, MPFR_RNDN); 543 1.1 mrg mpfr_set_str (z, "-f.fffffffffffffffffffffffffffffffffffffffffffffffffffffff" 544 1.1 mrg "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" 545 1.1 mrg "ffffffffffffffffffffffffffffffffffffffffffffffffffffff99be91f83ec6f0ed28a3d42" 546 1.1 mrg "e6e9a327230345ea6@-1", 16, MPFR_RNDN); 547 1.1 mrg i = mpfr_mul (x, y, z, MPFR_RNDU); 548 1.1 mrg mpfr_set_str (y, "f.ffffffffffffffffffffffffffffffffffffffffffffffffffffffff" 549 1.1 mrg "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" 550 1.1 mrg "fffffffffffffffffffffffffffffffffffffffffffffffffffff337d23f07d8de1da5147a85c" 551 1.1 mrg "dd3464e46068bd4d@-1", 16, MPFR_RNDN); 552 1.1 mrg if (mpfr_cmp (x, y) || i <= 0) 553 1.1 mrg { 554 1.1 mrg printf ("Regression test (5) failed! (i=%d - expected 1)\n", i); 555 1.1 mrg mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); 556 1.1 mrg printf ("\n"); 557 1.1 mrg exit (1); 558 1.1 mrg } 559 1.1 mrg 560 1.1 mrg 561 1.1 mrg mpfr_set_prec (x, 50); 562 1.1 mrg mpfr_set_prec (y, 40); 563 1.1 mrg mpfr_set_prec (z, 53); 564 1.1 mrg mpfr_set_str (y, "4.1ffffffff8", 16, MPFR_RNDN); 565 1.1 mrg mpfr_set_str (z, "4.2000000ffe0000@-4", 16, MPFR_RNDN); 566 1.1 mrg i = mpfr_mul (x, y, z, MPFR_RNDN); 567 1.1 mrg if (mpfr_cmp_str (x, "1.104000041d6c0@-3", 16, MPFR_RNDN) != 0 568 1.1 mrg || i <= 0) 569 1.1 mrg { 570 1.1 mrg printf ("Regression test (6) failed! (i=%d - expected 1)\nx=", i); 571 1.1 mrg mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); 572 1.1 mrg printf ("\nMore prec="); 573 1.1 mrg mpfr_set_prec (x, 93); 574 1.1 mrg mpfr_mul (x, y, z, MPFR_RNDN); 575 1.1 mrg mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); 576 1.1 mrg printf ("\n"); 577 1.1 mrg exit (1); 578 1.1 mrg } 579 1.1 mrg 580 1.1 mrg mpfr_set_prec (x, 439); 581 1.1 mrg mpfr_set_prec (y, 393); 582 1.1 mrg mpfr_set_str (y, "-1.921fb54442d18469898cc51701b839a252049c1114cf98e804177d" 583 1.1 mrg "4c76273644a29410f31c6809bbdf2a33679a748636600", 584 1.1 mrg 16, MPFR_RNDN); 585 1.1.1.6 mrg /* the following call to mpfr_mul with identical arguments is intentional */ 586 1.1 mrg i = mpfr_mul (x, y, y, MPFR_RNDU); 587 1.1 mrg if (mpfr_cmp_str (x, "2.77a79937c8bbcb495b89b36602306b1c2159a8ff834288a19a08" 588 1.1 mrg "84094f1cda3dc426da61174c4544a173de83c2500f8bfea2e0569e3698", 589 1.1 mrg 16, MPFR_RNDN) != 0 590 1.1 mrg || i <= 0) 591 1.1 mrg { 592 1.1 mrg printf ("Regression test (7) failed! (i=%d - expected 1)\nx=", i); 593 1.1 mrg mpfr_out_str (stdout, 16, 0, x, MPFR_RNDN); 594 1.1 mrg printf ("\n"); 595 1.1 mrg exit (1); 596 1.1 mrg } 597 1.1 mrg 598 1.1 mrg mpfr_set_prec (x, 1023); 599 1.1 mrg mpfr_set_prec (y, 1023); 600 1.1 mrg mpfr_set_prec (z, 511); 601 1.1 mrg mpfr_set_ui (x, 17, MPFR_RNDN); 602 1.1 mrg mpfr_set_ui (y, 42, MPFR_RNDN); 603 1.1 mrg i = mpfr_mul (z, x, y, MPFR_RNDN); 604 1.1 mrg if (mpfr_cmp_ui (z, 17*42) != 0 || i != 0) 605 1.1 mrg { 606 1.1 mrg printf ("Regression test (8) failed! (i=%d - expected 0)\nz=", i); 607 1.1 mrg mpfr_out_str (stdout, 16, 0, z, MPFR_RNDN); 608 1.1 mrg printf ("\n"); 609 1.1 mrg exit (1); 610 1.1 mrg } 611 1.1 mrg 612 1.1 mrg mpfr_clears (x, y, z, (mpfr_ptr) 0); 613 1.1 mrg } 614 1.1 mrg 615 1.1 mrg #define TEST_FUNCTION test_mul 616 1.1 mrg #define TWO_ARGS 617 1.1 mrg #define RAND_FUNCTION(x) mpfr_random2(x, MPFR_LIMB_SIZE (x), randlimb () % 100, RANDS) 618 1.1 mrg #include "tgeneric.c" 619 1.1 mrg 620 1.1 mrg /* multiplies x by 53-bit approximation of Pi */ 621 1.1 mrg static int 622 1.1 mrg mpfr_mulpi (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t r) 623 1.1 mrg { 624 1.1 mrg mpfr_t z; 625 1.1 mrg int inex; 626 1.1 mrg 627 1.1 mrg mpfr_init2 (z, 53); 628 1.1 mrg mpfr_set_str_binary (z, "11.001001000011111101101010100010001000010110100011"); 629 1.1 mrg inex = mpfr_mul (y, x, z, r); 630 1.1 mrg mpfr_clear (z); 631 1.1 mrg return inex; 632 1.1 mrg } 633 1.1 mrg 634 1.1.1.2 mrg static void 635 1.1.1.2 mrg valgrind20110503 (void) 636 1.1.1.2 mrg { 637 1.1.1.2 mrg mpfr_t a, b, c; 638 1.1.1.2 mrg 639 1.1.1.2 mrg mpfr_init2 (a, 2); 640 1.1.1.2 mrg mpfr_init2 (b, 2005); 641 1.1.1.2 mrg mpfr_init2 (c, 2); 642 1.1.1.2 mrg 643 1.1.1.2 mrg mpfr_set_ui (b, 5, MPFR_RNDN); 644 1.1.1.2 mrg mpfr_nextabove (b); 645 1.1.1.2 mrg mpfr_set_ui (c, 1, MPFR_RNDN); 646 1.1.1.2 mrg mpfr_mul (a, b, c, MPFR_RNDZ); 647 1.1.1.2 mrg /* After the call to mpfr_mulhigh_n, valgrind complains: 648 1.1.1.2 mrg Conditional jump or move depends on uninitialised value(s) */ 649 1.1.1.2 mrg 650 1.1.1.2 mrg mpfr_clears (a, b, c, (mpfr_ptr) 0); 651 1.1.1.2 mrg } 652 1.1.1.2 mrg 653 1.1.1.4 mrg static void 654 1.1.1.4 mrg testall_rndf (mpfr_prec_t pmax) 655 1.1.1.4 mrg { 656 1.1.1.4 mrg mpfr_t a, b, c, d; 657 1.1.1.4 mrg mpfr_prec_t pa, pb, pc; 658 1.1.1.4 mrg 659 1.1.1.4 mrg for (pa = MPFR_PREC_MIN; pa <= pmax; pa++) 660 1.1.1.4 mrg { 661 1.1.1.4 mrg mpfr_init2 (a, pa); 662 1.1.1.4 mrg mpfr_init2 (d, pa); 663 1.1.1.4 mrg for (pb = MPFR_PREC_MIN; pb <= pmax; pb++) 664 1.1.1.4 mrg { 665 1.1.1.4 mrg mpfr_init2 (b, pb); 666 1.1.1.4 mrg mpfr_set_ui (b, 1, MPFR_RNDN); 667 1.1.1.4 mrg while (mpfr_cmp_ui (b, 2) < 0) 668 1.1.1.4 mrg { 669 1.1.1.4 mrg for (pc = MPFR_PREC_MIN; pc <= pmax; pc++) 670 1.1.1.4 mrg { 671 1.1.1.4 mrg mpfr_init2 (c, pc); 672 1.1.1.4 mrg mpfr_set_ui (c, 1, MPFR_RNDN); 673 1.1.1.4 mrg while (mpfr_cmp_ui (c, 2) < 0) 674 1.1.1.4 mrg { 675 1.1.1.4 mrg mpfr_mul (a, b, c, MPFR_RNDF); 676 1.1.1.4 mrg mpfr_mul (d, b, c, MPFR_RNDD); 677 1.1.1.4 mrg if (!mpfr_equal_p (a, d)) 678 1.1.1.4 mrg { 679 1.1.1.4 mrg mpfr_mul (d, b, c, MPFR_RNDU); 680 1.1.1.4 mrg if (!mpfr_equal_p (a, d)) 681 1.1.1.4 mrg { 682 1.1.1.4 mrg printf ("Error: mpfr_mul(a,b,c,RNDF) does not " 683 1.1.1.4 mrg "match RNDD/RNDU\n"); 684 1.1.1.4 mrg printf ("b="); mpfr_dump (b); 685 1.1.1.4 mrg printf ("c="); mpfr_dump (c); 686 1.1.1.4 mrg printf ("a="); mpfr_dump (a); 687 1.1.1.4 mrg exit (1); 688 1.1.1.4 mrg } 689 1.1.1.4 mrg } 690 1.1.1.4 mrg mpfr_nextabove (c); 691 1.1.1.4 mrg } 692 1.1.1.4 mrg mpfr_clear (c); 693 1.1.1.4 mrg } 694 1.1.1.4 mrg mpfr_nextabove (b); 695 1.1.1.4 mrg } 696 1.1.1.4 mrg mpfr_clear (b); 697 1.1.1.4 mrg } 698 1.1.1.4 mrg mpfr_clear (a); 699 1.1.1.4 mrg mpfr_clear (d); 700 1.1.1.4 mrg } 701 1.1.1.4 mrg } 702 1.1.1.4 mrg 703 1.1.1.3 mrg /* Check underflow flag corresponds to *after* rounding. 704 1.1.1.3 mrg * 705 1.1.1.3 mrg * More precisely, we want to test mpfr_mul on inputs b and c such that 706 1.1.1.3 mrg * EXP(b*c) < emin but EXP(round(b*c, p, rnd)) = emin. Thus an underflow 707 1.1.1.3 mrg * must not be generated. 708 1.1.1.3 mrg */ 709 1.1.1.3 mrg static void 710 1.1.1.3 mrg test_underflow (mpfr_prec_t pmax) 711 1.1.1.3 mrg { 712 1.1.1.3 mrg mpfr_exp_t emin; 713 1.1.1.3 mrg mpfr_prec_t p; 714 1.1.1.3 mrg mpfr_t a0, a, b, c; 715 1.1.1.3 mrg int inex; 716 1.1.1.3 mrg 717 1.1.1.3 mrg mpfr_init2 (a0, MPFR_PREC_MIN); 718 1.1.1.3 mrg emin = mpfr_get_emin (); 719 1.1.1.3 mrg mpfr_setmin (a0, emin); /* 0.5 * 2^emin */ 720 1.1.1.3 mrg 721 1.1.1.3 mrg /* for RNDN, we want b*c < 0.5 * 2^emin but RNDN(b*c, p) = 0.5 * 2^emin, 722 1.1.1.3 mrg thus b*c >= (0.5 - 1/4 * ulp_p(0.5)) * 2^emin */ 723 1.1.1.3 mrg for (p = MPFR_PREC_MIN; p <= pmax; p++) 724 1.1.1.3 mrg { 725 1.1.1.3 mrg mpfr_init2 (a, p + 1); 726 1.1.1.3 mrg mpfr_init2 (b, p + 10); 727 1.1.1.3 mrg mpfr_init2 (c, p + 10); 728 1.1.1.3 mrg do mpfr_urandomb (b, RANDS); while (MPFR_IS_ZERO (b)); 729 1.1.1.3 mrg inex = mpfr_set_ui_2exp (a, 1, -1, MPFR_RNDZ); /* a = 0.5 */ 730 1.1.1.3 mrg MPFR_ASSERTN (inex == 0); 731 1.1.1.3 mrg mpfr_nextbelow (a); /* 0.5 - 1/2*ulp_{p+1}(0.5) = 0.5 - 1/4*ulp_p(0.5) */ 732 1.1.1.3 mrg inex = mpfr_div (c, a, b, MPFR_RNDU); 733 1.1.1.3 mrg /* 0.5 - 1/4 * ulp_p(0.5) = a <= b*c < 0.5 */ 734 1.1.1.3 mrg mpfr_mul_2si (b, b, emin / 2, MPFR_RNDZ); 735 1.1.1.3 mrg mpfr_mul_2si (c, c, (emin - 1) / 2, MPFR_RNDZ); 736 1.1.1.3 mrg /* now (0.5 - 1/4 * ulp_p(0.5)) * 2^emin <= b*c < 0.5 * 2^emin, 737 1.1.1.3 mrg thus b*c should be rounded to 0.5 * 2^emin */ 738 1.1.1.3 mrg mpfr_set_prec (a, p); 739 1.1.1.3 mrg mpfr_clear_underflow (); 740 1.1.1.3 mrg mpfr_mul (a, b, c, MPFR_RNDN); 741 1.1.1.3 mrg if (mpfr_underflow_p () || ! mpfr_equal_p (a, a0)) 742 1.1.1.3 mrg { 743 1.1.1.3 mrg printf ("Error, b*c incorrect or underflow flag incorrectly set" 744 1.1.1.3 mrg " for emin=%" MPFR_EXP_FSPEC "d, rnd=%s\n", 745 1.1.1.3 mrg (mpfr_eexp_t) emin, mpfr_print_rnd_mode (MPFR_RNDN)); 746 1.1.1.3 mrg printf ("b="); mpfr_dump (b); 747 1.1.1.3 mrg printf ("c="); mpfr_dump (c); 748 1.1.1.3 mrg printf ("a="); mpfr_dump (a); 749 1.1.1.3 mrg mpfr_set_prec (a, mpfr_get_prec (b) + mpfr_get_prec (c)); 750 1.1.1.5 mrg mpfr_mul_2ui (b, b, 1, MPFR_RNDN); 751 1.1.1.3 mrg inex = mpfr_mul (a, b, c, MPFR_RNDN); 752 1.1.1.3 mrg MPFR_ASSERTN (inex == 0); 753 1.1.1.3 mrg printf ("Exact 2*a="); mpfr_dump (a); 754 1.1.1.3 mrg exit (1); 755 1.1.1.3 mrg } 756 1.1.1.3 mrg mpfr_clear (a); 757 1.1.1.3 mrg mpfr_clear (b); 758 1.1.1.3 mrg mpfr_clear (c); 759 1.1.1.3 mrg } 760 1.1.1.3 mrg 761 1.1.1.3 mrg /* for RNDU, we want b*c < 0.5*2^emin but RNDU(b*c, p) = 0.5*2^emin thus 762 1.1.1.3 mrg b*c > (0.5 - 1/2 * ulp_p(0.5)) * 2^emin */ 763 1.1.1.3 mrg for (p = MPFR_PREC_MIN; p <= pmax; p++) 764 1.1.1.3 mrg { 765 1.1.1.3 mrg mpfr_init2 (a, p); 766 1.1.1.3 mrg mpfr_init2 (b, p + 10); 767 1.1.1.3 mrg mpfr_init2 (c, p + 10); 768 1.1.1.3 mrg do mpfr_urandomb (b, RANDS); while (MPFR_IS_ZERO (b)); 769 1.1.1.3 mrg inex = mpfr_set_ui_2exp (a, 1, -1, MPFR_RNDZ); /* a = 0.5 */ 770 1.1.1.3 mrg MPFR_ASSERTN (inex == 0); 771 1.1.1.3 mrg mpfr_nextbelow (a); /* 0.5 - 1/2 * ulp_p(0.5) */ 772 1.1.1.3 mrg inex = mpfr_div (c, a, b, MPFR_RNDU); 773 1.1.1.3 mrg /* 0.5 - 1/2 * ulp_p(0.5) <= b*c < 0.5 */ 774 1.1.1.3 mrg mpfr_mul_2si (b, b, emin / 2, MPFR_RNDZ); 775 1.1.1.3 mrg mpfr_mul_2si (c, c, (emin - 1) / 2, MPFR_RNDZ); 776 1.1.1.3 mrg if (inex == 0) 777 1.1.1.3 mrg mpfr_nextabove (c); /* ensures b*c > (0.5 - 1/2 * ulp_p(0.5)) * 2^emin. 778 1.1.1.3 mrg Warning: for p=1, 0.5 - 1/2 * ulp_p(0.5) 779 1.1.1.3 mrg = 0.25, thus b*c > 2^(emin-2), which should 780 1.1.1.3 mrg also be rounded up with p=1 to 0.5 * 2^emin 781 1.1.1.3 mrg with an unbounded exponent range. */ 782 1.1.1.3 mrg mpfr_clear_underflow (); 783 1.1.1.3 mrg mpfr_mul (a, b, c, MPFR_RNDU); 784 1.1.1.3 mrg if (mpfr_underflow_p () || ! mpfr_equal_p (a, a0)) 785 1.1.1.3 mrg { 786 1.1.1.3 mrg printf ("Error, b*c incorrect or underflow flag incorrectly set" 787 1.1.1.3 mrg " for emin=%" MPFR_EXP_FSPEC "d, rnd=%s\n", 788 1.1.1.3 mrg (mpfr_eexp_t) emin, mpfr_print_rnd_mode (MPFR_RNDU)); 789 1.1.1.3 mrg printf ("b="); mpfr_dump (b); 790 1.1.1.3 mrg printf ("c="); mpfr_dump (c); 791 1.1.1.3 mrg printf ("a="); mpfr_dump (a); 792 1.1.1.3 mrg mpfr_set_prec (a, mpfr_get_prec (b) + mpfr_get_prec (c)); 793 1.1.1.5 mrg mpfr_mul_2ui (b, b, 1, MPFR_RNDN); 794 1.1.1.3 mrg inex = mpfr_mul (a, b, c, MPFR_RNDN); 795 1.1.1.3 mrg MPFR_ASSERTN (inex == 0); 796 1.1.1.3 mrg printf ("Exact 2*a="); mpfr_dump (a); 797 1.1.1.3 mrg exit (1); 798 1.1.1.3 mrg } 799 1.1.1.3 mrg mpfr_clear (a); 800 1.1.1.3 mrg mpfr_clear (b); 801 1.1.1.3 mrg mpfr_clear (c); 802 1.1.1.3 mrg } 803 1.1.1.3 mrg 804 1.1.1.3 mrg mpfr_clear (a0); 805 1.1.1.3 mrg } 806 1.1.1.3 mrg 807 1.1.1.4 mrg /* checks special case where no underflow should occur */ 808 1.1.1.4 mrg static void 809 1.1.1.4 mrg bug20161209 (void) 810 1.1.1.4 mrg { 811 1.1.1.4 mrg mpfr_exp_t emin; 812 1.1.1.4 mrg mpfr_t x, y, z; 813 1.1.1.4 mrg 814 1.1.1.4 mrg emin = mpfr_get_emin (); 815 1.1.1.4 mrg set_emin (-1); 816 1.1.1.4 mrg 817 1.1.1.4 mrg /* test for mpfr_mul_1 for 64-bit limb, mpfr_mul_2 for 32-bit limb */ 818 1.1.1.4 mrg mpfr_init2 (x, 53); 819 1.1.1.4 mrg mpfr_init2 (y, 53); 820 1.1.1.4 mrg mpfr_init2 (z, 53); 821 1.1.1.4 mrg mpfr_set_str_binary (x, "0.101000001E-1"); /* x = 321/2^10 */ 822 1.1.1.4 mrg mpfr_set_str_binary (y, "0.110011000010100101111000011011000111011000001E-1"); 823 1.1.1.4 mrg /* y = 28059810762433/2^46 */ 824 1.1.1.4 mrg /* x * y = (2^53+1)/2^56 = 0.001...000[1]000..., and should round to 0.25 */ 825 1.1.1.4 mrg mpfr_mul (z, x, y, MPFR_RNDN); 826 1.1.1.4 mrg MPFR_ASSERTN(mpfr_cmp_ui_2exp (z, 1, -2) == 0); 827 1.1.1.4 mrg 828 1.1.1.4 mrg /* test for mpfr_mul_2 for 64-bit limb */ 829 1.1.1.4 mrg mpfr_set_prec (x, 65); 830 1.1.1.4 mrg mpfr_set_prec (y, 65); 831 1.1.1.4 mrg mpfr_set_prec (z, 65); 832 1.1.1.4 mrg mpfr_set_str_binary (x, "0.101101000010010110100001E-1"); /* 11806113/2^25 */ 833 1.1.1.4 mrg mpfr_set_str_binary (y, "0.101101011110010101011010001111111001100001E-1"); 834 1.1.1.4 mrg /* y = 3124947910241/2^43 */ 835 1.1.1.4 mrg /* x * y = (2^65+1)/2^68 = 0.001...000[1]000..., and should round to 0.25 */ 836 1.1.1.4 mrg mpfr_mul (z, x, y, MPFR_RNDN); 837 1.1.1.4 mrg MPFR_ASSERTN(mpfr_cmp_ui_2exp (z, 1, -2) == 0); 838 1.1.1.4 mrg 839 1.1.1.4 mrg /* test for the generic code */ 840 1.1.1.4 mrg mpfr_set_prec (x, 54); 841 1.1.1.4 mrg mpfr_set_prec (y, 55); 842 1.1.1.4 mrg mpfr_set_prec (z, 53); 843 1.1.1.4 mrg mpfr_set_str_binary (x, "0.101000001E-1"); 844 1.1.1.4 mrg mpfr_set_str_binary (y, "0.110011000010100101111000011011000111011000001E-1"); 845 1.1.1.4 mrg mpfr_mul (z, x, y, MPFR_RNDN); 846 1.1.1.4 mrg MPFR_ASSERTN(mpfr_cmp_ui_2exp (z, 1, -2) == 0); 847 1.1.1.4 mrg 848 1.1.1.4 mrg /* another test for the generic code */ 849 1.1.1.4 mrg mpfr_set_prec (x, 66); 850 1.1.1.4 mrg mpfr_set_prec (y, 67); 851 1.1.1.4 mrg mpfr_set_prec (z, 65); 852 1.1.1.4 mrg mpfr_set_str_binary (x, "0.101101000010010110100001E-1"); 853 1.1.1.4 mrg mpfr_set_str_binary (y, "0.101101011110010101011010001111111001100001E-1"); 854 1.1.1.4 mrg mpfr_mul (z, x, y, MPFR_RNDN); 855 1.1.1.4 mrg MPFR_ASSERTN(mpfr_cmp_ui_2exp (z, 1, -2) == 0); 856 1.1.1.4 mrg 857 1.1.1.4 mrg mpfr_clear (x); 858 1.1.1.4 mrg mpfr_clear (y); 859 1.1.1.4 mrg mpfr_clear (z); 860 1.1.1.4 mrg set_emin (emin); 861 1.1.1.4 mrg } 862 1.1.1.4 mrg 863 1.1.1.4 mrg /* test for case in mpfr_mul_1() where: 864 1.1.1.4 mrg ax = __gmpfr_emin - 1 865 1.1.1.4 mrg ap[0] == ~mask 866 1.1.1.4 mrg rnd_mode = MPFR_RNDZ. 867 1.1.1.4 mrg Whatever the values of rb and sb, we should round to zero (underflow). */ 868 1.1.1.4 mrg static void 869 1.1.1.4 mrg bug20161209a (void) 870 1.1.1.4 mrg { 871 1.1.1.4 mrg mpfr_exp_t emin; 872 1.1.1.4 mrg mpfr_t x, y, z; 873 1.1.1.4 mrg 874 1.1.1.4 mrg emin = mpfr_get_emin (); 875 1.1.1.4 mrg set_emin (-1); 876 1.1.1.4 mrg 877 1.1.1.4 mrg mpfr_init2 (x, 53); 878 1.1.1.4 mrg mpfr_init2 (y, 53); 879 1.1.1.4 mrg mpfr_init2 (z, 53); 880 1.1.1.4 mrg 881 1.1.1.4 mrg /* case rb = sb = 0 */ 882 1.1.1.4 mrg mpfr_set_str_binary (x, "0.11010010100110000110110011111E-1"); 883 1.1.1.4 mrg mpfr_set_str_binary (y, "0.1001101110011000110100001"); 884 1.1.1.4 mrg /* x = 441650591/2^30, y = 20394401/2^25 */ 885 1.1.1.4 mrg /* x * y = (2^53-1)/2^55 = 0.00111...111[0]000..., and should round to 0 */ 886 1.1.1.4 mrg mpfr_mul (z, x, y, MPFR_RNDZ); 887 1.1.1.4 mrg MPFR_ASSERTN(mpfr_zero_p (z)); 888 1.1.1.4 mrg 889 1.1.1.4 mrg /* case rb = 1, sb = 0 */ 890 1.1.1.4 mrg mpfr_set_str_binary (x, "0.111111111000000000000000000111111111E-1"); 891 1.1.1.4 mrg mpfr_set_str_binary (y, "0.1000000001000000001"); 892 1.1.1.4 mrg /* x = 68585259519/2^37, y = 262657/2^19 */ 893 1.1.1.4 mrg /* x * y = (2^54-1)/2^56 = 0.00111...111[1]000..., and should round to 0 */ 894 1.1.1.4 mrg mpfr_mul (z, x, y, MPFR_RNDZ); 895 1.1.1.4 mrg MPFR_ASSERTN(mpfr_zero_p (z)); 896 1.1.1.4 mrg 897 1.1.1.4 mrg /* case rb = 0, sb = 1 */ 898 1.1.1.4 mrg mpfr_set_str_binary (x, "0.110010011001011110001100100001000001E-1"); 899 1.1.1.4 mrg mpfr_set_str_binary (y, "0.10100010100010111101"); 900 1.1.1.4 mrg /* x = 541144371852^37, y = 665789/2^20 */ 901 1.1.1.4 mrg /* x * y = (2^55-3)/2^57 = 0.00111...111[0]100..., and should round to 0 */ 902 1.1.1.4 mrg mpfr_mul (z, x, y, MPFR_RNDZ); 903 1.1.1.4 mrg MPFR_ASSERTN(mpfr_zero_p (z)); 904 1.1.1.4 mrg 905 1.1.1.4 mrg /* case rb = sb = 1 */ 906 1.1.1.4 mrg mpfr_set_str_binary (x, "0.10100110001001001010001111110010100111E-1"); 907 1.1.1.4 mrg mpfr_set_str_binary (y, "0.110001010011101001"); 908 1.1.1.4 mrg /* x = 178394823847/2^39, y = 201961/2^18 */ 909 1.1.1.4 mrg /* x * y = (2^55-1)/2^57 = 0.00111...111[1]100..., and should round to 0 */ 910 1.1.1.4 mrg mpfr_mul (z, x, y, MPFR_RNDZ); 911 1.1.1.4 mrg MPFR_ASSERTN(mpfr_zero_p (z)); 912 1.1.1.4 mrg 913 1.1.1.4 mrg /* similar test for mpfr_mul_2 (we only check rb = sb = 1 here) */ 914 1.1.1.4 mrg mpfr_set_prec (x, 65); 915 1.1.1.4 mrg mpfr_set_prec (y, 65); 916 1.1.1.4 mrg mpfr_set_prec (z, 65); 917 1.1.1.4 mrg /* 2^67-1 = 193707721 * 761838257287 */ 918 1.1.1.4 mrg mpfr_set_str_binary (x, "0.1011100010111011111011001001E-1"); 919 1.1.1.4 mrg mpfr_set_str_binary (y, "0.1011000101100001000110010100010010000111"); 920 1.1.1.4 mrg mpfr_mul (z, x, y, MPFR_RNDZ); 921 1.1.1.4 mrg MPFR_ASSERTN(mpfr_zero_p (z)); 922 1.1.1.4 mrg 923 1.1.1.4 mrg mpfr_clear (x); 924 1.1.1.4 mrg mpfr_clear (y); 925 1.1.1.4 mrg mpfr_clear (z); 926 1.1.1.4 mrg set_emin (emin); 927 1.1.1.4 mrg } 928 1.1.1.4 mrg 929 1.1.1.4 mrg /* bug for RNDF */ 930 1.1.1.4 mrg static void 931 1.1.1.4 mrg bug20170602 (void) 932 1.1.1.4 mrg { 933 1.1.1.4 mrg mpfr_t x, u, y, yd, yu; 934 1.1.1.4 mrg 935 1.1.1.4 mrg mpfr_init2 (x, 493); 936 1.1.1.4 mrg mpfr_init2 (u, 493); 937 1.1.1.4 mrg mpfr_init2 (y, 503); 938 1.1.1.4 mrg mpfr_init2 (yd, 503); 939 1.1.1.4 mrg mpfr_init2 (yu, 503); 940 1.1.1.4 mrg mpfr_set_str_binary (x, "0.1111100000000000001111111110000000001111111111111000000000000000000011111111111111111111111000000000000000000001111111111111111111111111111111111111111000000000011111111111111111111000000000011111111111111000000000000001110000000000000000000000000000000000000000011111111111110011111111111100000000000000011111111111111111110000000011111111111111111110011111111111110000000000001111111111111111000000000000000000000000000000000000111111111111111111111111111111011111111111111111111111111111100E44"); 941 1.1.1.4 mrg mpfr_set_str_binary (u, "0.1110000000000000001111111111111111111111111111111111111000000000111111111111111111111111111111000000000000000000001111111000000000000000011111111111111111111111111111111111111111111111111111111000000000000000011111111111111000000011111111111111111110000000000000001111111111111111111111111111111111111110000000000001111111111111111111111111111111111111000000000000000000000000000000000001111111111111000000000000000000001111111111100000000000000011111111111111111111111111111111111111111111111E35"); 942 1.1.1.4 mrg mpfr_mul (y, x, u, MPFR_RNDF); 943 1.1.1.4 mrg mpfr_mul (yd, x, u, MPFR_RNDD); 944 1.1.1.4 mrg mpfr_mul (yu, x, u, MPFR_RNDU); 945 1.1.1.4 mrg if (mpfr_cmp (y, yd) != 0 && mpfr_cmp (y, yu) != 0) 946 1.1.1.4 mrg { 947 1.1.1.4 mrg printf ("RNDF is neither RNDD nor RNDU\n"); 948 1.1.1.4 mrg printf ("x"); mpfr_dump (x); 949 1.1.1.4 mrg printf ("u"); mpfr_dump (u); 950 1.1.1.4 mrg printf ("y(RNDF)="); mpfr_dump (y); 951 1.1.1.4 mrg printf ("y(RNDD)="); mpfr_dump (yd); 952 1.1.1.4 mrg printf ("y(RNDU)="); mpfr_dump (yu); 953 1.1.1.4 mrg exit (1); 954 1.1.1.4 mrg } 955 1.1.1.4 mrg mpfr_clear (x); 956 1.1.1.4 mrg mpfr_clear (u); 957 1.1.1.4 mrg mpfr_clear (y); 958 1.1.1.4 mrg mpfr_clear (yd); 959 1.1.1.4 mrg mpfr_clear (yu); 960 1.1.1.4 mrg } 961 1.1.1.4 mrg 962 1.1.1.4 mrg /* Test for 1 to 3 limbs. */ 963 1.1.1.4 mrg static void 964 1.1.1.4 mrg small_prec (void) 965 1.1.1.4 mrg { 966 1.1.1.4 mrg mpfr_exp_t emin, emax; 967 1.1.1.4 mrg mpfr_t x, y, z1, z2, zz; 968 1.1.1.4 mrg int xq, yq, zq; 969 1.1.1.4 mrg mpfr_rnd_t rnd; 970 1.1.1.4 mrg mpfr_flags_t flags1, flags2; 971 1.1.1.4 mrg int inex1, inex2; 972 1.1.1.4 mrg int i, j, r, s, ediff; 973 1.1.1.4 mrg 974 1.1.1.4 mrg emin = mpfr_get_emin (); 975 1.1.1.4 mrg emax = mpfr_get_emax (); 976 1.1.1.4 mrg 977 1.1.1.4 mrg /* The mpfr_mul implementation doesn't extend the exponent range, 978 1.1.1.4 mrg so that it is OK to reduce it here for the test to make sure that 979 1.1.1.4 mrg mpfr_mul_2si can be used. */ 980 1.1.1.4 mrg set_emin (-1000); 981 1.1.1.4 mrg set_emax (1000); 982 1.1.1.4 mrg 983 1.1.1.4 mrg mpfr_inits2 (3 * GMP_NUMB_BITS, x, y, z1, z2, (mpfr_ptr) 0); 984 1.1.1.4 mrg mpfr_init2 (zz, 6 * GMP_NUMB_BITS); 985 1.1.1.4 mrg for (i = 0; i < 3; i++) 986 1.1.1.4 mrg for (j = 0; j < 10000; j++) 987 1.1.1.4 mrg { 988 1.1.1.4 mrg xq = i * GMP_NUMB_BITS + 1 + randlimb () % GMP_NUMB_BITS; 989 1.1.1.4 mrg mpfr_set_prec (x, xq); 990 1.1.1.4 mrg yq = i * GMP_NUMB_BITS + 1 + randlimb () % GMP_NUMB_BITS; 991 1.1.1.4 mrg mpfr_set_prec (y, yq); 992 1.1.1.4 mrg zq = i * GMP_NUMB_BITS + 1 + randlimb () % (GMP_NUMB_BITS-1); 993 1.1.1.4 mrg mpfr_set_prec (z1, zq); 994 1.1.1.4 mrg mpfr_set_prec (z2, zq); 995 1.1.1.4 mrg s = r = randlimb () & 0x7f; 996 1.1.1.4 mrg do mpfr_urandomb (x, RANDS); while (mpfr_zero_p (x)); 997 1.1.1.4 mrg if (s & 1) 998 1.1.1.4 mrg mpfr_neg (x, x, MPFR_RNDN); 999 1.1.1.4 mrg s >>= 1; 1000 1.1.1.4 mrg if (s & 1) 1001 1.1.1.4 mrg { 1002 1.1.1.4 mrg do mpfr_urandomb (y, RANDS); while (mpfr_zero_p (y)); 1003 1.1.1.4 mrg } 1004 1.1.1.4 mrg else 1005 1.1.1.4 mrg { 1006 1.1.1.4 mrg mpfr_ui_div (y, 1, x, MPFR_RNDN); 1007 1.1.1.4 mrg mpfr_set_exp (y, 0); 1008 1.1.1.4 mrg } 1009 1.1.1.4 mrg s >>= 1; 1010 1.1.1.4 mrg if (s & 1) 1011 1.1.1.4 mrg mpfr_neg (y, y, MPFR_RNDN); 1012 1.1.1.4 mrg s >>= 1; 1013 1.1.1.4 mrg rnd = RND_RAND_NO_RNDF (); 1014 1.1.1.4 mrg inex1 = mpfr_mul (zz, x, y, MPFR_RNDN); 1015 1.1.1.4 mrg MPFR_ASSERTN (inex1 == 0); 1016 1.1.1.4 mrg if (s == 0) 1017 1.1.1.4 mrg { 1018 1.1.1.4 mrg ediff = __gmpfr_emin - MPFR_EXP (x); 1019 1.1.1.4 mrg mpfr_set_exp (x, __gmpfr_emin); 1020 1.1.1.4 mrg } 1021 1.1.1.4 mrg else if (s == 1) 1022 1.1.1.4 mrg { 1023 1.1.1.4 mrg ediff = __gmpfr_emax - MPFR_EXP (x) + 1; 1024 1.1.1.4 mrg mpfr_set_exp (x, __gmpfr_emax); 1025 1.1.1.4 mrg mpfr_mul_2ui (y, y, 1, MPFR_RNDN); 1026 1.1.1.4 mrg } 1027 1.1.1.4 mrg else 1028 1.1.1.4 mrg ediff = 0; 1029 1.1.1.4 mrg mpfr_clear_flags (); 1030 1.1.1.4 mrg inex1 = mpfr_mul_2si (z1, zz, ediff, rnd); 1031 1.1.1.4 mrg flags1 = __gmpfr_flags; 1032 1.1.1.4 mrg mpfr_clear_flags (); 1033 1.1.1.4 mrg inex2 = mpfr_mul (z2, x, y, rnd); 1034 1.1.1.4 mrg flags2 = __gmpfr_flags; 1035 1.1.1.4 mrg if (!(mpfr_equal_p (z1, z2) && 1036 1.1.1.5 mrg SAME_SIGN (inex1, inex2) 1037 1.1.1.5 mrg && flags1 == flags2 1038 1.1.1.5 mrg )) 1039 1.1.1.4 mrg { 1040 1.1.1.4 mrg printf ("Error in small_prec on i = %d, j = %d\n", i, j); 1041 1.1.1.4 mrg printf ("r = 0x%x, xq = %d, yq = %d, zq = %d, rnd = %s\n", 1042 1.1.1.4 mrg r, xq, yq, zq, mpfr_print_rnd_mode (rnd)); 1043 1.1.1.4 mrg printf ("x = "); 1044 1.1.1.4 mrg mpfr_dump (x); 1045 1.1.1.4 mrg printf ("y = "); 1046 1.1.1.4 mrg mpfr_dump (y); 1047 1.1.1.4 mrg printf ("ediff = %d\n", ediff); 1048 1.1.1.4 mrg printf ("zz = "); 1049 1.1.1.4 mrg mpfr_dump (zz); 1050 1.1.1.4 mrg printf ("Expected "); 1051 1.1.1.4 mrg mpfr_dump (z1); 1052 1.1.1.4 mrg printf ("with inex = %d and flags =", inex1); 1053 1.1.1.4 mrg flags_out (flags1); 1054 1.1.1.4 mrg printf ("Got "); 1055 1.1.1.4 mrg mpfr_dump (z2); 1056 1.1.1.4 mrg printf ("with inex = %d and flags =", inex2); 1057 1.1.1.4 mrg flags_out (flags2); 1058 1.1.1.4 mrg exit (1); 1059 1.1.1.4 mrg } 1060 1.1.1.4 mrg } 1061 1.1.1.4 mrg mpfr_clears (x, y, z1, z2, zz, (mpfr_ptr) 0); 1062 1.1.1.4 mrg 1063 1.1.1.4 mrg set_emin (emin); 1064 1.1.1.4 mrg set_emax (emax); 1065 1.1.1.4 mrg } 1066 1.1.1.4 mrg 1067 1.1.1.4 mrg /* check ax < __gmpfr_emin with rnd_mode == MPFR_RNDN, rb = 0 and sb <> 0 */ 1068 1.1.1.4 mrg static void 1069 1.1.1.4 mrg test_underflow2 (void) 1070 1.1.1.4 mrg { 1071 1.1.1.4 mrg mpfr_t x, y, z; 1072 1.1.1.4 mrg mpfr_exp_t emin; 1073 1.1.1.4 mrg 1074 1.1.1.4 mrg emin = mpfr_get_emin (); 1075 1.1.1.6 mrg set_emin (0); 1076 1.1.1.4 mrg 1077 1.1.1.4 mrg mpfr_init2 (x, 24); 1078 1.1.1.4 mrg mpfr_init2 (y, 24); 1079 1.1.1.4 mrg mpfr_init2 (z, 24); 1080 1.1.1.4 mrg 1081 1.1.1.4 mrg mpfr_set_ui_2exp (x, 12913, -14, MPFR_RNDN); 1082 1.1.1.4 mrg mpfr_set_ui_2exp (y, 5197, -13, MPFR_RNDN); 1083 1.1.1.4 mrg mpfr_clear_underflow (); 1084 1.1.1.4 mrg /* x*y = 0.0111111111111111111111111[01] thus underflow */ 1085 1.1.1.4 mrg mpfr_mul (z, y, x, MPFR_RNDN); 1086 1.1.1.4 mrg MPFR_ASSERTN(mpfr_cmp_ui_2exp (z, 1, -1) == 0); 1087 1.1.1.4 mrg MPFR_ASSERTN(mpfr_underflow_p ()); 1088 1.1.1.4 mrg 1089 1.1.1.4 mrg mpfr_set_prec (x, 65); 1090 1.1.1.4 mrg mpfr_set_prec (y, 65); 1091 1.1.1.4 mrg mpfr_set_prec (z, 65); 1092 1.1.1.4 mrg mpfr_set_str_binary (x, "0.10011101000110111011111100101001111"); 1093 1.1.1.4 mrg mpfr_set_str_binary (y, "0.110100001001000111000011011110011"); 1094 1.1.1.4 mrg mpfr_clear_underflow (); 1095 1.1.1.4 mrg /* x*y = 0.011111111111111111111111111111111111111111111111111111111111111111[01] thus underflow */ 1096 1.1.1.4 mrg mpfr_mul (z, y, x, MPFR_RNDN); 1097 1.1.1.4 mrg MPFR_ASSERTN(mpfr_cmp_ui_2exp (z, 1, -1) == 0); 1098 1.1.1.4 mrg MPFR_ASSERTN(mpfr_underflow_p ()); 1099 1.1.1.4 mrg 1100 1.1.1.4 mrg mpfr_clear (y); 1101 1.1.1.4 mrg mpfr_clear (x); 1102 1.1.1.4 mrg mpfr_clear (z); 1103 1.1.1.4 mrg 1104 1.1.1.6 mrg set_emin (emin); 1105 1.1.1.4 mrg } 1106 1.1.1.4 mrg 1107 1.1.1.5 mrg static void 1108 1.1.1.5 mrg coverage (mpfr_prec_t pmax) 1109 1.1.1.5 mrg { 1110 1.1.1.5 mrg mpfr_t a, b, c; 1111 1.1.1.5 mrg mpfr_prec_t p; 1112 1.1.1.5 mrg int inex; 1113 1.1.1.5 mrg 1114 1.1.1.5 mrg for (p = MPFR_PREC_MIN; p <= pmax; p++) 1115 1.1.1.5 mrg { 1116 1.1.1.5 mrg mpfr_init2 (a, p); 1117 1.1.1.5 mrg mpfr_init2 (b, p); 1118 1.1.1.5 mrg mpfr_init2 (c, p); 1119 1.1.1.5 mrg 1120 1.1.1.5 mrg /* exercise case b*c = 2^(emin-2), which is just in the middle 1121 1.1.1.5 mrg between 0 and the smallest positive number 0.5*2^emin */ 1122 1.1.1.5 mrg mpfr_set_ui_2exp (b, 1, mpfr_get_emin (), MPFR_RNDN); 1123 1.1.1.5 mrg mpfr_set_ui_2exp (c, 1, -2, MPFR_RNDN); 1124 1.1.1.5 mrg mpfr_clear_flags (); 1125 1.1.1.5 mrg inex = mpfr_mul (a, b, c, MPFR_RNDN); 1126 1.1.1.5 mrg MPFR_ASSERTN(inex < 0); 1127 1.1.1.5 mrg MPFR_ASSERTN(mpfr_zero_p (a) && mpfr_signbit (a) == 0); 1128 1.1.1.5 mrg MPFR_ASSERTN(mpfr_underflow_p ()); 1129 1.1.1.5 mrg 1130 1.1.1.5 mrg if (p == 1) 1131 1.1.1.5 mrg goto end_of_loop; 1132 1.1.1.5 mrg 1133 1.1.1.5 mrg /* case b*c > 2^(emin-2): b = (1-2^(-p))*2^emin, 1134 1.1.1.5 mrg c = 0.25*(1+2^(1-p)), thus b*c = (1+2^(-p)-2^(1-2p))*2^(emin-2) 1135 1.1.1.5 mrg should be rounded to 2^(emin-1) for RNDN */ 1136 1.1.1.5 mrg mpfr_nextbelow (b); 1137 1.1.1.5 mrg mpfr_nextabove (c); 1138 1.1.1.5 mrg mpfr_clear_flags (); 1139 1.1.1.5 mrg inex = mpfr_mul (a, b, c, MPFR_RNDN); 1140 1.1.1.5 mrg MPFR_ASSERTN(inex > 0); 1141 1.1.1.5 mrg MPFR_ASSERTN(mpfr_cmp_ui_2exp (a, 1, mpfr_get_emin () - 1) == 0); 1142 1.1.1.5 mrg MPFR_ASSERTN(mpfr_underflow_p ()); 1143 1.1.1.5 mrg 1144 1.1.1.5 mrg /* b = (1-2^(1-p))*2^emin, c = 0.25*(1+2^(1-p)), 1145 1.1.1.5 mrg thus b*c = (1-2^(2-2p))*2^(emin-2) should be rounded to 0 */ 1146 1.1.1.5 mrg mpfr_nextbelow (b); 1147 1.1.1.5 mrg mpfr_clear_flags (); 1148 1.1.1.5 mrg inex = mpfr_mul (a, b, c, MPFR_RNDN); 1149 1.1.1.5 mrg MPFR_ASSERTN(inex < 0); 1150 1.1.1.5 mrg MPFR_ASSERTN(mpfr_zero_p (a) && mpfr_signbit (a) == 0); 1151 1.1.1.5 mrg MPFR_ASSERTN(mpfr_underflow_p ()); 1152 1.1.1.5 mrg 1153 1.1.1.5 mrg /* special case where b*c is in [nextbelow(0.5*2^emin),0.5*2^emin[ */ 1154 1.1.1.5 mrg if ((p % 2) == 0) 1155 1.1.1.5 mrg { 1156 1.1.1.5 mrg /* the middle of the interval [nextbelow(0.5*2^emin),0.5*2^emin[ 1157 1.1.1.5 mrg is (1-2^(-p-1))*2^(emin-1) 1158 1.1.1.5 mrg = (1-2^(-p/2))*(1+2^(-p/2))*2^(emin-1) */ 1159 1.1.1.5 mrg mpfr_set_si_2exp (b, -1, -p/2, MPFR_RNDN); 1160 1.1.1.5 mrg mpfr_add_ui (b, b, 1, MPFR_RNDN); 1161 1.1.1.5 mrg mpfr_set_si_2exp (c, 1, -p/2, MPFR_RNDN); 1162 1.1.1.5 mrg mpfr_add_ui (c, c, 1, MPFR_RNDN); 1163 1.1.1.5 mrg MPFR_ASSERTN(mpfr_get_emin () < 0); 1164 1.1.1.5 mrg mpfr_mul_2si (b, b, (mpfr_get_emin () - 1) / 2, MPFR_RNDN); 1165 1.1.1.5 mrg mpfr_mul_2si (c, c, (mpfr_get_emin () - 2) / 2, MPFR_RNDN); 1166 1.1.1.5 mrg mpfr_clear_flags (); 1167 1.1.1.5 mrg inex = mpfr_mul (a, b, c, MPFR_RNDN); 1168 1.1.1.5 mrg MPFR_ASSERTN(inex > 0); 1169 1.1.1.5 mrg MPFR_ASSERTN(mpfr_cmp_ui_2exp (a, 1, mpfr_get_emin () - 1) == 0); 1170 1.1.1.5 mrg MPFR_ASSERTN(mpfr_underflow_p ()); 1171 1.1.1.5 mrg mpfr_clear_flags (); 1172 1.1.1.5 mrg inex = mpfr_mul (a, b, c, MPFR_RNDU); 1173 1.1.1.5 mrg MPFR_ASSERTN(inex > 0); 1174 1.1.1.5 mrg MPFR_ASSERTN(mpfr_cmp_ui_2exp (a, 1, mpfr_get_emin () - 1) == 0); 1175 1.1.1.5 mrg MPFR_ASSERTN(mpfr_underflow_p ()); 1176 1.1.1.5 mrg mpfr_clear_flags (); 1177 1.1.1.5 mrg inex = mpfr_mul (a, b, c, MPFR_RNDD); 1178 1.1.1.5 mrg MPFR_ASSERTN(inex < 0); 1179 1.1.1.5 mrg MPFR_ASSERTN(mpfr_zero_p (a) && mpfr_signbit (a) == 0); 1180 1.1.1.5 mrg MPFR_ASSERTN(mpfr_underflow_p ()); 1181 1.1.1.5 mrg } 1182 1.1.1.5 mrg else /* p is odd: 1183 1.1.1.5 mrg b = (1-2^(-(p+1)/2))*2^... 1184 1.1.1.5 mrg c = (1+2^(-(p+1)/2))*2^... */ 1185 1.1.1.5 mrg { 1186 1.1.1.5 mrg mpfr_set_si_2exp (b, -1, -(p+1)/2, MPFR_RNDN); 1187 1.1.1.5 mrg mpfr_add_ui (b, b, 1, MPFR_RNDN); 1188 1.1.1.5 mrg mpfr_set_si_2exp (c, 1, -(p+1)/2, MPFR_RNDN); 1189 1.1.1.5 mrg mpfr_add_ui (c, c, 1, MPFR_RNDN); 1190 1.1.1.5 mrg MPFR_ASSERTN(mpfr_get_emin () < 0); 1191 1.1.1.5 mrg mpfr_mul_2si (b, b, (mpfr_get_emin () - 1) / 2, MPFR_RNDN); 1192 1.1.1.5 mrg mpfr_mul_2si (c, c, (mpfr_get_emin () - 2) / 2, MPFR_RNDN); 1193 1.1.1.5 mrg mpfr_clear_flags (); 1194 1.1.1.5 mrg inex = mpfr_mul (a, b, c, MPFR_RNDN); 1195 1.1.1.5 mrg MPFR_ASSERTN(inex > 0); 1196 1.1.1.5 mrg MPFR_ASSERTN(mpfr_cmp_ui_2exp (a, 1, mpfr_get_emin () - 1) == 0); 1197 1.1.1.5 mrg MPFR_ASSERTN(!mpfr_underflow_p ()); 1198 1.1.1.5 mrg mpfr_clear_flags (); 1199 1.1.1.5 mrg inex = mpfr_mul (a, b, c, MPFR_RNDU); 1200 1.1.1.5 mrg MPFR_ASSERTN(inex > 0); 1201 1.1.1.5 mrg MPFR_ASSERTN(mpfr_cmp_ui_2exp (a, 1, mpfr_get_emin () - 1) == 0); 1202 1.1.1.5 mrg MPFR_ASSERTN(!mpfr_underflow_p ()); 1203 1.1.1.5 mrg mpfr_clear_flags (); 1204 1.1.1.5 mrg inex = mpfr_mul (a, b, c, MPFR_RNDD); 1205 1.1.1.5 mrg MPFR_ASSERTN(inex < 0); 1206 1.1.1.5 mrg MPFR_ASSERTN(mpfr_zero_p (a) && mpfr_signbit (a) == 0); 1207 1.1.1.5 mrg MPFR_ASSERTN(mpfr_underflow_p ()); 1208 1.1.1.5 mrg } 1209 1.1.1.5 mrg 1210 1.1.1.5 mrg if (p <= 2) /* for p=2, 1+2^(-ceil((p+1)/2)) = 1 + 2^(-2) is not 1211 1.1.1.5 mrg exactly representable */ 1212 1.1.1.5 mrg goto end_of_loop; 1213 1.1.1.5 mrg 1214 1.1.1.5 mrg /* b = 1-2^(-ceil((p+1)/2)) 1215 1.1.1.5 mrg c = 1+2^(-ceil((p+1)/2)) 1216 1.1.1.5 mrg For p odd, b*c = 1-2^(p+1) should round to 1; 1217 1.1.1.5 mrg for p even, b*c = 1-2^(p+2) should round to 1 too. */ 1218 1.1.1.5 mrg mpfr_set_si_2exp (b, -1, -(p+2)/2, MPFR_RNDN); 1219 1.1.1.5 mrg mpfr_add_ui (b, b, 1, MPFR_RNDN); 1220 1.1.1.5 mrg mpfr_set_si_2exp (c, 1, -(p+2)/2, MPFR_RNDN); 1221 1.1.1.5 mrg mpfr_add_ui (c, c, 1, MPFR_RNDN); 1222 1.1.1.5 mrg inex = mpfr_mul (a, b, c, MPFR_RNDN); 1223 1.1.1.5 mrg MPFR_ASSERTN(inex > 0); 1224 1.1.1.5 mrg MPFR_ASSERTN(mpfr_cmp_ui (a, 1) == 0); 1225 1.1.1.5 mrg /* For RNDU, b*c should round to 1 */ 1226 1.1.1.5 mrg inex = mpfr_mul (a, b, c, MPFR_RNDU); 1227 1.1.1.5 mrg MPFR_ASSERTN(inex > 0); 1228 1.1.1.5 mrg MPFR_ASSERTN(mpfr_cmp_ui (a, 1) == 0); 1229 1.1.1.5 mrg /* For RNDD, b*c should round to 1-2^(-p) */ 1230 1.1.1.5 mrg inex = mpfr_mul (a, b, c, MPFR_RNDD); 1231 1.1.1.5 mrg MPFR_ASSERTN(inex < 0); 1232 1.1.1.5 mrg mpfr_nextabove (a); 1233 1.1.1.5 mrg MPFR_ASSERTN(mpfr_cmp_ui (a, 1) == 0); 1234 1.1.1.5 mrg 1235 1.1.1.5 mrg /* same as above, but near emax, to exercise the case where a carry 1236 1.1.1.5 mrg produces an overflow */ 1237 1.1.1.5 mrg mpfr_set_si_2exp (b, -1, -(p+2)/2, MPFR_RNDN); 1238 1.1.1.5 mrg mpfr_add_ui (b, b, 1, MPFR_RNDN); 1239 1.1.1.5 mrg mpfr_mul_2si (b, b, mpfr_get_emax (), MPFR_RNDN); 1240 1.1.1.5 mrg mpfr_set_si_2exp (c, 1, -(p+2)/2, MPFR_RNDN); 1241 1.1.1.5 mrg mpfr_add_ui (c, c, 1, MPFR_RNDN); 1242 1.1.1.5 mrg /* b*c should round to 2^emax */ 1243 1.1.1.5 mrg mpfr_clear_flags (); 1244 1.1.1.5 mrg inex = mpfr_mul (a, b, c, MPFR_RNDN); 1245 1.1.1.5 mrg MPFR_ASSERTN(inex > 0); 1246 1.1.1.5 mrg MPFR_ASSERTN(mpfr_inf_p (a) && mpfr_sgn (a) > 0); 1247 1.1.1.5 mrg MPFR_ASSERTN(mpfr_overflow_p ()); 1248 1.1.1.5 mrg /* idem for RNDU */ 1249 1.1.1.5 mrg mpfr_clear_flags (); 1250 1.1.1.5 mrg inex = mpfr_mul (a, b, c, MPFR_RNDU); 1251 1.1.1.5 mrg MPFR_ASSERTN(inex > 0); 1252 1.1.1.5 mrg MPFR_ASSERTN(mpfr_inf_p (a) && mpfr_sgn (a) > 0); 1253 1.1.1.5 mrg MPFR_ASSERTN(mpfr_overflow_p ()); 1254 1.1.1.5 mrg /* For RNDD, b*c should round to (1-2^(-p))*2^emax */ 1255 1.1.1.5 mrg mpfr_clear_flags (); 1256 1.1.1.5 mrg inex = mpfr_mul (a, b, c, MPFR_RNDD); 1257 1.1.1.5 mrg MPFR_ASSERTN(inex < 0); 1258 1.1.1.5 mrg MPFR_ASSERTN(!mpfr_inf_p (a)); 1259 1.1.1.5 mrg MPFR_ASSERTN(!mpfr_overflow_p ()); 1260 1.1.1.5 mrg mpfr_nextabove (a); 1261 1.1.1.5 mrg MPFR_ASSERTN(mpfr_inf_p (a) && mpfr_sgn (a) > 0); 1262 1.1.1.5 mrg 1263 1.1.1.5 mrg end_of_loop: 1264 1.1.1.5 mrg mpfr_clear (a); 1265 1.1.1.5 mrg mpfr_clear (b); 1266 1.1.1.5 mrg mpfr_clear (c); 1267 1.1.1.5 mrg } 1268 1.1.1.5 mrg } 1269 1.1.1.5 mrg 1270 1.1.1.5 mrg /* check special underflow case for precision = 64 */ 1271 1.1.1.5 mrg static void 1272 1.1.1.5 mrg coverage2 (void) 1273 1.1.1.5 mrg { 1274 1.1.1.5 mrg mpfr_t a, b, c; 1275 1.1.1.5 mrg int inex; 1276 1.1.1.5 mrg mpfr_exp_t emin; 1277 1.1.1.5 mrg 1278 1.1.1.5 mrg emin = mpfr_get_emin (); /* save emin */ 1279 1.1.1.6 mrg set_emin (0); 1280 1.1.1.5 mrg 1281 1.1.1.5 mrg mpfr_init2 (a, 64); 1282 1.1.1.5 mrg mpfr_init2 (b, 64); 1283 1.1.1.5 mrg mpfr_init2 (c, 64); 1284 1.1.1.5 mrg 1285 1.1.1.5 mrg mpfr_set_str_binary (b, "1111110110100001011100100000100000110110001100100010011010011001E-64"); /* 18276014142440744601/2^64 */ 1286 1.1.1.5 mrg mpfr_set_str_binary (c, "1000000100110010000111000100010010010001000100101010111101010100E-64"); /* 9309534460545511252/2^64 */ 1287 1.1.1.5 mrg /* since 1/2-2^-66 < b0*c0 < 1/2, b0*c0 should be rounded to 1/2 */ 1288 1.1.1.5 mrg inex = mpfr_mul (a, b, c, MPFR_RNDN); 1289 1.1.1.5 mrg MPFR_ASSERTN(mpfr_cmp_ui_2exp (a, 1, -1) == 0); 1290 1.1.1.5 mrg MPFR_ASSERTN(inex > 0); 1291 1.1.1.5 mrg 1292 1.1.1.5 mrg mpfr_clear (a); 1293 1.1.1.5 mrg mpfr_clear (b); 1294 1.1.1.5 mrg mpfr_clear (c); 1295 1.1.1.5 mrg 1296 1.1.1.6 mrg set_emin (emin); /* restore emin */ 1297 1.1.1.5 mrg } 1298 1.1.1.5 mrg 1299 1.1 mrg int 1300 1.1 mrg main (int argc, char *argv[]) 1301 1.1 mrg { 1302 1.1 mrg tests_start_mpfr (); 1303 1.1 mrg 1304 1.1.1.5 mrg coverage (1024); 1305 1.1.1.5 mrg coverage2 (); 1306 1.1.1.4 mrg testall_rndf (9); 1307 1.1 mrg check_nans (); 1308 1.1 mrg check_exact (); 1309 1.1 mrg check_float (); 1310 1.1 mrg 1311 1.1 mrg check53("6.9314718055994530941514e-1", "0.0", MPFR_RNDZ, "0.0"); 1312 1.1 mrg check53("0.0", "6.9314718055994530941514e-1", MPFR_RNDZ, "0.0"); 1313 1.1 mrg check_sign(); 1314 1.1 mrg check53("-4.165000000e4", "-0.00004801920768307322868063274915", MPFR_RNDN, 1315 1.1 mrg "2.0"); 1316 1.1 mrg check53("2.71331408349172961467e-08", "-6.72658901114033715233e-165", 1317 1.1 mrg MPFR_RNDZ, "-1.8251348697787782844e-172"); 1318 1.1 mrg check53("2.71331408349172961467e-08", "-6.72658901114033715233e-165", 1319 1.1 mrg MPFR_RNDA, "-1.8251348697787786e-172"); 1320 1.1 mrg check53("0.31869277231188065", "0.88642843322303122", MPFR_RNDZ, 1321 1.1 mrg "2.8249833483992453642e-1"); 1322 1.1 mrg check("8.47622108205396074254e-01", "3.24039313247872939883e-01", MPFR_RNDU, 1323 1.1 mrg 28, 45, 2, "0.375"); 1324 1.1 mrg check("8.47622108205396074254e-01", "3.24039313247872939883e-01", MPFR_RNDA, 1325 1.1 mrg 28, 45, 2, "0.375"); 1326 1.1 mrg check("2.63978122803639081440e-01", "6.8378615379333496093e-1", MPFR_RNDN, 1327 1.1 mrg 34, 23, 31, "0.180504585267044603"); 1328 1.1 mrg check("1.0", "0.11835170935876249132", MPFR_RNDU, 6, 41, 36, 1329 1.1 mrg "0.1183517093595583"); 1330 1.1 mrg check53("67108865.0", "134217729.0", MPFR_RNDN, "9.007199456067584e15"); 1331 1.1 mrg check("1.37399642157394197284e-01", "2.28877275604219221350e-01", MPFR_RNDN, 1332 1.1 mrg 49, 15, 32, "0.0314472340833162888"); 1333 1.1 mrg check("4.03160720978664954828e-01", "5.854828e-1" 1334 1.1 mrg /*"5.85483042917246621073e-01"*/, MPFR_RNDZ, 1335 1.1 mrg 51, 22, 32, "0.2360436821472831"); 1336 1.1 mrg check("3.90798504668055102229e-14", "9.85394674650308388664e-04", MPFR_RNDN, 1337 1.1 mrg 46, 22, 12, "0.385027296503914762e-16"); 1338 1.1 mrg check("4.58687081072827851358e-01", "2.20543551472118792844e-01", MPFR_RNDN, 1339 1.1 mrg 49, 3, 2, "0.09375"); 1340 1.1 mrg check_max(); 1341 1.1 mrg check_min(); 1342 1.1.1.4 mrg small_prec (); 1343 1.1 mrg 1344 1.1 mrg check_regression (); 1345 1.1.1.4 mrg test_generic (MPFR_PREC_MIN, 500, 100); 1346 1.1 mrg 1347 1.1 mrg data_check ("data/mulpi", mpfr_mulpi, "mpfr_mulpi"); 1348 1.1 mrg 1349 1.1.1.2 mrg valgrind20110503 (); 1350 1.1.1.3 mrg test_underflow (128); 1351 1.1.1.4 mrg bug20161209 (); 1352 1.1.1.4 mrg bug20161209a (); 1353 1.1.1.4 mrg bug20170602 (); 1354 1.1.1.4 mrg test_underflow2 (); 1355 1.1.1.2 mrg 1356 1.1 mrg tests_end_mpfr (); 1357 1.1 mrg return 0; 1358 1.1 mrg } 1359