1 /* Test file for mpfr_set_d and mpfr_get_d. 2 3 Copyright 1999-2023 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 27 int 28 main (int argc, char *argv[]) 29 { 30 mpfr_t x, y, z; 31 unsigned long k, n; 32 volatile double d; 33 double dd; 34 35 tests_start_mpfr (); 36 mpfr_test_init (); 37 38 #ifndef MPFR_DOUBLE_SPEC 39 printf ("Warning! The MPFR_DOUBLE_SPEC macro is not defined. This means\n" 40 "that you do not have a conforming C implementation and problems\n" 41 "may occur with conversions between MPFR numbers and standard\n" 42 "floating-point types. Please contact the MPFR team.\n"); 43 #elif MPFR_DOUBLE_SPEC == 0 44 /* 45 printf ("The type 'double' of your C implementation does not seem to\n" 46 "correspond to the IEEE-754 double precision. Though code has\n" 47 "been written to support such implementations, tests have been\n" 48 "done only on IEEE-754 double-precision implementations and\n" 49 "conversions between MPFR numbers and standard floating-point\n" 50 "types may be inaccurate. You may wish to contact the MPFR team\n" 51 "for further testing.\n"); 52 */ 53 printf ("The type 'double' of your C implementation does not seem to\n" 54 "correspond to the IEEE-754 double precision. Such particular\n" 55 "implementations are not supported yet, and conversions between\n" 56 "MPFR numbers and standard floating-point types may be very\n" 57 "inaccurate.\n"); 58 printf ("FLT_RADIX = %ld\n", (long) FLT_RADIX); 59 printf ("DBL_MANT_DIG = %ld\n", (long) DBL_MANT_DIG); 60 printf ("DBL_MIN_EXP = %ld\n", (long) DBL_MIN_EXP); 61 printf ("DBL_MAX_EXP = %ld\n", (long) DBL_MAX_EXP); 62 #endif 63 64 mpfr_init (x); 65 66 #if !defined(MPFR_ERRDIVZERO) 67 mpfr_set_nan (x); 68 d = mpfr_get_d (x, MPFR_RNDN); 69 if (! DOUBLE_ISNAN (d)) 70 { 71 printf ("ERROR for NAN (1)\n"); 72 #ifdef MPFR_NANISNAN 73 printf ("The reason is that NAN == NAN. Please look at the configure " 74 "output\nand Section \"In case of problem\" of the INSTALL " 75 "file.\n"); 76 #endif 77 exit (1); 78 } 79 mpfr_set_ui (x, 0, MPFR_RNDN); 80 mpfr_set_d (x, d, MPFR_RNDN); 81 if (! mpfr_nan_p (x)) 82 { 83 printf ("ERROR for NAN (2)\n"); 84 #ifdef MPFR_NANISNAN 85 printf ("The reason is that NAN == NAN. Please look at the configure " 86 "output\nand Section \"In case of problem\" of the INSTALL " 87 "file.\n"); 88 #endif 89 exit (1); 90 } 91 #endif /* MPFR_ERRDIVZERO */ 92 93 #ifdef HAVE_SIGNEDZ 94 d = 0.0; 95 mpfr_set_d (x, d, MPFR_RNDN); 96 MPFR_ASSERTN(mpfr_cmp_ui (x, 0) == 0 && MPFR_IS_POS(x)); 97 d = -d; 98 mpfr_set_d (x, d, MPFR_RNDN); 99 if (mpfr_cmp_ui (x, 0) != 0 || MPFR_IS_POS(x)) 100 { 101 printf ("Error in mpfr_set_d on -0\n"); 102 printf ("d = %g, x = ", d); 103 mpfr_dump (x); 104 exit (1); 105 } 106 #endif /* HAVE_SIGNEDZ */ 107 108 #if !defined(MPFR_ERRDIVZERO) 109 mpfr_set_inf (x, 1); 110 d = mpfr_get_d (x, MPFR_RNDN); 111 mpfr_set_ui (x, 0, MPFR_RNDN); 112 mpfr_set_d (x, d, MPFR_RNDN); 113 MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) > 0); 114 115 mpfr_set_inf (x, -1); 116 d = mpfr_get_d (x, MPFR_RNDN); 117 mpfr_set_ui (x, 0, MPFR_RNDN); 118 mpfr_set_d (x, d, MPFR_RNDN); 119 MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) < 0); 120 #endif /* MPFR_ERRDIVZERO */ 121 122 mpfr_set_prec (x, 2); 123 124 /* checks that subnormals are not flushed to zero */ 125 d = DBL_MIN; /* 2^(-1022) */ 126 for (n = 0; n < 53; n++, d /= 2.0) 127 if (d != 0.0) /* should be 2^(-1022-n) */ 128 { 129 mpfr_set_d (x, d, MPFR_RNDN); 130 if (mpfr_cmp_ui_2exp (x, 1, -1022-n)) 131 { 132 printf ("Wrong result for d=2^(%ld), ", -1022-n); 133 printf ("got "); 134 mpfr_out_str (stdout, 10, 10, x, MPFR_RNDN); 135 printf ("\n"); 136 mpfr_dump (x); 137 exit (1); 138 } 139 } 140 141 /* checks that rounds to nearest sets the last 142 bit to zero in case of equal distance */ 143 mpfr_set_d (x, 5.0, MPFR_RNDN); 144 if (mpfr_cmp_ui (x, 4)) 145 { 146 printf ("Error in tset_d: expected 4.0, got "); 147 mpfr_dump (x); 148 exit (1); 149 } 150 mpfr_set_d (x, -5.0, MPFR_RNDN); 151 if (mpfr_cmp_si (x, -4)) 152 { 153 printf ("Error in tset_d: expected -4.0, got "); 154 mpfr_dump (x); 155 exit (1); 156 } 157 158 mpfr_set_d (x, 9.84891017624509146344e-01, MPFR_RNDU); 159 if (mpfr_cmp_ui (x, 1)) 160 { 161 printf ("Error in tset_d: expected 1.0, got "); 162 mpfr_dump (x); 163 exit (1); 164 } 165 166 mpfr_init2 (z, 32); 167 mpfr_set_d (z, 1.0, (mpfr_rnd_t) 0); 168 if (mpfr_cmp_ui (z, 1)) 169 { 170 mpfr_dump (z); 171 printf ("Error: 1.0 != 1.0\n"); 172 exit (1); 173 } 174 mpfr_set_prec (x, 53); 175 mpfr_init2 (y, 53); 176 mpfr_set_d (x, d=-1.08007920352320089721e+150, (mpfr_rnd_t) 0); 177 if (mpfr_get_d1 (x) != d) 178 { 179 mpfr_dump (x); 180 printf ("Error: get_d o set_d <> identity for d = %1.20e %1.20e\n", 181 d, mpfr_get_d1 (x)); 182 exit (1); 183 } 184 185 mpfr_set_d (x, 8.06294740693074521573e-310, (mpfr_rnd_t) 0); 186 d = -6.72658901114033715233e-165; 187 mpfr_set_d (x, d, (mpfr_rnd_t) 0); 188 if (d != mpfr_get_d1 (x)) 189 { 190 mpfr_dump (x); 191 printf ("Error: get_d o set_d <> identity for d = %1.20e %1.20e\n", 192 d, mpfr_get_d1 (x)); 193 exit (1); 194 } 195 196 n = argc == 1 ? 500000 : atoi (argv[1]); 197 for (k = 1; k <= n; k++) 198 { 199 do 200 { 201 d = DBL_RAND (); 202 } 203 while (ABS(d) < DBL_MIN); 204 mpfr_set_d (x, d, (mpfr_rnd_t) 0); 205 dd = mpfr_get_d1 (x); 206 if (d != dd && !(Isnan(d) && Isnan(dd))) 207 { 208 printf ("Mismatch on : %1.18g != %1.18g\n", d, mpfr_get_d1 (x)); 209 mpfr_dump (x); 210 exit (1); 211 } 212 } 213 214 mpfr_clear (x); 215 mpfr_clear (y); 216 mpfr_clear (z); 217 218 tests_end_mpfr (); 219 return 0; 220 } 221