xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/tget_d.c (revision aef5eb5f59cdfe8314f1b5f78ac04eb144e44010)
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