xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/tmul_2exp.c (revision a5847cc334d9a7029f6352b847e9e8d71a0f9e0c)
1 /* Test file for mpfr_{mul,div}_2{ui,si}.
2 
3 Copyright 1999, 2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
4 Contributed by the Arenaire and Cacao 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
105                     printf ("%ld", e);
106                   printf (") with mpfr_%s,\nx = %d/16, prec = %d, k = %d, "
107                           "%s\n", div == 0 ? "mul_2si" : div == 1 ?
108                           "div_2si" : "div_2ui", i, prec, k,
109                           mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
110                   printf ("Expected ");
111                   mpfr_out_str (stdout, 16, 0, z1, MPFR_RNDN);
112                   printf (", inex = %d, flags = %u\n", SIGN (inex1), flags1);
113                   printf ("Got      ");
114                   mpfr_out_str (stdout, 16, 0, z2, MPFR_RNDN);
115                   printf (", inex = %d, flags = %u\n", SIGN (inex2), flags2);
116                   exit (1);
117                 }  /* div */
118               }  /* k */
119           mpfr_clears (z1, z2, (mpfr_ptr) 0);
120         }  /* prec */
121     }  /* i */
122   mpfr_clears (x, y, (mpfr_ptr) 0);
123   set_emin (emin);
124 }
125 
126 static void
127 underflow0 (void)
128 {
129   underflow (-256);
130   if (mpfr_get_emin () != MPFR_EMIN_MIN)
131     underflow (mpfr_get_emin ());
132   underflow (MPFR_EMIN_MIN);
133 }
134 
135 static void
136 large (mpfr_exp_t e)
137 {
138   mpfr_t x, y, z;
139   mpfr_exp_t emax;
140   int inex;
141   unsigned int flags;
142 
143   emax = mpfr_get_emax ();
144   set_emax (e);
145   mpfr_init2 (x, 8);
146   mpfr_init2 (y, 8);
147   mpfr_init2 (z, 4);
148 
149   mpfr_set_inf (x, 1);
150   mpfr_nextbelow (x);
151 
152   mpfr_mul_2si (y, x, -1, MPFR_RNDU);
153   mpfr_prec_round (y, 4, MPFR_RNDU);
154 
155   mpfr_clear_flags ();
156   inex = mpfr_mul_2si (z, x, -1, MPFR_RNDU);
157   flags = __gmpfr_flags;
158 
159   if (inex <= 0 || flags != MPFR_FLAGS_INEXACT || ! mpfr_equal_p (y, z))
160     {
161       printf ("Error in large(");
162       if (e == MPFR_EMAX_MAX)
163         printf ("MPFR_EMAX_MAX");
164       else if (e == emax)
165         printf ("default emax");
166       else if (e <= LONG_MAX)
167         printf ("%ld", (long) e);
168       else
169         printf (">LONG_MAX");
170       printf (") for mpfr_mul_2si\n");
171       printf ("Expected inex > 0, flags = %u,\n         y = ",
172               (unsigned int) MPFR_FLAGS_INEXACT);
173       mpfr_dump (y);
174       printf ("Got      inex = %d, flags = %u,\n         y = ",
175               inex, flags);
176       mpfr_dump (z);
177       exit (1);
178     }
179 
180   mpfr_clear_flags ();
181   inex = mpfr_div_2si (z, x, 1, MPFR_RNDU);
182   flags = __gmpfr_flags;
183 
184   if (inex <= 0 || flags != MPFR_FLAGS_INEXACT || ! mpfr_equal_p (y, z))
185     {
186       printf ("Error in large(");
187       if (e == MPFR_EMAX_MAX)
188         printf ("MPFR_EMAX_MAX");
189       else if (e == emax)
190         printf ("default emax");
191       else if (e <= LONG_MAX)
192         printf ("%ld", (long) e);
193       else
194         printf (">LONG_MAX");
195       printf (") for mpfr_div_2si\n");
196       printf ("Expected inex > 0, flags = %u,\n         y = ",
197               (unsigned int) MPFR_FLAGS_INEXACT);
198       mpfr_dump (y);
199       printf ("Got      inex = %d, flags = %u,\n         y = ",
200               inex, flags);
201       mpfr_dump (z);
202       exit (1);
203     }
204 
205   mpfr_clear_flags ();
206   inex = mpfr_div_2ui (z, x, 1, MPFR_RNDU);
207   flags = __gmpfr_flags;
208 
209   if (inex <= 0 || flags != MPFR_FLAGS_INEXACT || ! mpfr_equal_p (y, z))
210     {
211       printf ("Error in large(");
212       if (e == MPFR_EMAX_MAX)
213         printf ("MPFR_EMAX_MAX");
214       else if (e == emax)
215         printf ("default emax");
216       else if (e <= LONG_MAX)
217         printf ("%ld", (long) e);
218       else
219         printf (">LONG_MAX");
220       printf (") for mpfr_div_2ui\n");
221       printf ("Expected inex > 0, flags = %u,\n         y = ",
222               (unsigned int) MPFR_FLAGS_INEXACT);
223       mpfr_dump (y);
224       printf ("Got      inex = %d, flags = %u,\n         y = ",
225               inex, flags);
226       mpfr_dump (z);
227       exit (1);
228     }
229 
230   mpfr_clears (x, y, z, (mpfr_ptr) 0);
231   set_emax (emax);
232 }
233 
234 static void
235 large0 (void)
236 {
237   large (256);
238   if (mpfr_get_emax () != MPFR_EMAX_MAX)
239     large (mpfr_get_emax ());
240   large (MPFR_EMAX_MAX);
241 }
242 
243 int
244 main (int argc, char *argv[])
245 {
246   mpfr_t w,z;
247   unsigned long k;
248   int i;
249 
250   tests_start_mpfr ();
251 
252   mpfr_inits2 (53, w, z, (mpfr_ptr) 0);
253 
254   for (i = 0; i < 3; i++)
255     {
256       mpfr_set_inf (w, 1);
257       test_mul (i, 0, w, w, 10, MPFR_RNDZ);
258       if (!MPFR_IS_INF(w))
259         {
260           printf ("Result is not Inf (i = %d)\n", i);
261           exit (1);
262         }
263 
264       mpfr_set_nan (w);
265       test_mul (i, 0, w, w, 10, MPFR_RNDZ);
266       if (!MPFR_IS_NAN(w))
267         {
268           printf ("Result is not NaN (i = %d)\n", i);
269           exit (1);
270         }
271 
272       for (k = 0 ; k < numberof(val) ; k+=3)
273         {
274           mpfr_set_str (w, val[k], 16, MPFR_RNDN);
275           test_mul (i, 0, z, w, 10, MPFR_RNDZ);
276           if (mpfr_cmp_str (z, val[k+1], 16, MPFR_RNDN))
277             {
278               printf ("ERROR for x * 2^n (i = %d) for %s\n", i, val[k]);
279               printf ("Expected: %s\n"
280                       "Got     : ", val[k+1]);
281               mpfr_out_str (stdout, 16, 0, z, MPFR_RNDN);
282               putchar ('\n');
283               exit (1);
284             }
285           test_mul (i, 1, z, w, 10, MPFR_RNDZ);
286           if (mpfr_cmp_str (z, val[k+2], 16, MPFR_RNDN))
287             {
288               printf ("ERROR for x / 2^n (i = %d) for %s\n", i, val[k]);
289               printf ("Expected: %s\n"
290                       "Got     : ", val[k+2]);
291               mpfr_out_str (stdout, 16, 0, z, MPFR_RNDN);
292               putchar ('\n');
293               exit (1);
294             }
295         }
296 
297       mpfr_set_inf (w, 1);
298       mpfr_nextbelow (w);
299       test_mul (i, 0, w, w, 1, MPFR_RNDN);
300       if (!mpfr_inf_p (w))
301         {
302           printf ("Overflow error (i = %d)!\n", i);
303           exit (1);
304         }
305       mpfr_set_ui (w, 0, MPFR_RNDN);
306       mpfr_nextabove (w);
307       test_mul (i, 1, w, w, 1, MPFR_RNDN);
308       if (mpfr_cmp_ui (w, 0))
309         {
310           printf ("Underflow error (i = %d)!\n", i);
311           exit (1);
312         }
313     }
314 
315   if (MPFR_EXP_MAX >= LONG_MAX/2 && MPFR_EXP_MIN <= LONG_MAX/2-LONG_MAX-1)
316     {
317       unsigned long lmp1 = (unsigned long) LONG_MAX + 1;
318 
319       mpfr_set_ui (w, 1, MPFR_RNDN);
320       mpfr_mul_2ui (w, w, LONG_MAX/2, MPFR_RNDZ);
321       mpfr_div_2ui (w, w, lmp1, MPFR_RNDZ);
322       mpfr_mul_2ui (w, w, lmp1 - LONG_MAX/2, MPFR_RNDZ);
323       if (!mpfr_cmp_ui (w, 1))
324         {
325           printf ("Underflow LONG_MAX error!\n");
326           exit (1);
327         }
328     }
329 
330   mpfr_clears (w, z, (mpfr_ptr) 0);
331 
332   underflow0 ();
333   large0 ();
334 
335   tests_end_mpfr ();
336   return 0;
337 }
338