xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/thypot.c (revision ba125506a622fe649968631a56eba5d42ff57863)
1 /* Test file for mpfr_hypot.
2 
3 Copyright 2001-2023 Free Software Foundation, Inc.
4 Contributed by the AriC and Caramba 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 https://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 "mpfr-test.h"
24 
25 /* Non-zero when extended exponent range */
26 static int ext = 0;
27 
28 static void
special(void)29 special (void)
30 {
31   mpfr_t x, y, z;
32 
33   mpfr_init (x);
34   mpfr_init (y);
35   mpfr_init (z);
36 
37   mpfr_set_nan (x);
38   mpfr_set_ui (y, 0, MPFR_RNDN);
39   mpfr_hypot (z, x, x, MPFR_RNDN);
40   MPFR_ASSERTN(mpfr_nan_p (z));
41   mpfr_hypot (z, x, y, MPFR_RNDN);
42   MPFR_ASSERTN(mpfr_nan_p (z));
43   mpfr_hypot (z, y, x, MPFR_RNDN);
44   MPFR_ASSERTN(mpfr_nan_p (z));
45 
46   mpfr_set_inf (x, 1);
47   mpfr_set_inf (y, -1);
48   mpfr_hypot (z, x, y, MPFR_RNDN);
49   MPFR_ASSERTN(mpfr_inf_p (z) && mpfr_sgn (z) > 0);
50 
51   mpfr_set_inf (x, -1);
52   mpfr_set_nan (y);
53   mpfr_hypot (z, x, y, MPFR_RNDN);
54   MPFR_ASSERTN(mpfr_inf_p (z) && mpfr_sgn (z) > 0);
55 
56   mpfr_set_nan (x);
57   mpfr_set_inf (y, -1);
58   mpfr_hypot (z, x, y, MPFR_RNDN);
59   MPFR_ASSERTN(mpfr_inf_p (z) && mpfr_sgn (z) > 0);
60 
61   mpfr_clear (x);
62   mpfr_clear (y);
63   mpfr_clear (z);
64 }
65 
66 static void
test_large(void)67 test_large (void)
68 {
69   mpfr_t x, y, z, t;
70 
71   mpfr_init (x);
72   mpfr_init (y);
73   mpfr_init (z);
74   mpfr_init (t);
75 
76   mpfr_set_ui (x, 21, MPFR_RNDN);
77   mpfr_set_ui (y, 28, MPFR_RNDN);
78   mpfr_set_ui (z, 35, MPFR_RNDN);
79 
80   mpfr_mul_2ui (x, x, MPFR_EMAX_DEFAULT-6, MPFR_RNDN);
81   mpfr_mul_2ui (y, y, MPFR_EMAX_DEFAULT-6, MPFR_RNDN);
82   mpfr_mul_2ui (z, z, MPFR_EMAX_DEFAULT-6, MPFR_RNDN);
83 
84   mpfr_hypot (t, x, y, MPFR_RNDN);
85   if (mpfr_cmp (z, t))
86     {
87       printf ("Error in test_large: got\n");
88       mpfr_out_str (stdout, 2, 0, t, MPFR_RNDN);
89       printf ("\ninstead of\n");
90       mpfr_out_str (stdout, 2, 0, z, MPFR_RNDN);
91       printf ("\n");
92       exit (1);
93     }
94 
95   mpfr_set_prec (x, 53);
96   mpfr_set_prec (t, 53);
97   mpfr_set_prec (y, 53);
98   mpfr_set_str_binary (x, "0.11101100011110000011101000010101010011001101000001100E-1021");
99   mpfr_set_str_binary (y, "0.11111001010011000001110110001101011100001000010010100E-1021");
100   mpfr_hypot (t, x, y, MPFR_RNDN);
101   mpfr_set_str_binary (z, "0.101010111100110111101110111110100110010011001010111E-1020");
102   if (mpfr_cmp (z, t))
103     {
104       printf ("Error in test_large: got\n");
105       mpfr_out_str (stdout, 2, 0, t, MPFR_RNDN);
106       printf ("\ninstead of\n");
107       mpfr_out_str (stdout, 2, 0, z, MPFR_RNDN);
108       printf ("\n");
109       exit (1);
110     }
111 
112   mpfr_set_prec (x, 240);
113   mpfr_set_prec (y, 22);
114   mpfr_set_prec (z, 2);
115   mpfr_set_prec (t, 2);
116   mpfr_set_str_binary (x, "0.100111011010010010110100000100000001100010011100110101101111111101011110111011011101010110100101111000111100010100110000100101011110111011100110100110100101110101101100011000001100000001111101110100100100011011011010110111100110010101000111e-7");
117   mpfr_set_str_binary (y, "0.1111000010000011000111E-10");
118   mpfr_hypot (t, x, y, MPFR_RNDN);
119   mpfr_set_str_binary (z, "0.11E-7");
120   if (mpfr_cmp (z, t))
121     {
122       printf ("Error in test_large: got\n");
123       mpfr_out_str (stdout, 2, 0, t, MPFR_RNDN);
124       printf ("\ninstead of\n");
125       mpfr_out_str (stdout, 2, 0, z, MPFR_RNDN);
126       printf ("\n");
127       exit (1);
128     }
129 
130   mpfr_clear (x);
131   mpfr_clear (y);
132   mpfr_clear (z);
133   mpfr_clear (t);
134 }
135 
136 static void
test_small(void)137 test_small (void)
138 {
139   mpfr_t x, y, z1, z2;
140   int inex1, inex2;
141   unsigned int flags;
142 
143   /* Test hypot(x,x) with x = 2^(emin-1). Result is x * sqrt(2). */
144   mpfr_inits2 (8, x, y, z1, z2, (mpfr_ptr) 0);
145   mpfr_set_si_2exp (x, 1, mpfr_get_emin () - 1, MPFR_RNDN);
146   mpfr_set_si_2exp (y, 1, mpfr_get_emin () - 1, MPFR_RNDN);
147   mpfr_set_ui (z1, 2, MPFR_RNDN);
148   inex1 = mpfr_sqrt (z1, z1, MPFR_RNDN);
149   inex2 = mpfr_mul (z1, z1, x, MPFR_RNDN);
150   MPFR_ASSERTN (inex2 == 0);
151   mpfr_clear_flags ();
152   inex2 = mpfr_hypot (z2, x, y, MPFR_RNDN);
153   flags = __gmpfr_flags;
154   if (mpfr_cmp (z1, z2) != 0)
155     {
156       printf ("Error in test_small%s\nExpected ",
157               ext ? ", extended exponent range" : "");
158       mpfr_out_str (stdout, 2, 0, z1, MPFR_RNDN);
159       printf ("\nGot      ");
160       mpfr_out_str (stdout, 2, 0, z2, MPFR_RNDN);
161       printf ("\n");
162       exit (1);
163     }
164   if (! SAME_SIGN (inex1, inex2))
165     {
166       printf ("Bad ternary value in test_small%s\nExpected %d, got %d\n",
167               ext ? ", extended exponent range" : "", inex1, inex2);
168       exit (1);
169     }
170   if (flags != MPFR_FLAGS_INEXACT)
171     {
172       printf ("Bad flags in test_small%s\nExpected %u, got %u\n",
173               ext ? ", extended exponent range" : "",
174               (unsigned int) MPFR_FLAGS_INEXACT, flags);
175       exit (1);
176     }
177   mpfr_clears (x, y, z1, z2, (mpfr_ptr) 0);
178 }
179 
180 static void
test_large_small(void)181 test_large_small (void)
182 {
183   mpfr_t x, y, z;
184   int inexact, inex2, r;
185 
186   mpfr_init2 (x, 3);
187   mpfr_init2 (y, 2);
188   mpfr_init2 (z, 2);
189 
190   mpfr_set_ui_2exp (x, 1, mpfr_get_emax () / 2, MPFR_RNDN);
191   mpfr_set_ui_2exp (y, 1, -1, MPFR_RNDN);
192   inexact = mpfr_hypot (z, x, y, MPFR_RNDN);
193   if (inexact >= 0 || mpfr_cmp (x, z))
194     {
195       printf ("Error 1 in test_large_small%s\n",
196               ext ? ", extended exponent range" : "");
197       exit (1);
198     }
199 
200   mpfr_mul_ui (x, x, 5, MPFR_RNDN);
201   inexact = mpfr_hypot (z, x, y, MPFR_RNDN);
202   if (mpfr_cmp (x, z) >= 0)
203     {
204       printf ("Error 2 in test_large_small%s\n",
205               ext ? ", extended exponent range" : "");
206       printf ("x = ");
207       mpfr_out_str (stdout, 2, 0, x, MPFR_RNDN);
208       printf ("\n");
209       printf ("y = ");
210       mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN);
211       printf ("\n");
212       printf ("z = ");
213       mpfr_out_str (stdout, 2, 0, z, MPFR_RNDN);
214       printf (" (in precision 2) instead of\n    ");
215       mpfr_out_str (stdout, 2, 2, x, MPFR_RNDU);
216       printf ("\n");
217       exit (1);
218     }
219 
220   RND_LOOP(r)
221     {
222       mpfr_set_ui_2exp (x, 1, mpfr_get_emax () - 1, MPFR_RNDN);
223       mpfr_set_ui_2exp (y, 1, mpfr_get_emin (), MPFR_RNDN);
224       inexact = mpfr_hypot (z, x, y, (mpfr_rnd_t) r);
225       inex2 = mpfr_add_ui (y, x, 1, (mpfr_rnd_t) r);
226       if (! mpfr_equal_p (y, z) || ! SAME_SIGN (inexact, inex2))
227         {
228           printf ("Error 3 in test_large_small, %s%s\n",
229                   mpfr_print_rnd_mode ((mpfr_rnd_t) r),
230                   ext ? ", extended exponent range" : "");
231           printf ("Expected ");
232           mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN);
233           printf (", inex = %d\n", inex2);
234           printf ("Got      ");
235           mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN);
236           printf (", inex = %d\n", inexact);
237           exit (1);
238         }
239     }
240 
241   mpfr_clear (x);
242   mpfr_clear (y);
243   mpfr_clear (z);
244 }
245 
246 static void
check_overflow(void)247 check_overflow (void)
248 {
249   mpfr_t x, y;
250   int inex, r;
251 
252   mpfr_inits2 (8, x, y, (mpfr_ptr) 0);
253   mpfr_set_ui (x, 1, MPFR_RNDN);
254   mpfr_setmax (x, mpfr_get_emax ());
255 
256   RND_LOOP(r)
257     {
258       mpfr_clear_overflow ();
259       inex = mpfr_hypot (y, x, x, (mpfr_rnd_t) r);
260       if (!mpfr_overflow_p ())
261         {
262           printf ("No overflow in check_overflow for %s%s\n",
263                   mpfr_print_rnd_mode ((mpfr_rnd_t) r),
264                   ext ? ", extended exponent range" : "");
265           exit (1);
266         }
267       MPFR_ASSERTN (MPFR_IS_POS (y));
268       if (r == MPFR_RNDZ || r == MPFR_RNDD)
269         {
270           MPFR_ASSERTN (inex < 0);
271           MPFR_ASSERTN (!mpfr_inf_p (y));
272           mpfr_nexttoinf (y);
273         }
274       else
275         {
276           MPFR_ASSERTN (inex > 0);
277         }
278       MPFR_ASSERTN (mpfr_inf_p (y));
279     }
280 
281   mpfr_clears (x, y, (mpfr_ptr) 0);
282 }
283 
284 #define TWO_ARGS
285 #define TEST_FUNCTION mpfr_hypot
286 #include "tgeneric.c"
287 
288 static void
alltst(void)289 alltst (void)
290 {
291   mpfr_exp_t emin, emax;
292 
293   ext = 0;
294   test_small ();
295   test_large_small ();
296   check_overflow ();
297 
298   emin = mpfr_get_emin ();
299   emax = mpfr_get_emax ();
300   set_emin (MPFR_EMIN_MIN);
301   set_emax (MPFR_EMAX_MAX);
302   if (mpfr_get_emin () != emin || mpfr_get_emax () != emax)
303     {
304       ext = 1;
305       test_small ();
306       test_large_small ();
307       check_overflow ();
308       set_emin (emin);
309       set_emax (emax);
310     }
311 }
312 
313 /* Test failing with GMP_CHECK_RANDOMIZE=1513841234 (overflow flag not set).
314    The bug was in fact in mpfr_nexttoinf which didn't set the overflow flag. */
315 static void
bug20171221(void)316 bug20171221 (void)
317 {
318   mpfr_t x, u, y;
319   int inex;
320   mpfr_exp_t emax;
321 
322   mpfr_init2 (x, 12);
323   mpfr_init2 (u, 12);
324   mpfr_init2 (y, 11);
325   mpfr_set_str_binary (x, "0.111111111110E0");
326   mpfr_set_str_binary (u, "0.111011110100E-177");
327   emax = mpfr_get_emax ();
328   set_emax (0);
329   mpfr_clear_flags ();
330   inex = mpfr_hypot (y, x, u, MPFR_RNDU);
331   MPFR_ASSERTN(mpfr_inf_p (y) && mpfr_sgn (y) > 0);
332   MPFR_ASSERTN(inex > 0);
333   MPFR_ASSERTN(mpfr_inexflag_p ());
334   MPFR_ASSERTN(mpfr_overflow_p ());
335   set_emax (emax);
336   mpfr_clear (x);
337   mpfr_clear (u);
338   mpfr_clear (y);
339 }
340 
341 /* check overflow for x=0xf.ffffffffffff8p+1020 and u=0xf.fffffp+124
342    with rounding upwards and emax=1024 (as in binary64) */
343 static void
test_overflow(void)344 test_overflow (void)
345 {
346   mpfr_t x, u, y;
347   int inex;
348   mpfr_exp_t emax;
349 
350   mpfr_init2 (x, 53);
351   mpfr_init2 (u, 53);
352   mpfr_init2 (y, 53);
353   mpfr_set_str (x, "0xf.ffffffffffff8p+1020", 16, MPFR_RNDN);
354   mpfr_set_str (u, "0xf.fffffp+124", 16, MPFR_RNDN);
355   emax = mpfr_get_emax ();
356   set_emax (1024);
357   mpfr_clear_flags ();
358   inex = mpfr_hypot (y, x, u, MPFR_RNDU);
359   MPFR_ASSERTN(mpfr_inf_p (y) && mpfr_sgn (y) > 0);
360   MPFR_ASSERTN(inex > 0);
361   MPFR_ASSERTN(mpfr_inexflag_p ());
362   MPFR_ASSERTN(mpfr_overflow_p ());
363   set_emax (emax);
364   mpfr_clear (x);
365   mpfr_clear (u);
366   mpfr_clear (y);
367 }
368 
369 int
main(int argc,char * argv[])370 main (int argc, char *argv[])
371 {
372   tests_start_mpfr ();
373 
374   bug20171221 ();
375   special ();
376 
377   test_large ();
378   alltst ();
379   test_overflow ();
380 
381   test_generic (MPFR_PREC_MIN, 100, 10);
382 
383   tests_end_mpfr ();
384   return 0;
385 }
386