1/* Test file for mpfr_get_d 2 3Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. 4Contributed by the AriC and Caramel 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 <float.h> 26 27#include "mpfr-test.h" 28#include "ieee_floats.h" 29 30static int 31check_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 90static void 91check_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 ASSERT_ALWAYS (d > 0); 103 ASSERT_ALWAYS (DOUBLE_ISINF (d)); 104 105 mpfr_set_inf (x, -1); 106 d = mpfr_get_d (x, MPFR_RNDZ); 107 ASSERT_ALWAYS (d < 0); 108 ASSERT_ALWAYS (DOUBLE_ISINF (d)); 109 110 mpfr_set_nan (x); 111 d = mpfr_get_d (x, MPFR_RNDZ); 112 ASSERT_ALWAYS (DOUBLE_ISNAN (d)); 113 114 mpfr_clear (x); 115#endif 116} 117 118static void 119check_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 166static void 167check_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 187static void 188check_get_d_2exp_inf_nan (void) 189{ 190 double var_d; 191 long exp; 192 mpfr_t var; 193 194#if !defined(MPFR_ERRDIVZERO) 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 250int 251main (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