1 /* Test mpfr_get_ld_2exp. 2 3 Copyright 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 <float.h> 26 27 #include "mpfr-test.h" 28 29 /* Check that hardware rounding doesn't make mpfr_get_ld_2exp return a value 30 outside its defined range. */ 31 static void 32 check_round (void) 33 { 34 static const unsigned long data[] = {1, 32, 53, 54, 63, 64, 65, 127, 128, 256, 512 }; 35 mpfr_t f; 36 long double got; 37 long got_exp; 38 int i, rnd_mode, neg; 39 40 mpfr_init2 (f, 1024L); 41 42 for (rnd_mode = 0; rnd_mode < MPFR_RND_MAX ; rnd_mode++) 43 { 44 for (i = 0; i < (int) numberof (data); i++) 45 { 46 mpfr_set_ui (f, 1L, MPFR_RNDZ); 47 mpfr_mul_2exp (f, f, data[i], MPFR_RNDZ); 48 mpfr_sub_ui (f, f, 1L, MPFR_RNDZ); 49 50 for (neg = 0; neg <= 1; neg++) 51 { 52 got = mpfr_get_ld_2exp (&got_exp, f, (mpfr_rnd_t) rnd_mode); 53 54 if (neg == 0 55 ? (got < 0.5 || got >= 1.0) 56 : (got <= -1.0 || got > -0.5)) 57 { 58 printf ("mpfr_get_ld_2exp wrong on 2**%lu-1\n", data[i]); 59 printf ("result out of range, expect 0.5 <= got < 1.0\n"); 60 printf (" rnd_mode = %d\n", rnd_mode); 61 printf (" data[i] = %lu\n", data[i]); 62 printf (" f "); 63 mpfr_out_str (stdout, 2, 0, f, MPFR_RNDN); 64 printf ("\n"); 65 d_trace (" got ", got); 66 printf (" got exp %ld\n", got_exp); 67 exit(1); 68 } 69 70 mpfr_neg (f, f, MPFR_RNDZ); 71 } 72 } 73 } 74 75 mpfr_clear (f); 76 } 77 78 79 static void 80 check_inf_nan (void) 81 { 82 /* only if nans and infs are available */ 83 #if _GMP_IEEE_FLOATS 84 mpfr_t x; 85 double d; 86 long exp; 87 88 mpfr_init2 (x, 123); 89 90 mpfr_set_inf (x, 1); 91 d = (double) mpfr_get_ld_2exp (&exp, x, MPFR_RNDZ); 92 ASSERT_ALWAYS (d > 0); 93 ASSERT_ALWAYS (DOUBLE_ISINF (d)); 94 95 mpfr_set_inf (x, -1); 96 d = (double) mpfr_get_ld_2exp (&exp, x, MPFR_RNDZ); 97 ASSERT_ALWAYS (d < 0); 98 ASSERT_ALWAYS (DOUBLE_ISINF (d)); 99 100 mpfr_set_nan (x); 101 d = (double) mpfr_get_ld_2exp (&exp, x, MPFR_RNDZ); 102 ASSERT_ALWAYS (DOUBLE_ISNAN (d)); 103 104 mpfr_clear (x); 105 #endif 106 } 107 108 static void 109 bug20090520 (void) 110 { 111 mpfr_t x; 112 long double d, e; 113 int i; 114 115 mpfr_init (x); 116 mpfr_set_ui (x, 1, MPFR_RNDN); 117 d = 1.0; 118 mpfr_div_2exp (x, x, 16383, MPFR_RNDN); 119 for (i = 0; i < 16383; i++) 120 d *= 0.5; 121 e = mpfr_get_ld (x, MPFR_RNDN); 122 if (e != d) 123 { 124 printf ("mpfr_get_ld(1e-16383) failed\n"); 125 printf ("expected %.20Le\n", d); 126 printf ("got %.20Le\n", e); 127 exit (1); 128 } 129 mpfr_clear (x); 130 } 131 132 int 133 main (void) 134 { 135 tests_start_mpfr (); 136 mpfr_test_init (); 137 138 bug20090520 (); 139 140 check_round (); 141 check_inf_nan (); 142 143 tests_end_mpfr (); 144 return 0; 145 } 146