xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/tget_f.c (revision 9573673d78c64ea1eac42d7f2e9521be89932ae5)
1 /* Test file for mpfr_get_f.
2 
3 Copyright 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
4 Contributed by the AriC and Caramel 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 <limits.h>
26 
27 #include "mpfr-test.h"
28 
29 /* Test that there is no lost of accuracy when converting a mpfr_t number
30    into a mpf_t number (test with various precisions and exponents). */
31 static void
32 prec_test (void)
33 {
34   int px, py;
35 
36   for (py = 3; py <= 136; py++)
37     {
38       mpfr_t y1, y2, y3;
39 
40       mpfr_init2 (y1, py);
41       mpfr_init2 (y2, py);
42       mpfr_init2 (y3, py);
43 
44       for (px = 32; px <= 160; px += 32)
45         {
46           mpf_t x1, x2, x3;
47           int e;
48 
49           mpf_init (x1);
50           mpf_init (x2);
51           mpf_init (x3);
52           mpfr_set_ui_2exp (y1, 1, py - 1, MPFR_RNDN);
53           mpfr_get_f (x1, y1, MPFR_RNDN);  /* exact (power of 2) */
54           mpf_set (x2, x1);
55           mpfr_set (y2, y1, MPFR_RNDN);
56 
57           for (e = py - 2; e >= 0; e--)
58             {
59               int inex;
60               mpf_div_2exp (x2, x2, 1);
61               mpf_add (x1, x1, x2);
62               mpfr_div_2exp (y2, y2, 1, MPFR_RNDN);
63               inex = mpfr_add (y1, y1, y2, MPFR_RNDN);
64               MPFR_ASSERTN (inex == 0);
65               mpfr_set_f (y3, x1, MPFR_RNDN);
66               if (! mpfr_equal_p (y1, y3))
67                 break;
68               inex = mpfr_get_f (x3, y3, MPFR_RNDN);
69               if (mpf_cmp (x1, x3) != 0)
70                 {
71                   printf ("Error in prec_test (px = %d, py = %d, e = %d)\n",
72                           px, py, e);
73                   printf ("x1 = ");
74                   mpf_out_str (stdout, 16, 0, x1);
75                   printf ("\nx2 = ");
76                   mpf_out_str (stdout, 16, 0, x2);
77                   printf ("\n");
78                   exit (1);
79                 }
80               if (inex != 0)
81                 {
82                   printf ("Error in prec_test (px = %d, py = %d, e = %d)\n",
83                           px, py, e);
84                   printf ("wrong ternary value got: %+d, expected: 0\n",
85                           inex);
86                   exit (1);
87                 }
88             }
89 
90           mpf_clear (x1);
91           mpf_clear (x2);
92           mpf_clear (x3);
93         }
94 
95       mpfr_clear (y1);
96       mpfr_clear (y2);
97       mpfr_clear (y3);
98     }
99 }
100 
101 static void
102 special_test (void)
103 {
104   int inex;
105   mpf_t x;
106   mpfr_t y;
107 
108   mpfr_init (y);
109   mpf_init (x);
110 
111   mpfr_set_nan (y);
112   mpfr_clear_flags ();
113   mpfr_get_f (x, y, MPFR_RNDN);
114   if (! mpfr_erangeflag_p ())
115     {
116       printf ("Error: mpfr_get_f(NaN) should raise erange flag\n");
117       exit (1);
118     }
119 
120   mpfr_set_inf (y, +1);
121   mpfr_clear_flags ();
122   inex = mpfr_get_f (x, y, MPFR_RNDN);
123   if (inex >= 0)
124     {
125       printf ("Error: mpfr_get_f(+Inf) should return a negative ternary"
126               "value\n");
127       exit (1);
128     }
129   if (! mpfr_erangeflag_p ())
130     {
131       printf ("Error: mpfr_get_f(+Inf) should raise erange flag\n");
132       exit (1);
133     }
134 
135   mpfr_set_inf (y, -1);
136   mpfr_clear_flags ();
137   inex = mpfr_get_f (x, y, MPFR_RNDN);
138   if (inex <= 0)
139     {
140       printf ("Error: mpfr_get_f(-Inf) should return a positive ternary"
141               "value\n");
142       exit (1);
143     }
144   if (! mpfr_erangeflag_p ())
145     {
146       printf ("Error: mpfr_get_f(-Inf) should raise erange flag\n");
147       exit (1);
148     }
149 
150   mpfr_set_ui (y, 0, MPFR_RNDN);
151   if (mpfr_get_f (x, y, MPFR_RNDN) != 0 || mpf_cmp_ui (x, 0))
152     {
153       printf ("Error: mpfr_get_f(+0) fails\n");
154       exit (1);
155     }
156 
157   mpfr_set_ui (y, 0, MPFR_RNDN);
158   mpfr_neg (y, y, MPFR_RNDN);
159   if (mpfr_get_f (x, y, MPFR_RNDN) != 0 || mpf_cmp_ui (x, 0))
160     {
161       printf ("Error: mpfr_get_f(-0) fails\n");
162       exit (1);
163     }
164 
165   mpfr_clear (y);
166   mpf_clear (x);
167 }
168 
169 static void
170 ternary_test (void)
171 {
172   int prec;
173   int rnd;
174   int inex, expected_inex;
175   mpf_t x;
176   mpfr_t y;
177 
178   mpf_init2 (x, 256);
179   mpfr_init2 (y, 256);
180 
181   for (prec = 2; prec <= 256; prec++)
182     {
183 
184       mpf_set_prec (x, prec);
185       mpfr_set_prec (y, PREC (x) * GMP_NUMB_BITS + 1);
186 
187       /* y == 1 */
188       mpfr_set_ui_2exp (y, 1, prec, MPFR_RNDN);
189 
190       RND_LOOP (rnd)
191       {
192         inex = mpfr_get_f (x, y, (mpfr_rnd_t) rnd);
193 
194         if (inex != 0 || mpfr_cmp_f (y, x) !=0)
195           {
196             printf ("Error in mpfr_get_f (x, y, %s)\nx = ",
197                     mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
198             mpf_out_str (stdout, 2, 0, x);
199             printf ("\ny = ");
200             mpfr_dump (y);
201             if (inex != 0)
202               printf ("got ternary value = %+d, expected: 0\n", inex);
203 
204             exit (1);
205           }
206       }
207 
208       /* y == 1 + epsilon */
209       mpfr_nextbelow (y);
210 
211       RND_LOOP (rnd)
212       {
213         switch (rnd)
214           {
215           case MPFR_RNDU: case MPFR_RNDA:
216           case MPFR_RNDN:
217             expected_inex = +1;
218             break;
219           default :
220             expected_inex = -1;
221           }
222 
223         inex = mpfr_get_f (x, y, (mpfr_rnd_t) rnd);
224 
225         if (! SAME_SIGN (expected_inex, inex)
226             || SAME_SIGN (expected_inex, mpfr_cmp_f (y, x)))
227           {
228             printf ("Error in mpfr_get_f (x, y, %s)\nx = ",
229                     mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
230             mpf_out_str (stdout, 2, 0, x);
231             printf ("\ny = ");
232             mpfr_dump (y);
233             if (! SAME_SIGN (expected_inex, inex))
234               printf ("got ternary value = %+d, expected: %+d\n",
235                       inex, expected_inex);
236 
237             exit (1);
238           }
239       }
240 
241       /* y == positive random float */
242       mpfr_random2 (y, MPFR_LIMB_SIZE (y), 1024, RANDS);
243 
244       RND_LOOP (rnd)
245       {
246         inex = mpfr_get_f (x, y, (mpfr_rnd_t) rnd);
247 
248         if (! SAME_SIGN (inex, -mpfr_cmp_f (y, x)))
249           {
250             printf ("Error in mpfr_get_f (x, y, %s)\nx = ",
251                     mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
252             mpf_out_str (stdout, 2, 0, x);
253             printf ("\ny = ");
254             mpfr_dump (y);
255             printf ("got ternary value = %+d, expected: %+d\n",
256                     inex, -mpfr_cmp_f (y, x));
257 
258             exit (1);
259           }
260       }
261     }
262 
263   mpf_clear (x);
264   mpfr_clear (y);
265 }
266 
267 int
268 main (void)
269 {
270   mpf_t x;
271   mpfr_t y, z;
272   unsigned long i;
273   mpfr_exp_t e;
274   int inex;
275 
276   tests_start_mpfr ();
277 
278   mpfr_init (y);
279   mpfr_init (z);
280   mpf_init (x);
281 
282   i = 1;
283   while (i)
284     {
285       mpfr_set_ui (y, i, MPFR_RNDN);
286       if (mpfr_get_f (x, y, MPFR_RNDN) != 0 || mpf_cmp_ui (x, i))
287         {
288           printf ("Error: mpfr_get_f(%lu) fails\n", i);
289           exit (1);
290         }
291       if (i <= - (unsigned long) LONG_MIN)
292         {
293           long j = i < - (unsigned long) LONG_MIN ? - (long) i : LONG_MIN;
294           mpfr_set_si (y, j, MPFR_RNDN);
295           if (mpfr_get_f (x, y, MPFR_RNDN) != 0 || mpf_cmp_si (x, j))
296             {
297               printf ("Error: mpfr_get_f(-%lu) fails\n", i);
298               exit (1);
299             }
300         }
301       i *= 2;
302     }
303 
304   /* same tests, but with a larger precision for y, which requires to
305      round it */
306   mpfr_set_prec (y, 100);
307   i = 1;
308   while (i)
309     {
310       mpfr_set_ui (y, i, MPFR_RNDN);
311       inex = mpfr_get_f (x, y, MPFR_RNDN);
312       if (! SAME_SIGN (inex, - mpfr_cmp_f (y, x)) || mpf_cmp_ui (x, i))
313         {
314           printf ("Error: mpfr_get_f(%lu) fails\n", i);
315           exit (1);
316         }
317       mpfr_set_si (y, (signed long) -i, MPFR_RNDN);
318       inex = mpfr_get_f (x, y, MPFR_RNDN);
319       if (! SAME_SIGN (inex, - mpfr_cmp_f (y, x))
320           || mpf_cmp_si (x, (signed long) -i))
321         {
322           printf ("Error: mpfr_get_f(-%lu) fails\n", i);
323           exit (1);
324         }
325       i *= 2;
326     }
327 
328   /* bug reported by Jim White */
329   for (e = 0; e <= 2 * GMP_NUMB_BITS; e++)
330     {
331       /* test with 2^(-e) */
332       mpfr_set_ui (y, 1, MPFR_RNDN);
333       mpfr_div_2exp (y, y, e, MPFR_RNDN);
334       inex = mpfr_get_f (x, y, MPFR_RNDN);
335       mpf_mul_2exp (x, x, e);
336       if (inex != 0 || mpf_cmp_ui (x, 1) != 0)
337         {
338           printf ("Error: mpfr_get_f(x,y,MPFR_RNDN) fails\n");
339           printf ("y=");
340           mpfr_dump (y);
341           printf ("x=");
342           mpf_div_2exp (x, x, e);
343           mpf_out_str (stdout, 2, 0, x);
344           exit (1);
345         }
346 
347       /* test with 2^(e) */
348       mpfr_set_ui (y, 1, MPFR_RNDN);
349       mpfr_mul_2exp (y, y, e, MPFR_RNDN);
350       inex = mpfr_get_f (x, y, MPFR_RNDN);
351       mpf_div_2exp (x, x, e);
352       if (inex != 0 || mpf_cmp_ui (x, 1) != 0)
353         {
354           printf ("Error: mpfr_get_f(x,y,MPFR_RNDN) fails\n");
355           printf ("y=");
356           mpfr_dump (y);
357           printf ("x=");
358           mpf_mul_2exp (x, x, e);
359           mpf_out_str (stdout, 2, 0, x);
360           exit (1);
361         }
362     }
363 
364   /* Bug reported by Yury Lukach on 2006-04-05 */
365   mpfr_set_prec (y, 32);
366   mpfr_set_prec (z, 32);
367   mpf_set_prec (x, 32);
368   mpfr_set_ui_2exp (y, 0xc1234567, -30, MPFR_RNDN);
369   mpfr_get_f (x, y, MPFR_RNDN);
370   inex = mpfr_set_f (z, x, MPFR_RNDN);
371   if (inex != 0 || ! mpfr_equal_p (y, z))
372     {
373       printf ("Error in mpfr_get_f:\n  inex = %d, y = ", inex);
374       mpfr_dump (z);
375       printf ("Expected:\n  inex = 0, y = ");
376       mpfr_dump (y);
377       exit (1);
378     }
379 
380   mpfr_clear (y);
381   mpfr_clear (z);
382   mpf_clear (x);
383 
384   special_test ();
385   prec_test ();
386   ternary_test ();
387 
388   tests_end_mpfr ();
389   return 0;
390 }
391