xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/tmul_2exp.c (revision fa28c6faa16e0b00edee7acdcaf4899797043def)
1 /* Test file for mpfr_{mul,div}_2{ui,si}.
2 
3 Copyright 1999, 2001, 2002, 2003, 2004, 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 
26 #include "mpfr-test.h"
27 
28 static const char * const val[] = {
29   "1.0001@100","4.0004000000000@102", "4.0004000000000@97",
30   "1.ABF012345@-100","6.afc048d140000@-98","6.afc048d140000@-103",
31   "F.FFFFFFFFF@10000","3.fffffffffc000@10003","3.fffffffffc000@9998",
32   "1.23456789ABCDEF@42","4.8d159e26af37c@44","4.8d159e26af37c@39",
33   "17@42","5.c000000000000@45","5.c000000000000@40",
34   "42@-17","1.0800000000000@-13","1.0800000000000@-18"
35 };
36 
37 static int
38 test_mul (int i, int div, mpfr_ptr y, mpfr_srcptr x,
39           unsigned long int n, mpfr_rnd_t r)
40 {
41   return
42     i == 0 ? (div ? mpfr_div_2ui : mpfr_mul_2ui) (y, x, n, r) :
43     i == 1 ? (div ? mpfr_div_2si : mpfr_mul_2si) (y, x, n, r) :
44     i == 2 ? (div ? mpfr_mul_2si : mpfr_div_2si) (y, x, -n, r) :
45     (exit (1), 0);
46 }
47 
48 static void
49 underflow (mpfr_exp_t e)
50 {
51   mpfr_t x, y, z1, z2;
52   mpfr_exp_t emin;
53   int i, k;
54   int prec;
55   int rnd;
56   int div;
57   int inex1, inex2;
58   unsigned int flags1, flags2;
59 
60   /* Test mul_2si(x, e - k), div_2si(x, k - e) and div_2ui(x, k - e)
61    * with emin = e, x = 1 + i/16, i in { -1, 0, 1 }, and k = 1 to 4,
62    * by comparing the result with the one of a simple division.
63    */
64   emin = mpfr_get_emin ();
65   set_emin (e);
66   mpfr_inits2 (8, x, y, (mpfr_ptr) 0);
67   for (i = 15; i <= 17; i++)
68     {
69       inex1 = mpfr_set_ui_2exp (x, i, -4, MPFR_RNDN);
70       MPFR_ASSERTN (inex1 == 0);
71       for (prec = 6; prec >= 3; prec -= 3)
72         {
73           mpfr_inits2 (prec, z1, z2, (mpfr_ptr) 0);
74           RND_LOOP (rnd)
75             for (k = 1; k <= 4; k++)
76               {
77                 /* The following one is assumed to be correct. */
78                 inex1 = mpfr_mul_2si (y, x, e, MPFR_RNDN);
79                 MPFR_ASSERTN (inex1 == 0);
80                 inex1 = mpfr_set_ui (z1, 1 << k, MPFR_RNDN);
81                 MPFR_ASSERTN (inex1 == 0);
82                 mpfr_clear_flags ();
83                 /* Do not use mpfr_div_ui to avoid the optimization
84                    by mpfr_div_2si. */
85                 inex1 = mpfr_div (z1, y, z1, (mpfr_rnd_t) rnd);
86                 flags1 = __gmpfr_flags;
87 
88               for (div = 0; div <= 2; div++)
89                 {
90                   mpfr_clear_flags ();
91                   inex2 = div == 0 ?
92                     mpfr_mul_2si (z2, x, e - k, (mpfr_rnd_t) rnd) : div == 1 ?
93                     mpfr_div_2si (z2, x, k - e, (mpfr_rnd_t) rnd) :
94                     mpfr_div_2ui (z2, x, k - e, (mpfr_rnd_t) rnd);
95                   flags2 = __gmpfr_flags;
96                   if (flags1 == flags2 && SAME_SIGN (inex1, inex2) &&
97                       mpfr_equal_p (z1, z2))
98                     continue;
99                   printf ("Error in underflow(");
100                   if (e == MPFR_EMIN_MIN)
101                     printf ("MPFR_EMIN_MIN");
102                   else if (e == emin)
103                     printf ("default emin");
104                   else if (e >= LONG_MIN)
105                     printf ("%ld", (long) e);
106                   else
107                     printf ("<LONG_MIN");
108                   printf (") with mpfr_%s,\nx = %d/16, prec = %d, k = %d, "
109                           "%s\n", div == 0 ? "mul_2si" : div == 1 ?
110                           "div_2si" : "div_2ui", i, prec, k,
111                           mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
112                   printf ("Expected ");
113                   mpfr_out_str (stdout, 16, 0, z1, MPFR_RNDN);
114                   printf (", inex = %d, flags = %u\n", SIGN (inex1), flags1);
115                   printf ("Got      ");
116                   mpfr_out_str (stdout, 16, 0, z2, MPFR_RNDN);
117                   printf (", inex = %d, flags = %u\n", SIGN (inex2), flags2);
118                   exit (1);
119                 }  /* div */
120               }  /* k */
121           mpfr_clears (z1, z2, (mpfr_ptr) 0);
122         }  /* prec */
123     }  /* i */
124   mpfr_clears (x, y, (mpfr_ptr) 0);
125   set_emin (emin);
126 }
127 
128 static void
129 underflow0 (void)
130 {
131   underflow (-256);
132   if (mpfr_get_emin () != MPFR_EMIN_MIN)
133     underflow (mpfr_get_emin ());
134   underflow (MPFR_EMIN_MIN);
135 }
136 
137 static void
138 large (mpfr_exp_t e)
139 {
140   mpfr_t x, y, z;
141   mpfr_exp_t emax;
142   int inex;
143   unsigned int flags;
144 
145   emax = mpfr_get_emax ();
146   set_emax (e);
147   mpfr_init2 (x, 8);
148   mpfr_init2 (y, 8);
149   mpfr_init2 (z, 4);
150 
151   mpfr_set_inf (x, 1);
152   mpfr_nextbelow (x);
153 
154   mpfr_mul_2si (y, x, -1, MPFR_RNDU);
155   mpfr_prec_round (y, 4, MPFR_RNDU);
156 
157   mpfr_clear_flags ();
158   inex = mpfr_mul_2si (z, x, -1, MPFR_RNDU);
159   flags = __gmpfr_flags;
160 
161   if (inex <= 0 || flags != MPFR_FLAGS_INEXACT || ! mpfr_equal_p (y, z))
162     {
163       printf ("Error in large(");
164       if (e == MPFR_EMAX_MAX)
165         printf ("MPFR_EMAX_MAX");
166       else if (e == emax)
167         printf ("default emax");
168       else if (e <= LONG_MAX)
169         printf ("%ld", (long) e);
170       else
171         printf (">LONG_MAX");
172       printf (") for mpfr_mul_2si\n");
173       printf ("Expected inex > 0, flags = %u,\n         y = ",
174               (unsigned int) MPFR_FLAGS_INEXACT);
175       mpfr_dump (y);
176       printf ("Got      inex = %d, flags = %u,\n         y = ",
177               inex, flags);
178       mpfr_dump (z);
179       exit (1);
180     }
181 
182   mpfr_clear_flags ();
183   inex = mpfr_div_2si (z, x, 1, MPFR_RNDU);
184   flags = __gmpfr_flags;
185 
186   if (inex <= 0 || flags != MPFR_FLAGS_INEXACT || ! mpfr_equal_p (y, z))
187     {
188       printf ("Error in large(");
189       if (e == MPFR_EMAX_MAX)
190         printf ("MPFR_EMAX_MAX");
191       else if (e == emax)
192         printf ("default emax");
193       else if (e <= LONG_MAX)
194         printf ("%ld", (long) e);
195       else
196         printf (">LONG_MAX");
197       printf (") for mpfr_div_2si\n");
198       printf ("Expected inex > 0, flags = %u,\n         y = ",
199               (unsigned int) MPFR_FLAGS_INEXACT);
200       mpfr_dump (y);
201       printf ("Got      inex = %d, flags = %u,\n         y = ",
202               inex, flags);
203       mpfr_dump (z);
204       exit (1);
205     }
206 
207   mpfr_clear_flags ();
208   inex = mpfr_div_2ui (z, x, 1, MPFR_RNDU);
209   flags = __gmpfr_flags;
210 
211   if (inex <= 0 || flags != MPFR_FLAGS_INEXACT || ! mpfr_equal_p (y, z))
212     {
213       printf ("Error in large(");
214       if (e == MPFR_EMAX_MAX)
215         printf ("MPFR_EMAX_MAX");
216       else if (e == emax)
217         printf ("default emax");
218       else if (e <= LONG_MAX)
219         printf ("%ld", (long) e);
220       else
221         printf (">LONG_MAX");
222       printf (") for mpfr_div_2ui\n");
223       printf ("Expected inex > 0, flags = %u,\n         y = ",
224               (unsigned int) MPFR_FLAGS_INEXACT);
225       mpfr_dump (y);
226       printf ("Got      inex = %d, flags = %u,\n         y = ",
227               inex, flags);
228       mpfr_dump (z);
229       exit (1);
230     }
231 
232   mpfr_clears (x, y, z, (mpfr_ptr) 0);
233   set_emax (emax);
234 }
235 
236 static void
237 large0 (void)
238 {
239   large (256);
240   if (mpfr_get_emax () != MPFR_EMAX_MAX)
241     large (mpfr_get_emax ());
242   large (MPFR_EMAX_MAX);
243 }
244 
245 int
246 main (int argc, char *argv[])
247 {
248   mpfr_t w,z;
249   unsigned long k;
250   int i;
251 
252   tests_start_mpfr ();
253 
254   mpfr_inits2 (53, w, z, (mpfr_ptr) 0);
255 
256   for (i = 0; i < 3; i++)
257     {
258       mpfr_set_inf (w, 1);
259       test_mul (i, 0, w, w, 10, MPFR_RNDZ);
260       if (!MPFR_IS_INF(w))
261         {
262           printf ("Result is not Inf (i = %d)\n", i);
263           exit (1);
264         }
265 
266       mpfr_set_nan (w);
267       test_mul (i, 0, w, w, 10, MPFR_RNDZ);
268       if (!MPFR_IS_NAN(w))
269         {
270           printf ("Result is not NaN (i = %d)\n", i);
271           exit (1);
272         }
273 
274       for (k = 0 ; k < numberof(val) ; k+=3)
275         {
276           mpfr_set_str (w, val[k], 16, MPFR_RNDN);
277           test_mul (i, 0, z, w, 10, MPFR_RNDZ);
278           if (mpfr_cmp_str (z, val[k+1], 16, MPFR_RNDN))
279             {
280               printf ("ERROR for x * 2^n (i = %d) for %s\n", i, val[k]);
281               printf ("Expected: %s\n"
282                       "Got     : ", val[k+1]);
283               mpfr_out_str (stdout, 16, 0, z, MPFR_RNDN);
284               putchar ('\n');
285               exit (1);
286             }
287           test_mul (i, 1, z, w, 10, MPFR_RNDZ);
288           if (mpfr_cmp_str (z, val[k+2], 16, MPFR_RNDN))
289             {
290               printf ("ERROR for x / 2^n (i = %d) for %s\n", i, val[k]);
291               printf ("Expected: %s\n"
292                       "Got     : ", val[k+2]);
293               mpfr_out_str (stdout, 16, 0, z, MPFR_RNDN);
294               putchar ('\n');
295               exit (1);
296             }
297         }
298 
299       mpfr_set_inf (w, 1);
300       mpfr_nextbelow (w);
301       test_mul (i, 0, w, w, 1, MPFR_RNDN);
302       if (!mpfr_inf_p (w))
303         {
304           printf ("Overflow error (i = %d)!\n", i);
305           exit (1);
306         }
307       mpfr_set_ui (w, 0, MPFR_RNDN);
308       mpfr_nextabove (w);
309       test_mul (i, 1, w, w, 1, MPFR_RNDN);
310       if (mpfr_cmp_ui (w, 0))
311         {
312           printf ("Underflow error (i = %d)!\n", i);
313           exit (1);
314         }
315     }
316 
317   if (MPFR_EXP_MAX >= LONG_MAX/2 && MPFR_EXP_MIN <= LONG_MAX/2-LONG_MAX-1)
318     {
319       unsigned long lmp1 = (unsigned long) LONG_MAX + 1;
320 
321       mpfr_set_ui (w, 1, MPFR_RNDN);
322       mpfr_mul_2ui (w, w, LONG_MAX/2, MPFR_RNDZ);
323       mpfr_div_2ui (w, w, lmp1, MPFR_RNDZ);
324       mpfr_mul_2ui (w, w, lmp1 - LONG_MAX/2, MPFR_RNDZ);
325       if (!mpfr_cmp_ui (w, 1))
326         {
327           printf ("Underflow LONG_MAX error!\n");
328           exit (1);
329         }
330     }
331 
332   mpfr_clears (w, z, (mpfr_ptr) 0);
333 
334   underflow0 ();
335   large0 ();
336 
337   tests_end_mpfr ();
338   return 0;
339 }
340