1/* Test file for mpfr_get_d 2 3Copyright 1999, 2000, 2001, 2002, 2003, 2004, 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 <float.h> 26 27#include "mpfr-test.h" 28 29static int 30check_denorms (void) 31{ 32 mpfr_rnd_t rnd_mode; 33 mpfr_t x; 34 double d, d2, dd, f; 35 int fail = 0, k, n; 36 37 mpfr_init2 (x, GMP_NUMB_BITS); 38 39 rnd_mode = MPFR_RNDN; 40 for (k = -17; k <= 17; k += 2) 41 { 42 d = (double) k * DBL_MIN; /* k * 2^(-1022) */ 43 f = 1.0; 44 mpfr_set_si (x, k, MPFR_RNDN); 45 mpfr_div_2exp (x, x, 1022, MPFR_RNDN); /* k * 2^(-1022) */ 46 for (n = 0; n <= 58; n++) 47 { 48 d2 = d * f; 49 dd = mpfr_get_d (x, rnd_mode); 50 if (d2 != dd) /* should be k * 2^(-1022-n) for n < 53 */ 51 { 52 printf ("Wrong result for %d * 2^(%d), rnd_mode %d\n", 53 k, -1022-n, rnd_mode); 54 printf ("got %.20e instead of %.20e\n", dd, d2); 55 fail = 1; 56 } 57 f *= 0.5; 58 mpfr_div_2exp (x, x, 1, MPFR_RNDN); 59 } 60 } 61 62 mpfr_set_str_binary (x, "1e-1074"); 63 dd = mpfr_get_d (x, MPFR_RNDA); 64 d2 = DBL_MIN; /* 2^(-1022) */ 65 for (k = 0; k < 52; k++) 66 d2 *= 0.5; /* 2^(-1074) */ 67 /* we first check that d2 is not zero (it could happen on a platform with 68 no subnormals) */ 69 if (d2 != 0.0 && dd != d2) 70 { 71 printf ("Error for x=1e-1074, RNDA\n"); 72 exit (1); 73 } 74 75 mpfr_set_str_binary (x, "1e-1075"); 76 dd = mpfr_get_d (x, MPFR_RNDA); 77 if (d2 != 0.0 && dd != d2) 78 { 79 printf ("Error for x=1e-1075, RNDA\n"); 80 printf ("expected %.16e\n", d2); 81 printf ("got %.16e\n", dd); 82 exit (1); 83 } 84 85 mpfr_clear (x); 86 return fail; 87} 88 89static void 90check_inf_nan (void) 91{ 92 /* only if nans and infs are available */ 93#if _GMP_IEEE_FLOATS 94 mpfr_t x; 95 double d; 96 97 mpfr_init2 (x, 123); 98 99 mpfr_set_inf (x, 1); 100 d = mpfr_get_d (x, MPFR_RNDZ); 101 ASSERT_ALWAYS (d > 0); 102 ASSERT_ALWAYS (DOUBLE_ISINF (d)); 103 104 mpfr_set_inf (x, -1); 105 d = mpfr_get_d (x, MPFR_RNDZ); 106 ASSERT_ALWAYS (d < 0); 107 ASSERT_ALWAYS (DOUBLE_ISINF (d)); 108 109 mpfr_set_nan (x); 110 d = mpfr_get_d (x, MPFR_RNDZ); 111 ASSERT_ALWAYS (DOUBLE_ISNAN (d)); 112 113 mpfr_clear (x); 114#endif 115} 116 117static void 118check_max (void) 119{ 120 double d, e; 121 mpfr_t u; 122 123 d = 1.0; 124 while (d < (DBL_MAX / 2.0)) 125 d += d; 126 mpfr_init (u); 127 if (mpfr_set_d (u, d, MPFR_RNDN) == 0) 128 { 129 /* If setting is exact */ 130 e = (mpfr_get_d1) (u); 131 if (e != d) 132 { 133 printf ("get_d(set_d)(1): %1.20e != %1.20e\n", d, e); 134 exit (1); 135 } 136 } 137 138 mpfr_set_str_binary (u, "-1E1024"); 139 d = mpfr_get_d (u, MPFR_RNDZ); 140 MPFR_ASSERTN(d == -DBL_MAX); 141 d = mpfr_get_d (u, MPFR_RNDU); 142 MPFR_ASSERTN(d == -DBL_MAX); 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 148 mpfr_set_str_binary (u, "1E1024"); 149 d = mpfr_get_d (u, MPFR_RNDZ); 150 MPFR_ASSERTN(d == DBL_MAX); 151 d = mpfr_get_d (u, MPFR_RNDD); 152 MPFR_ASSERTN(d == DBL_MAX); 153 d = mpfr_get_d (u, MPFR_RNDN); 154 MPFR_ASSERTN(DOUBLE_ISINF(d) && d > 0.0); 155 d = mpfr_get_d (u, MPFR_RNDU); 156 MPFR_ASSERTN(DOUBLE_ISINF(d) && d > 0.0); 157 158 mpfr_clear (u); 159} 160 161static void 162check_min(void) 163{ 164 double d, e; 165 mpfr_t u; 166 167 d = 1.0; while (d > (DBL_MIN * 2.0)) d /= 2.0; 168 mpfr_init(u); 169 if (mpfr_set_d(u, d, MPFR_RNDN) == 0) 170 { 171 /* If setting is exact */ 172 e = mpfr_get_d1(u); 173 if (e != d) 174 { 175 printf("get_d(set_d)(2): %1.20e != %1.20e\n", d, e); 176 exit(1); 177 } 178 } 179 mpfr_clear(u); 180} 181 182int 183main (void) 184{ 185 tests_start_mpfr (); 186 mpfr_test_init (); 187 188#ifndef MPFR_DOUBLE_SPEC 189 printf ("Warning! The MPFR_DOUBLE_SPEC macro is not defined. This means\n" 190 "that you do not have a conforming C implementation and problems\n" 191 "may occur with conversions between MPFR numbers and standard\n" 192 "floating-point types. Please contact the MPFR team.\n"); 193#elif MPFR_DOUBLE_SPEC == 0 194 /* 195 printf ("The type 'double' of your C implementation does not seem to\n" 196 "correspond to the IEEE-754 double precision. Though code has\n" 197 "been written to support such implementations, tests have been\n" 198 "done only on IEEE-754 double-precision implementations and\n" 199 "conversions between MPFR numbers and standard floating-point\n" 200 "types may be inaccurate. You may wish to contact the MPFR team\n" 201 "for further testing.\n"); 202 */ 203 printf ("The type 'double' of your C implementation does not seem to\n" 204 "correspond to the IEEE-754 double precision. Such particular\n" 205 "implementations are not supported yet, and conversions between\n" 206 "MPFR numbers and standard floating-point types may be very\n" 207 "inaccurate.\n"); 208 printf ("FLT_RADIX = %ld\n", (long) FLT_RADIX); 209 printf ("DBL_MANT_DIG = %ld\n", (long) DBL_MANT_DIG); 210 printf ("DBL_MIN_EXP = %ld\n", (long) DBL_MIN_EXP); 211 printf ("DBL_MAX_EXP = %ld\n", (long) DBL_MAX_EXP); 212#endif 213 214 if (check_denorms ()) 215 exit (1); 216 217 check_inf_nan (); 218 check_min(); 219 check_max(); 220 221 tests_end_mpfr (); 222 return 0; 223} 224