1 /* Test file for mpfr_get_f. 2 3 Copyright 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. 4 Contributed by the AriC and Caramel projects, INRIA. 5 6 This file is part of the GNU MPFR Library. 7 8 The GNU MPFR Library is free software; you can redistribute it and/or modify 9 it under the terms of the GNU Lesser General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or (at your 11 option) any later version. 12 13 The GNU MPFR Library is distributed in the hope that it will be useful, but 14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16 License for more details. 17 18 You should have received a copy of the GNU Lesser General Public License 19 along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see 20 http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., 21 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ 22 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <limits.h> 26 27 #include "mpfr-test.h" 28 29 /* Test that there is no lost of accuracy when converting a mpfr_t number 30 into a mpf_t number (test with various precisions and exponents). */ 31 static void 32 prec_test (void) 33 { 34 int px, py; 35 36 for (py = 3; py <= 136; py++) 37 { 38 mpfr_t y1, y2, y3; 39 40 mpfr_init2 (y1, py); 41 mpfr_init2 (y2, py); 42 mpfr_init2 (y3, py); 43 44 for (px = 32; px <= 160; px += 32) 45 { 46 mpf_t x1, x2, x3; 47 int e; 48 49 mpf_init (x1); 50 mpf_init (x2); 51 mpf_init (x3); 52 mpfr_set_ui_2exp (y1, 1, py - 1, MPFR_RNDN); 53 mpfr_get_f (x1, y1, MPFR_RNDN); /* exact (power of 2) */ 54 mpf_set (x2, x1); 55 mpfr_set (y2, y1, MPFR_RNDN); 56 57 for (e = py - 2; e >= 0; e--) 58 { 59 int inex; 60 mpf_div_2exp (x2, x2, 1); 61 mpf_add (x1, x1, x2); 62 mpfr_div_2exp (y2, y2, 1, MPFR_RNDN); 63 inex = mpfr_add (y1, y1, y2, MPFR_RNDN); 64 MPFR_ASSERTN (inex == 0); 65 mpfr_set_f (y3, x1, MPFR_RNDN); 66 if (! mpfr_equal_p (y1, y3)) 67 break; 68 inex = mpfr_get_f (x3, y3, MPFR_RNDN); 69 if (mpf_cmp (x1, x3) != 0) 70 { 71 printf ("Error in prec_test (px = %d, py = %d, e = %d)\n", 72 px, py, e); 73 printf ("x1 = "); 74 mpf_out_str (stdout, 16, 0, x1); 75 printf ("\nx2 = "); 76 mpf_out_str (stdout, 16, 0, x2); 77 printf ("\n"); 78 exit (1); 79 } 80 if (inex != 0) 81 { 82 printf ("Error in prec_test (px = %d, py = %d, e = %d)\n", 83 px, py, e); 84 printf ("wrong ternary value got: %+d, expected: 0\n", 85 inex); 86 exit (1); 87 } 88 } 89 90 mpf_clear (x1); 91 mpf_clear (x2); 92 mpf_clear (x3); 93 } 94 95 mpfr_clear (y1); 96 mpfr_clear (y2); 97 mpfr_clear (y3); 98 } 99 } 100 101 static void 102 special_test (void) 103 { 104 int inex; 105 mpf_t x; 106 mpfr_t y; 107 108 mpfr_init (y); 109 mpf_init (x); 110 111 mpfr_set_nan (y); 112 mpfr_clear_flags (); 113 mpfr_get_f (x, y, MPFR_RNDN); 114 if (! mpfr_erangeflag_p ()) 115 { 116 printf ("Error: mpfr_get_f(NaN) should raise erange flag\n"); 117 exit (1); 118 } 119 120 mpfr_set_inf (y, +1); 121 mpfr_clear_flags (); 122 inex = mpfr_get_f (x, y, MPFR_RNDN); 123 if (inex >= 0) 124 { 125 printf ("Error: mpfr_get_f(+Inf) should return a negative ternary" 126 "value\n"); 127 exit (1); 128 } 129 if (! mpfr_erangeflag_p ()) 130 { 131 printf ("Error: mpfr_get_f(+Inf) should raise erange flag\n"); 132 exit (1); 133 } 134 135 mpfr_set_inf (y, -1); 136 mpfr_clear_flags (); 137 inex = mpfr_get_f (x, y, MPFR_RNDN); 138 if (inex <= 0) 139 { 140 printf ("Error: mpfr_get_f(-Inf) should return a positive ternary" 141 "value\n"); 142 exit (1); 143 } 144 if (! mpfr_erangeflag_p ()) 145 { 146 printf ("Error: mpfr_get_f(-Inf) should raise erange flag\n"); 147 exit (1); 148 } 149 150 mpfr_set_ui (y, 0, MPFR_RNDN); 151 if (mpfr_get_f (x, y, MPFR_RNDN) != 0 || mpf_cmp_ui (x, 0)) 152 { 153 printf ("Error: mpfr_get_f(+0) fails\n"); 154 exit (1); 155 } 156 157 mpfr_set_ui (y, 0, MPFR_RNDN); 158 mpfr_neg (y, y, MPFR_RNDN); 159 if (mpfr_get_f (x, y, MPFR_RNDN) != 0 || mpf_cmp_ui (x, 0)) 160 { 161 printf ("Error: mpfr_get_f(-0) fails\n"); 162 exit (1); 163 } 164 165 mpfr_clear (y); 166 mpf_clear (x); 167 } 168 169 static void 170 ternary_test (void) 171 { 172 int prec; 173 int rnd; 174 int inex, expected_inex; 175 mpf_t x; 176 mpfr_t y; 177 178 mpf_init2 (x, 256); 179 mpfr_init2 (y, 256); 180 181 for (prec = 2; prec <= 256; prec++) 182 { 183 184 mpf_set_prec (x, prec); 185 mpfr_set_prec (y, PREC (x) * GMP_NUMB_BITS + 1); 186 187 /* y == 1 */ 188 mpfr_set_ui_2exp (y, 1, prec, MPFR_RNDN); 189 190 RND_LOOP (rnd) 191 { 192 inex = mpfr_get_f (x, y, (mpfr_rnd_t) rnd); 193 194 if (inex != 0 || mpfr_cmp_f (y, x) !=0) 195 { 196 printf ("Error in mpfr_get_f (x, y, %s)\nx = ", 197 mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); 198 mpf_out_str (stdout, 2, 0, x); 199 printf ("\ny = "); 200 mpfr_dump (y); 201 if (inex != 0) 202 printf ("got ternary value = %+d, expected: 0\n", inex); 203 204 exit (1); 205 } 206 } 207 208 /* y == 1 + epsilon */ 209 mpfr_nextbelow (y); 210 211 RND_LOOP (rnd) 212 { 213 switch (rnd) 214 { 215 case MPFR_RNDU: case MPFR_RNDA: 216 case MPFR_RNDN: 217 expected_inex = +1; 218 break; 219 default : 220 expected_inex = -1; 221 } 222 223 inex = mpfr_get_f (x, y, (mpfr_rnd_t) rnd); 224 225 if (! SAME_SIGN (expected_inex, inex) 226 || SAME_SIGN (expected_inex, mpfr_cmp_f (y, x))) 227 { 228 printf ("Error in mpfr_get_f (x, y, %s)\nx = ", 229 mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); 230 mpf_out_str (stdout, 2, 0, x); 231 printf ("\ny = "); 232 mpfr_dump (y); 233 if (! SAME_SIGN (expected_inex, inex)) 234 printf ("got ternary value = %+d, expected: %+d\n", 235 inex, expected_inex); 236 237 exit (1); 238 } 239 } 240 241 /* y == positive random float */ 242 mpfr_random2 (y, MPFR_LIMB_SIZE (y), 1024, RANDS); 243 244 RND_LOOP (rnd) 245 { 246 inex = mpfr_get_f (x, y, (mpfr_rnd_t) rnd); 247 248 if (! SAME_SIGN (inex, -mpfr_cmp_f (y, x))) 249 { 250 printf ("Error in mpfr_get_f (x, y, %s)\nx = ", 251 mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); 252 mpf_out_str (stdout, 2, 0, x); 253 printf ("\ny = "); 254 mpfr_dump (y); 255 printf ("got ternary value = %+d, expected: %+d\n", 256 inex, -mpfr_cmp_f (y, x)); 257 258 exit (1); 259 } 260 } 261 } 262 263 mpf_clear (x); 264 mpfr_clear (y); 265 } 266 267 int 268 main (void) 269 { 270 mpf_t x; 271 mpfr_t y, z; 272 unsigned long i; 273 mpfr_exp_t e; 274 int inex; 275 276 tests_start_mpfr (); 277 278 mpfr_init (y); 279 mpfr_init (z); 280 mpf_init (x); 281 282 i = 1; 283 while (i) 284 { 285 mpfr_set_ui (y, i, MPFR_RNDN); 286 if (mpfr_get_f (x, y, MPFR_RNDN) != 0 || mpf_cmp_ui (x, i)) 287 { 288 printf ("Error: mpfr_get_f(%lu) fails\n", i); 289 exit (1); 290 } 291 if (i <= - (unsigned long) LONG_MIN) 292 { 293 long j = i < - (unsigned long) LONG_MIN ? - (long) i : LONG_MIN; 294 mpfr_set_si (y, j, MPFR_RNDN); 295 if (mpfr_get_f (x, y, MPFR_RNDN) != 0 || mpf_cmp_si (x, j)) 296 { 297 printf ("Error: mpfr_get_f(-%lu) fails\n", i); 298 exit (1); 299 } 300 } 301 i *= 2; 302 } 303 304 /* same tests, but with a larger precision for y, which requires to 305 round it */ 306 mpfr_set_prec (y, 100); 307 i = 1; 308 while (i) 309 { 310 mpfr_set_ui (y, i, MPFR_RNDN); 311 inex = mpfr_get_f (x, y, MPFR_RNDN); 312 if (! SAME_SIGN (inex, - mpfr_cmp_f (y, x)) || mpf_cmp_ui (x, i)) 313 { 314 printf ("Error: mpfr_get_f(%lu) fails\n", i); 315 exit (1); 316 } 317 mpfr_set_si (y, (signed long) -i, MPFR_RNDN); 318 inex = mpfr_get_f (x, y, MPFR_RNDN); 319 if (! SAME_SIGN (inex, - mpfr_cmp_f (y, x)) 320 || mpf_cmp_si (x, (signed long) -i)) 321 { 322 printf ("Error: mpfr_get_f(-%lu) fails\n", i); 323 exit (1); 324 } 325 i *= 2; 326 } 327 328 /* bug reported by Jim White */ 329 for (e = 0; e <= 2 * GMP_NUMB_BITS; e++) 330 { 331 /* test with 2^(-e) */ 332 mpfr_set_ui (y, 1, MPFR_RNDN); 333 mpfr_div_2exp (y, y, e, MPFR_RNDN); 334 inex = mpfr_get_f (x, y, MPFR_RNDN); 335 mpf_mul_2exp (x, x, e); 336 if (inex != 0 || mpf_cmp_ui (x, 1) != 0) 337 { 338 printf ("Error: mpfr_get_f(x,y,MPFR_RNDN) fails\n"); 339 printf ("y="); 340 mpfr_dump (y); 341 printf ("x="); 342 mpf_div_2exp (x, x, e); 343 mpf_out_str (stdout, 2, 0, x); 344 exit (1); 345 } 346 347 /* test with 2^(e) */ 348 mpfr_set_ui (y, 1, MPFR_RNDN); 349 mpfr_mul_2exp (y, y, e, MPFR_RNDN); 350 inex = mpfr_get_f (x, y, MPFR_RNDN); 351 mpf_div_2exp (x, x, e); 352 if (inex != 0 || mpf_cmp_ui (x, 1) != 0) 353 { 354 printf ("Error: mpfr_get_f(x,y,MPFR_RNDN) fails\n"); 355 printf ("y="); 356 mpfr_dump (y); 357 printf ("x="); 358 mpf_mul_2exp (x, x, e); 359 mpf_out_str (stdout, 2, 0, x); 360 exit (1); 361 } 362 } 363 364 /* Bug reported by Yury Lukach on 2006-04-05 */ 365 mpfr_set_prec (y, 32); 366 mpfr_set_prec (z, 32); 367 mpf_set_prec (x, 32); 368 mpfr_set_ui_2exp (y, 0xc1234567, -30, MPFR_RNDN); 369 mpfr_get_f (x, y, MPFR_RNDN); 370 inex = mpfr_set_f (z, x, MPFR_RNDN); 371 if (inex != 0 || ! mpfr_equal_p (y, z)) 372 { 373 printf ("Error in mpfr_get_f:\n inex = %d, y = ", inex); 374 mpfr_dump (z); 375 printf ("Expected:\n inex = 0, y = "); 376 mpfr_dump (y); 377 exit (1); 378 } 379 380 mpfr_clear (y); 381 mpfr_clear (z); 382 mpf_clear (x); 383 384 special_test (); 385 prec_test (); 386 ternary_test (); 387 388 tests_end_mpfr (); 389 return 0; 390 } 391