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
main(int argc,char * argv[])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