xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/tui_sub.c (revision 1b9578b8c2c1f848eeb16dabbfd7d1f0d9fdefbd)
1 /* Test file for mpfr_ui_sub.
2 
3 Copyright 2000, 2001, 2002, 2003, 2004, 2005, 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 #include <float.h>
26 
27 #include "mpfr-test.h"
28 
29 static void
30 special (void)
31 {
32   mpfr_t x, y, res;
33   int inexact;
34 
35   mpfr_init (x);
36   mpfr_init (y);
37   mpfr_init (res);
38 
39   mpfr_set_prec (x, 24);
40   mpfr_set_prec (y, 24);
41   mpfr_set_str_binary (y, "0.111100110001011010111");
42   inexact = mpfr_ui_sub (x, 1, y, MPFR_RNDN);
43   if (inexact)
44     {
45       printf ("Wrong inexact flag: got %d, expected 0\n", inexact);
46       exit (1);
47     }
48 
49   mpfr_set_prec (x, 24);
50   mpfr_set_prec (y, 24);
51   mpfr_set_str_binary (y, "0.111100110001011010111");
52   if ((inexact = mpfr_ui_sub (x, 38181761, y, MPFR_RNDN)) >= 0)
53     {
54       printf ("Wrong inexact flag: got %d, expected -1\n", inexact);
55       exit (1);
56     }
57 
58   mpfr_set_prec (x, 63);
59   mpfr_set_prec (y, 63);
60   mpfr_set_str_binary (y, "0.111110010010100100110101101010001001100101110001000101110111111E-1");
61   if ((inexact = mpfr_ui_sub (x, 1541116494, y, MPFR_RNDN)) <= 0)
62     {
63       printf ("Wrong inexact flag: got %d, expected +1\n", inexact);
64       exit (1);
65     }
66 
67   mpfr_set_prec (x, 32);
68   mpfr_set_prec (y, 32);
69   mpfr_set_str_binary (y, "0.11011000110111010001011100011100E-1");
70   if ((inexact = mpfr_ui_sub (x, 2000375416, y, MPFR_RNDN)) >= 0)
71     {
72       printf ("Wrong inexact flag: got %d, expected -1\n", inexact);
73       exit (1);
74     }
75 
76   mpfr_set_prec (x, 24);
77   mpfr_set_prec (y, 24);
78   mpfr_set_str_binary (y, "0.110011011001010011110111E-2");
79   if ((inexact = mpfr_ui_sub (x, 927694848, y, MPFR_RNDN)) <= 0)
80     {
81       printf ("Wrong inexact flag: got %d, expected +1\n", inexact);
82       exit (1);
83     }
84 
85   /* bug found by Mathieu Dutour, 12 Apr 2001 */
86   mpfr_set_prec (x, 5);
87   mpfr_set_prec (y, 5);
88   mpfr_set_prec (res, 5);
89   mpfr_set_str_binary (x, "1e-12");
90 
91   mpfr_ui_sub (y, 1, x, MPFR_RNDD);
92   mpfr_set_str_binary (res, "0.11111");
93   if (mpfr_cmp (y, res))
94     {
95       printf ("Error in mpfr_ui_sub (y, 1, x, MPFR_RNDD) for x=2^(-12)\nexpected 1.1111e-1, got ");
96       mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN);
97       printf ("\n");
98       exit (1);
99     }
100 
101   mpfr_ui_sub (y, 1, x, MPFR_RNDU);
102   mpfr_set_str_binary (res, "1.0");
103   if (mpfr_cmp (y, res))
104     {
105       printf ("Error in mpfr_ui_sub (y, 1, x, MPFR_RNDU) for x=2^(-12)\n"
106               "expected 1.0, got ");
107       mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN);
108       printf ("\n");
109       exit (1);
110     }
111 
112   mpfr_ui_sub (y, 1, x, MPFR_RNDN);
113   mpfr_set_str_binary (res, "1.0");
114   if (mpfr_cmp (y, res))
115     {
116       printf ("Error in mpfr_ui_sub (y, 1, x, MPFR_RNDN) for x=2^(-12)\n"
117               "expected 1.0, got ");
118       mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN);
119       printf ("\n");
120       exit (1);
121     }
122 
123   mpfr_set_prec (x, 10);
124   mpfr_set_prec (y, 10);
125   mpfr_urandomb (x, RANDS);
126   mpfr_ui_sub (y, 0, x, MPFR_RNDN);
127   if (MPFR_IS_ZERO(x))
128     MPFR_ASSERTN(MPFR_IS_ZERO(y));
129   else
130     MPFR_ASSERTN(mpfr_cmpabs (x, y) == 0 && mpfr_sgn (x) != mpfr_sgn (y));
131 
132   mpfr_set_prec (x, 73);
133   mpfr_set_str_binary (x, "0.1101111010101011011011100011010000000101110001011111001011011000101111101E-99");
134   mpfr_ui_sub (x, 1, x, MPFR_RNDZ);
135   mpfr_nextabove (x);
136   MPFR_ASSERTN(mpfr_cmp_ui (x, 1) == 0);
137 
138   mpfr_clear (x);
139   mpfr_clear (y);
140   mpfr_clear (res);
141 }
142 
143 /* checks that (y-x) gives the right results with 53 bits of precision */
144 static void
145 check (unsigned long y, const char *xs, mpfr_rnd_t rnd_mode, const char *zs)
146 {
147   mpfr_t xx, zz;
148 
149   mpfr_inits2 (53, xx, zz, (mpfr_ptr) 0);
150   mpfr_set_str1 (xx, xs);
151   mpfr_ui_sub (zz, y, xx, rnd_mode);
152   if (mpfr_cmp_str1 (zz, zs) )
153     {
154       printf ("expected difference is %s, got\n",zs);
155       mpfr_out_str(stdout, 10, 0, zz, MPFR_RNDN);
156       printf ("mpfr_ui_sub failed for y=%lu x=%s with rnd_mode=%s\n",
157               y, xs, mpfr_print_rnd_mode (rnd_mode));
158       exit (1);
159     }
160   mpfr_clears (xx, zz, (mpfr_ptr) 0);
161 }
162 
163 /* if u = o(x-y), v = o(u-x), w = o(v+y), then x-y = u-w */
164 static void
165 check_two_sum (mpfr_prec_t p)
166 {
167   unsigned int x;
168   mpfr_t y, u, v, w;
169   mpfr_rnd_t rnd;
170   int inexact;
171 
172   mpfr_inits2 (p, y, u, v, w, (mpfr_ptr) 0);
173   do
174     {
175       x = randlimb ();
176     }
177   while (x < 1);
178   mpfr_urandomb (y, RANDS);
179   rnd = MPFR_RNDN;
180   inexact = mpfr_ui_sub (u, x, y, rnd);
181   mpfr_sub_ui (v, u, x, rnd);
182   mpfr_add (w, v, y, rnd);
183   /* as u = (x-y) + w, we should have inexact and w of same sign */
184   if (((inexact == 0) && mpfr_cmp_ui (w, 0)) ||
185       ((inexact > 0) && (mpfr_cmp_ui (w, 0) <= 0)) ||
186       ((inexact < 0) && (mpfr_cmp_ui (w, 0) >= 0)))
187     {
188       printf ("Wrong inexact flag for prec=%u, rnd=%s\n",
189               (unsigned int) p, mpfr_print_rnd_mode (rnd));
190       printf ("x=%u\n", x);
191       printf ("y="); mpfr_print_binary(y); puts ("");
192       printf ("u="); mpfr_print_binary(u); puts ("");
193       printf ("v="); mpfr_print_binary(v); puts ("");
194       printf ("w="); mpfr_print_binary(w); puts ("");
195       printf ("inexact = %d\n", inexact);
196       exit (1);
197     }
198   mpfr_clears (y, u, v, w, (mpfr_ptr) 0);
199 }
200 
201 static void
202 check_nans (void)
203 {
204   mpfr_t  x, y;
205 
206   mpfr_init2 (x, 123L);
207   mpfr_init2 (y, 123L);
208 
209   /* 1 - nan == nan */
210   mpfr_set_nan (x);
211   mpfr_ui_sub (y, 1L, x, MPFR_RNDN);
212   MPFR_ASSERTN (mpfr_nan_p (y));
213 
214   /* 1 - +inf == -inf */
215   mpfr_set_inf (x, 1);
216   mpfr_ui_sub (y, 1L, x, MPFR_RNDN);
217   MPFR_ASSERTN (mpfr_inf_p (y));
218   MPFR_ASSERTN (mpfr_sgn (y) < 0);
219 
220   /* 1 - -inf == +inf */
221   mpfr_set_inf (x, -1);
222   mpfr_ui_sub (y, 1L, x, MPFR_RNDN);
223   MPFR_ASSERTN (mpfr_inf_p (y));
224   MPFR_ASSERTN (mpfr_sgn (y) > 0);
225 
226   mpfr_clear (x);
227   mpfr_clear (y);
228 }
229 
230 /* Check mpfr_ui_sub with u = 0 (unsigned). */
231 static void check_neg (void)
232 {
233   mpfr_t x, yneg, ysub;
234   int i, s;
235   int r;
236 
237   mpfr_init2 (x, 64);
238   mpfr_init2 (yneg, 32);
239   mpfr_init2 (ysub, 32);
240 
241   for (i = 0; i <= 25; i++)
242     {
243       mpfr_sqrt_ui (x, i, MPFR_RNDN);
244       for (s = 0; s <= 1; s++)
245         {
246           RND_LOOP (r)
247             {
248               int tneg, tsub;
249 
250               tneg = mpfr_neg (yneg, x, (mpfr_rnd_t) r);
251               tsub = mpfr_ui_sub (ysub, 0, x, (mpfr_rnd_t) r);
252               MPFR_ASSERTN (mpfr_equal_p (yneg, ysub));
253               MPFR_ASSERTN (!(MPFR_IS_POS (yneg) ^ MPFR_IS_POS (ysub)));
254               MPFR_ASSERTN (tneg == tsub);
255             }
256           mpfr_neg (x, x, MPFR_RNDN);
257         }
258     }
259 
260   mpfr_clear (x);
261   mpfr_clear (yneg);
262   mpfr_clear (ysub);
263 }
264 
265 int
266 main (int argc, char *argv[])
267 {
268   mpfr_prec_t p;
269   unsigned k;
270 
271   tests_start_mpfr ();
272 
273   check_nans ();
274 
275   special ();
276   for (p=2; p<100; p++)
277     for (k=0; k<100; k++)
278       check_two_sum (p);
279 
280   check(1196426492, "1.4218093058435347e-3", MPFR_RNDN,
281         "1.1964264919985781e9");
282   check(1092583421, "-1.0880649218158844e9", MPFR_RNDN,
283         "2.1806483428158845901e9");
284   check(948002822, "1.22191250737771397120e+20", MPFR_RNDN,
285         "-1.2219125073682338611e20");
286   check(832100416, "4.68311314939691330000e-215", MPFR_RNDD,
287         "8.3210041599999988079e8");
288   check(1976245324, "1.25296395864546893357e+232", MPFR_RNDZ,
289         "-1.2529639586454686577e232");
290   check(2128997392, "-1.08496826129284207724e+187", MPFR_RNDU,
291         "1.0849682612928422704e187");
292   check(293607738, "-1.9967571564050541e-5", MPFR_RNDU,
293         "2.9360773800002003e8");
294   check(354270183, "2.9469161763489528e3", MPFR_RNDN,
295         "3.5426723608382362e8");
296 
297   check_neg ();
298 
299   tests_end_mpfr ();
300   return 0;
301 }
302