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