1 /* Test file for mpfr_get_d 2 3 Copyright 1999-2016 Free Software Foundation, Inc. 4 Contributed by the AriC and Caramba 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 #include "ieee_floats.h" 29 30 static int 31 check_denorms (void) 32 { 33 mpfr_rnd_t rnd_mode; 34 mpfr_t x; 35 double d, d2, dd, f; 36 int fail = 0, k, n; 37 38 mpfr_init2 (x, GMP_NUMB_BITS); 39 40 rnd_mode = MPFR_RNDN; 41 for (k = -17; k <= 17; k += 2) 42 { 43 d = (double) k * DBL_MIN; /* k * 2^(-1022) */ 44 f = 1.0; 45 mpfr_set_si (x, k, MPFR_RNDN); 46 mpfr_div_2exp (x, x, 1022, MPFR_RNDN); /* k * 2^(-1022) */ 47 for (n = 0; n <= 58; n++) 48 { 49 d2 = d * f; 50 dd = mpfr_get_d (x, rnd_mode); 51 if (d2 != dd) /* should be k * 2^(-1022-n) for n < 53 */ 52 { 53 printf ("Wrong result for %d * 2^(%d), rnd_mode %d\n", 54 k, -1022-n, rnd_mode); 55 printf ("got %.20e instead of %.20e\n", dd, d2); 56 fail = 1; 57 } 58 f *= 0.5; 59 mpfr_div_2exp (x, x, 1, MPFR_RNDN); 60 } 61 } 62 63 mpfr_set_str_binary (x, "1e-1074"); 64 dd = mpfr_get_d (x, MPFR_RNDA); 65 d2 = DBL_MIN; /* 2^(-1022) */ 66 for (k = 0; k < 52; k++) 67 d2 *= 0.5; /* 2^(-1074) */ 68 /* we first check that d2 is not zero (it could happen on a platform with 69 no subnormals) */ 70 if (d2 != 0.0 && dd != d2) 71 { 72 printf ("Error for x=1e-1074, RNDA\n"); 73 exit (1); 74 } 75 76 mpfr_set_str_binary (x, "1e-1075"); 77 dd = mpfr_get_d (x, MPFR_RNDA); 78 if (d2 != 0.0 && dd != d2) 79 { 80 printf ("Error for x=1e-1075, RNDA\n"); 81 printf ("expected %.16e\n", d2); 82 printf ("got %.16e\n", dd); 83 exit (1); 84 } 85 86 mpfr_clear (x); 87 return fail; 88 } 89 90 static void 91 check_inf_nan (void) 92 { 93 /* only if nans and infs are available */ 94 #if _GMP_IEEE_FLOATS && !defined(MPFR_ERRDIVZERO) 95 mpfr_t x; 96 double d; 97 98 mpfr_init2 (x, 123); 99 100 mpfr_set_inf (x, 1); 101 d = mpfr_get_d (x, MPFR_RNDZ); 102 MPFR_ASSERTN (d > 0); 103 MPFR_ASSERTN (DOUBLE_ISINF (d)); 104 105 mpfr_set_inf (x, -1); 106 d = mpfr_get_d (x, MPFR_RNDZ); 107 MPFR_ASSERTN (d < 0); 108 MPFR_ASSERTN (DOUBLE_ISINF (d)); 109 110 mpfr_set_nan (x); 111 d = mpfr_get_d (x, MPFR_RNDZ); 112 MPFR_ASSERTN (DOUBLE_ISNAN (d)); 113 114 mpfr_clear (x); 115 #endif 116 } 117 118 static void 119 check_max (void) 120 { 121 double d, e; 122 mpfr_t u; 123 124 d = 1.0; 125 while (d < (DBL_MAX / 2.0)) 126 d += d; 127 mpfr_init (u); 128 if (mpfr_set_d (u, d, MPFR_RNDN) == 0) 129 { 130 /* If setting is exact */ 131 e = (mpfr_get_d1) (u); 132 if (e != d) 133 { 134 printf ("get_d(set_d)(1): %1.20e != %1.20e\n", d, e); 135 exit (1); 136 } 137 } 138 139 mpfr_set_str_binary (u, "-1E1024"); 140 d = mpfr_get_d (u, MPFR_RNDZ); 141 MPFR_ASSERTN(d == -DBL_MAX); 142 d = mpfr_get_d (u, MPFR_RNDU); 143 MPFR_ASSERTN(d == -DBL_MAX); 144 #if _GMP_IEEE_FLOATS && !defined(MPFR_ERRDIVZERO) 145 d = mpfr_get_d (u, MPFR_RNDN); 146 MPFR_ASSERTN(DOUBLE_ISINF(d) && d < 0.0); 147 d = mpfr_get_d (u, MPFR_RNDD); 148 MPFR_ASSERTN(DOUBLE_ISINF(d) && d < 0.0); 149 #endif 150 151 mpfr_set_str_binary (u, "1E1024"); 152 d = mpfr_get_d (u, MPFR_RNDZ); 153 MPFR_ASSERTN(d == DBL_MAX); 154 d = mpfr_get_d (u, MPFR_RNDD); 155 MPFR_ASSERTN(d == DBL_MAX); 156 #if _GMP_IEEE_FLOATS && !defined(MPFR_ERRDIVZERO) 157 d = mpfr_get_d (u, MPFR_RNDN); 158 MPFR_ASSERTN(DOUBLE_ISINF(d) && d > 0.0); 159 d = mpfr_get_d (u, MPFR_RNDU); 160 MPFR_ASSERTN(DOUBLE_ISINF(d) && d > 0.0); 161 #endif 162 163 mpfr_clear (u); 164 } 165 166 static void 167 check_min(void) 168 { 169 double d, e; 170 mpfr_t u; 171 172 d = 1.0; while (d > (DBL_MIN * 2.0)) d /= 2.0; 173 mpfr_init(u); 174 if (mpfr_set_d(u, d, MPFR_RNDN) == 0) 175 { 176 /* If setting is exact */ 177 e = mpfr_get_d1(u); 178 if (e != d) 179 { 180 printf("get_d(set_d)(2): %1.20e != %1.20e\n", d, e); 181 exit(1); 182 } 183 } 184 mpfr_clear(u); 185 } 186 187 static void 188 check_get_d_2exp_inf_nan (void) 189 { 190 #if !defined(MPFR_ERRDIVZERO) 191 192 double var_d; 193 long exp; 194 mpfr_t var; 195 196 mpfr_init2 (var, MPFR_PREC_MIN); 197 198 mpfr_set_nan (var); 199 var_d = mpfr_get_d_2exp (&exp, var, MPFR_RNDN); 200 if (!DOUBLE_ISNAN (var_d)) 201 { 202 printf ("mpfr_get_d_2exp with a NAN mpfr value returned a wrong value :\n" 203 " waiting for %g got %g\n", MPFR_DBL_NAN, var_d); 204 exit (1); 205 } 206 207 mpfr_set_zero (var, 1); 208 var_d = mpfr_get_d_2exp (&exp, var, MPFR_RNDN); 209 if ((exp != 0) || (var_d != 0.0)) 210 { 211 printf ("mpfr_get_d_2exp with a +0.0 mpfr value returned a wrong value :\n" 212 " double waiting for 0.0 got %g\n exp waiting for 0 got %ld\n", 213 var_d, exp); 214 exit (1); 215 } 216 217 mpfr_set_zero (var, -1); 218 var_d = mpfr_get_d_2exp (&exp, var, MPFR_RNDN); 219 if ((exp != 0) || (var_d != DBL_NEG_ZERO)) 220 { 221 printf ("mpfr_get_d_2exp with a +0.0 mpfr value returned a wrong value :\n" 222 " double waiting for %g got %g\n exp waiting for 0 got %ld\n", 223 DBL_NEG_ZERO, var_d, exp); 224 exit (1); 225 } 226 227 mpfr_set_inf (var, 1); 228 var_d = mpfr_get_d_2exp (&exp, var, MPFR_RNDN); 229 if (var_d != MPFR_DBL_INFP) 230 { 231 printf ("mpfr_get_d_2exp with a +Inf mpfr value returned a wrong value :\n" 232 " waiting for %g got %g\n", MPFR_DBL_INFP, var_d); 233 exit (1); 234 } 235 236 mpfr_set_inf (var, -1); 237 var_d = mpfr_get_d_2exp (&exp, var, MPFR_RNDN); 238 if (var_d != MPFR_DBL_INFM) 239 { 240 printf ("mpfr_get_d_2exp with a -Inf mpfr value returned a wrong value :\n" 241 " waiting for %g got %g\n", MPFR_DBL_INFM, var_d); 242 exit (1); 243 } 244 245 mpfr_clear (var); 246 247 #endif 248 } 249 250 int 251 main (void) 252 { 253 tests_start_mpfr (); 254 mpfr_test_init (); 255 256 #ifndef MPFR_DOUBLE_SPEC 257 printf ("Warning! The MPFR_DOUBLE_SPEC macro is not defined. This means\n" 258 "that you do not have a conforming C implementation and problems\n" 259 "may occur with conversions between MPFR numbers and standard\n" 260 "floating-point types. Please contact the MPFR team.\n"); 261 #elif MPFR_DOUBLE_SPEC == 0 262 /* 263 printf ("The type 'double' of your C implementation does not seem to\n" 264 "correspond to the IEEE-754 double precision. Though code has\n" 265 "been written to support such implementations, tests have been\n" 266 "done only on IEEE-754 double-precision implementations and\n" 267 "conversions between MPFR numbers and standard floating-point\n" 268 "types may be inaccurate. You may wish to contact the MPFR team\n" 269 "for further testing.\n"); 270 */ 271 printf ("The type 'double' of your C implementation does not seem to\n" 272 "correspond to the IEEE-754 double precision. Such particular\n" 273 "implementations are not supported yet, and conversions between\n" 274 "MPFR numbers and standard floating-point types may be very\n" 275 "inaccurate.\n"); 276 printf ("FLT_RADIX = %ld\n", (long) FLT_RADIX); 277 printf ("DBL_MANT_DIG = %ld\n", (long) DBL_MANT_DIG); 278 printf ("DBL_MIN_EXP = %ld\n", (long) DBL_MIN_EXP); 279 printf ("DBL_MAX_EXP = %ld\n", (long) DBL_MAX_EXP); 280 #endif 281 282 if (check_denorms ()) 283 exit (1); 284 285 check_inf_nan (); 286 check_min(); 287 check_max(); 288 289 check_get_d_2exp_inf_nan (); 290 291 tests_end_mpfr (); 292 return 0; 293 } 294 295