1/* Test file for mpfr_get_decimal64 and mpfr_set_decimal64.
2
3Copyright 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 <stdlib.h> /* for exit */
24#include "mpfr-test.h"
25
26/* #define DEBUG */
27
28#ifdef MPFR_WANT_DECIMAL_FLOATS
29static void
30print_decimal64 (_Decimal64 d)
31{
32  union ieee_double_extract x;
33  union ieee_double_decimal64 y;
34  unsigned int Gh, i;
35
36  y.d64 = d;
37  x.d = y.d;
38  Gh = x.s.exp >> 6;
39  printf ("|%d%d%d%d%d%d", x.s.sig, Gh >> 4, (Gh >> 3) & 1,
40          (Gh >> 2) & 1, (Gh >> 1) & 1, Gh & 1);
41  printf ("%d%d%d%d%d%d", (x.s.exp >> 5) & 1, (x.s.exp >> 4) & 1,
42          (x.s.exp >> 3) & 1, (x.s.exp >> 2) & 1, (x.s.exp >> 1) & 1,
43          x.s.exp & 1);
44  for (i = 20; i > 0; i--)
45    printf ("%d", (x.s.manh >> (i - 1)) & 1);
46  for (i = 32; i > 0; i--)
47    printf ("%d", (x.s.manl >> (i - 1)) & 1);
48  printf ("|\n");
49}
50
51static void
52check_inf_nan (void)
53{
54  mpfr_t  x, y;
55  _Decimal64 d;
56
57  mpfr_init2 (x, 123);
58  mpfr_init2 (y, 123);
59
60  mpfr_set_nan (x);
61  d = mpfr_get_decimal64 (x, MPFR_RNDZ);
62  mpfr_set_ui (x, 1, MPFR_RNDZ);
63  mpfr_set_decimal64 (x, d, MPFR_RNDZ);
64  ASSERT_ALWAYS (mpfr_nan_p (x));
65
66  mpfr_set_inf (x, 1);
67  d = mpfr_get_decimal64 (x, MPFR_RNDZ);
68  mpfr_set_ui (x, 1, MPFR_RNDZ);
69  mpfr_set_decimal64 (x, d, MPFR_RNDZ);
70  ASSERT_ALWAYS (mpfr_inf_p (x) && mpfr_sgn (x) > 0);
71
72  mpfr_set_inf (x, -1);
73  d = mpfr_get_decimal64 (x, MPFR_RNDZ);
74  mpfr_set_ui (x, 1, MPFR_RNDZ);
75  mpfr_set_decimal64 (x, d, MPFR_RNDZ);
76  ASSERT_ALWAYS (mpfr_inf_p (x) && mpfr_sgn (x) < 0);
77
78  mpfr_set_ui (x, 0, MPFR_RNDZ);
79  d = mpfr_get_decimal64 (x, MPFR_RNDZ);
80  mpfr_set_ui (x, 1, MPFR_RNDZ);
81  mpfr_set_decimal64 (x, d, MPFR_RNDZ);
82  ASSERT_ALWAYS (mpfr_cmp_ui (x, 0) == 0 && MPFR_SIGN (x) > 0);
83
84  mpfr_set_ui (x, 0, MPFR_RNDZ);
85  mpfr_neg (x, x, MPFR_RNDZ);
86  d = mpfr_get_decimal64 (x, MPFR_RNDZ);
87  mpfr_set_ui (x, 1, MPFR_RNDZ);
88  mpfr_set_decimal64 (x, d, MPFR_RNDZ);
89  ASSERT_ALWAYS (mpfr_cmp_ui (x, 0) == 0 && MPFR_SIGN (x) < 0);
90
91  mpfr_set_ui (x, 1, MPFR_RNDZ);
92  d = mpfr_get_decimal64 (x, MPFR_RNDZ);
93  mpfr_set_ui (x, 0, MPFR_RNDZ);
94  mpfr_set_decimal64 (x, d, MPFR_RNDZ);
95  ASSERT_ALWAYS (mpfr_cmp_ui (x, 1) == 0);
96
97  mpfr_set_si (x, -1, MPFR_RNDZ);
98  d = mpfr_get_decimal64 (x, MPFR_RNDZ);
99  mpfr_set_ui (x, 0, MPFR_RNDZ);
100  mpfr_set_decimal64 (x, d, MPFR_RNDZ);
101  ASSERT_ALWAYS (mpfr_cmp_si (x, -1) == 0);
102
103  mpfr_set_ui (x, 2, MPFR_RNDZ);
104  d = mpfr_get_decimal64 (x, MPFR_RNDZ);
105  mpfr_set_ui (x, 0, MPFR_RNDZ);
106  mpfr_set_decimal64 (x, d, MPFR_RNDZ);
107  ASSERT_ALWAYS (mpfr_cmp_ui (x, 2) == 0);
108
109  mpfr_set_ui (x, 99, MPFR_RNDZ);
110  d = mpfr_get_decimal64 (x, MPFR_RNDZ);
111  mpfr_set_ui (x, 0, MPFR_RNDZ);
112  mpfr_set_decimal64 (x, d, MPFR_RNDZ);
113  ASSERT_ALWAYS (mpfr_cmp_ui (x, 99) == 0);
114
115  mpfr_set_str (x, "9999999999999999", 10, MPFR_RNDZ);
116  mpfr_set (y, x, MPFR_RNDZ);
117  d = mpfr_get_decimal64 (x, MPFR_RNDZ);
118  mpfr_set_ui (x, 0, MPFR_RNDZ);
119  mpfr_set_decimal64 (x, d, MPFR_RNDZ);
120  ASSERT_ALWAYS (mpfr_cmp (x, y) == 0);
121
122  /* smallest normal number */
123  mpfr_set_str (x, "1E-383", 10, MPFR_RNDU);
124  mpfr_set (y, x, MPFR_RNDZ);
125  d = mpfr_get_decimal64 (x, MPFR_RNDZ);
126  mpfr_set_ui (x, 0, MPFR_RNDZ);
127  mpfr_set_decimal64 (x, d, MPFR_RNDU);
128  ASSERT_ALWAYS (mpfr_cmp (x, y) == 0);
129
130  /* smallest subnormal number */
131  mpfr_set_str (x, "1E-398", 10, MPFR_RNDU);
132  mpfr_set (y, x, MPFR_RNDZ);
133  d = mpfr_get_decimal64 (x, MPFR_RNDZ);
134  mpfr_set_ui (x, 0, MPFR_RNDZ);
135  mpfr_set_decimal64 (x, d, MPFR_RNDU);
136  ASSERT_ALWAYS (mpfr_cmp (x, y) == 0);
137
138  /* subnormal number with exponent change when we round back
139     from 16 digits to 1 digit */
140  mpfr_set_str (x, "9.9E-398", 10, MPFR_RNDN);
141  d = mpfr_get_decimal64 (x, MPFR_RNDU); /* should be 1E-397 */
142  mpfr_set_ui (x, 0, MPFR_RNDZ);
143  mpfr_set_decimal64 (x, d, MPFR_RNDD);
144  mpfr_set_str (y, "1E-397", 10, MPFR_RNDN);
145  ASSERT_ALWAYS (mpfr_cmp (x, y) == 0);
146
147  /* largest number */
148  mpfr_set_str (x, "9.999999999999999E384", 10, MPFR_RNDZ);
149  mpfr_set (y, x, MPFR_RNDZ);
150  d = mpfr_get_decimal64 (x, MPFR_RNDU);
151  mpfr_set_ui (x, 0, MPFR_RNDZ);
152  mpfr_set_decimal64 (x, d, MPFR_RNDZ);
153  ASSERT_ALWAYS (mpfr_cmp (x, y) == 0);
154
155  mpfr_set_prec (x, 53);
156  mpfr_set_prec (y, 53);
157
158  /* largest number */
159  mpfr_set_str (x, "9.999999999999999E384", 10, MPFR_RNDZ);
160  d = mpfr_get_decimal64 (x, MPFR_RNDZ);
161  mpfr_set_decimal64 (y, d, MPFR_RNDU);
162  ASSERT_ALWAYS (mpfr_cmp (x, y) == 0);
163
164  mpfr_clear (x);
165  mpfr_clear (y);
166}
167
168static void
169check_random (void)
170{
171  mpfr_t  x, y;
172  _Decimal64 d;
173  int i;
174
175  mpfr_init2 (x, 49);
176  mpfr_init2 (y, 49);
177
178  for (i = 0; i < 100000; i++)
179    {
180      mpfr_urandomb (x, RANDS); /* 0 <= x < 1 */
181      /* the normal decimal64 range contains [2^(-1272), 2^1278] */
182      mpfr_mul_2si (x, x, (i % 2550) - 1272, MPFR_RNDN);
183      if (mpfr_get_exp (x) <= -1272)
184        mpfr_mul_2exp (x, x, -1271 - mpfr_get_exp (x), MPFR_RNDN);
185      d = mpfr_get_decimal64 (x, MPFR_RNDN);
186      mpfr_set_decimal64 (y, d, MPFR_RNDN);
187      if (mpfr_cmp (x, y) != 0)
188        {
189          printf ("x="); mpfr_dump (x);
190          printf ("d="); print_decimal64 (d);
191          printf ("y="); mpfr_dump (y);
192          exit (1);
193        }
194    }
195
196  mpfr_clear (x);
197  mpfr_clear (y);
198}
199
200/* check with native decimal formats */
201static void
202check_native (void)
203{
204  mpfr_t x;
205  _Decimal64 d;
206
207  mpfr_init2 (x, 53);
208
209  /* check important constants are correctly converted */
210  mpfr_set_ui (x, 17, MPFR_RNDN);
211  d = mpfr_get_decimal64 (x, MPFR_RNDN);
212  MPFR_ASSERTN(d == 17.0dd);
213
214  mpfr_set_ui (x, 42, MPFR_RNDN);
215  d = mpfr_get_decimal64 (x, MPFR_RNDN);
216  MPFR_ASSERTN(d == 42.0dd);
217
218  mpfr_set_decimal64 (x, 17.0dd, MPFR_RNDN);
219  MPFR_ASSERTN(mpfr_cmp_ui (x, 17) == 0);
220
221  mpfr_set_decimal64 (x, 42.0dd, MPFR_RNDN);
222  MPFR_ASSERTN(mpfr_cmp_ui (x, 42) == 0);
223
224  mpfr_clear (x);
225}
226#endif /* MPFR_WANT_DECIMAL_FLOATS */
227
228int
229main (void)
230{
231  tests_start_mpfr ();
232  mpfr_test_init ();
233
234#ifdef MPFR_WANT_DECIMAL_FLOATS
235#ifdef DEBUG
236#ifdef DPD_FORMAT
237  printf ("Using DPD format\n");
238#else
239  printf ("Using BID format\n");
240#endif
241#endif
242  check_inf_nan ();
243  check_random ();
244  check_native ();
245#endif
246
247  tests_end_mpfr ();
248  return 0;
249}
250