xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/tget_d.c (revision 87d689fb734c654d2486f87f7be32f1b53ecdbec)
1 /* Test file for mpfr_get_d
2 
3 Copyright 1999-2016 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 http://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 <stdio.h>
24 #include <stdlib.h>
25 #include <float.h>
26 
27 #include "mpfr-test.h"
28 #include "ieee_floats.h"
29 
30 static int
31 check_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 
90 static void
91 check_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   MPFR_ASSERTN (d > 0);
103   MPFR_ASSERTN (DOUBLE_ISINF (d));
104 
105   mpfr_set_inf (x, -1);
106   d = mpfr_get_d (x, MPFR_RNDZ);
107   MPFR_ASSERTN (d < 0);
108   MPFR_ASSERTN (DOUBLE_ISINF (d));
109 
110   mpfr_set_nan (x);
111   d = mpfr_get_d (x, MPFR_RNDZ);
112   MPFR_ASSERTN (DOUBLE_ISNAN (d));
113 
114   mpfr_clear (x);
115 #endif
116 }
117 
118 static void
119 check_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 
166 static void
167 check_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 
187 static void
188 check_get_d_2exp_inf_nan (void)
189 {
190 #if !defined(MPFR_ERRDIVZERO)
191 
192   double var_d;
193   long exp;
194   mpfr_t var;
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 
250 int
251 main (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