1/* Test file for mpfr_get_f. 2 3Copyright 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. 4Contributed by the Arenaire and Cacao projects, INRIA. 5 6This file is part of the GNU MPFR Library. 7 8The GNU MPFR Library is free software; you can redistribute it and/or modify 9it under the terms of the GNU Lesser General Public License as published by 10the Free Software Foundation; either version 3 of the License, or (at your 11option) any later version. 12 13The GNU MPFR Library is distributed in the hope that it will be useful, but 14WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16License for more details. 17 18You should have received a copy of the GNU Lesser General Public License 19along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see 20http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., 2151 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). */ 31static void 32prec_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 101static void 102special_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 169static void 170ternary_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 267int 268main (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