xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/tatan2u.c (revision ba125506a622fe649968631a56eba5d42ff57863)
1 /* Test file for mpfr_atan2u.
2 
3 Copyright 2021-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 #define TEST_FUNCTION mpfr_atan2u
26 #define THREE_ARGS
27 #include "tgeneric.c"
28 
29 /* Special cases from IEEE 754-2019 (page 63) */
30 static void
check_ieee754(void)31 check_ieee754 (void)
32 {
33   mpfr_t x, y, z;
34   int i;
35   mpfr_prec_t prec = 2; /* we need at least 2 so that 3/4 is exact */
36 
37   mpfr_init2 (x, prec);
38   mpfr_init2 (y, prec);
39   mpfr_init2 (z, prec);
40 
41   /* atan2Pi(±0, −0) is ±1 */
42   mpfr_set_zero (x, -1);
43   mpfr_set_zero (y, +1);
44   mpfr_atan2u (z, y, x, 2, MPFR_RNDN);
45   if (mpfr_cmp_ui (z, 1) != 0)
46     {
47       printf ("Error for atan2u(+0,-0,2)\n");
48       printf ("expected 1\n");
49       printf ("got     "); mpfr_dump (z);
50       exit (1);
51     }
52   mpfr_set_zero (y, -1);
53   mpfr_atan2u (z, y, x, 2, MPFR_RNDN);
54   if (mpfr_cmp_si (z, -1) != 0)
55     {
56       printf ("Error for atan2u(-0,-0,2)\n");
57       printf ("expected -1\n");
58       printf ("got     "); mpfr_dump (z);
59       exit (1);
60     }
61 
62   /* atan2Pi(±0, +0) is ±0 */
63   mpfr_set_zero (x, +1);
64   mpfr_set_zero (y, +1);
65   mpfr_atan2u (z, y, x, 2, MPFR_RNDN);
66   if (!MPFR_IS_ZERO(z) || MPFR_IS_NEG(z))
67     {
68       printf ("Error for atan2u(+0,+0,2)\n");
69       printf ("expected +0\n");
70       printf ("got     "); mpfr_dump (z);
71       exit (1);
72     }
73   mpfr_set_zero (y, -1);
74   mpfr_atan2u (z, y, x, 2, MPFR_RNDN);
75   if (!MPFR_IS_ZERO(z) || MPFR_IS_POS(z))
76     {
77       printf ("Error for atan2u(-0,+0,2)\n");
78       printf ("expected -0\n");
79       printf ("got     "); mpfr_dump (z);
80       exit (1);
81     }
82 
83   /* atan2Pi(±0, x) is ±1 for x < 0 (including x=-Inf) */
84   for (i = 0; i < 2; i++)
85     {
86       if (i == 0)
87         mpfr_set_si (x, -1, MPFR_RNDN);
88       else
89         mpfr_set_inf (x, -1);
90       mpfr_set_zero (y, +1);
91       mpfr_atan2u (z, y, x, 2, MPFR_RNDN);
92       if (mpfr_cmp_ui (z, 1) != 0)
93         {
94           printf ("Error for atan2u(+0,x,2)\nwith x = ");
95           mpfr_dump (x);
96           printf ("expected 1\n");
97           printf ("got     "); mpfr_dump (z);
98           exit (1);
99         }
100       mpfr_set_zero (y, -1);
101       mpfr_atan2u (z, y, x, 2, MPFR_RNDN);
102       if (mpfr_cmp_si (z, -1) != 0)
103         {
104           printf ("Error for atan2u(-0,x,2)\nwith x = ");
105           mpfr_dump (x);
106           printf ("expected -1\n");
107           printf ("got     "); mpfr_dump (z);
108           exit (1);
109         }
110     }
111 
112   /* atan2Pi(±0, x) is ±0 for x > 0 (including x=+Inf) */
113   for (i = 0; i < 2; i++)
114     {
115       if (i == 0)
116           mpfr_set_ui (x, 1, MPFR_RNDN);
117       else
118         mpfr_set_inf (x, 1);
119       mpfr_set_zero (y, +1);
120       mpfr_atan2u (z, y, x, 2, MPFR_RNDN);
121       if (!MPFR_IS_ZERO(z) || MPFR_IS_NEG(z))
122         {
123           printf ("Error for atan2u(+0,x,2)\nwith x = ");
124           mpfr_dump (x);
125           printf ("expected +0\n");
126           printf ("got     "); mpfr_dump (z);
127           exit (1);
128         }
129       mpfr_set_zero (y, -1);
130       mpfr_atan2u (z, y, x, 2, MPFR_RNDN);
131       if (!MPFR_IS_ZERO(z) || MPFR_IS_POS(z))
132         {
133           printf ("Error for atan2u(-0,x,2)\nwith x = ");
134           mpfr_dump (x);
135           printf ("expected -0\n");
136           printf ("got     "); mpfr_dump (z);
137           exit (1);
138         }
139     }
140 
141   /* atan2Pi(y, ±0) is −½ for y < 0 */
142   mpfr_set_si (y, -1, MPFR_RNDN);
143   mpfr_set_zero (x, 1);
144   mpfr_atan2u (z, y, x, 2, MPFR_RNDN);
145   if (mpfr_cmp_si_2exp (z, -1, -1) != 0)
146     {
147       printf ("Error for atan2u(-1,+0,2)\n");
148       printf ("expected -1/2\n");
149       printf ("got     "); mpfr_dump (z);
150       exit (1);
151     }
152   mpfr_set_zero (x, -1);
153   mpfr_atan2u (z, y, x, 2, MPFR_RNDN);
154   if (mpfr_cmp_si_2exp (z, -1, -1) != 0)
155     {
156       printf ("Error for atan2u(-1,-0,2)\n");
157       printf ("expected -1/2\n");
158       printf ("got     "); mpfr_dump (z);
159       exit (1);
160     }
161 
162   /* atan2Pi(y, ±0) is +½ for y > 0 */
163   mpfr_set_ui (y, 1, MPFR_RNDN);
164   mpfr_set_zero (x, 1);
165   mpfr_atan2u (z, y, x, 2, MPFR_RNDN);
166   if (mpfr_cmp_ui_2exp (z, 1, -1) != 0)
167     {
168       printf ("Error for atan2u(1,+0,2)\n");
169       printf ("expected 1/2\n");
170       printf ("got     "); mpfr_dump (z);
171       exit (1);
172     }
173   mpfr_set_zero (x, -1);
174   mpfr_atan2u (z, y, x, 2, MPFR_RNDN);
175   if (mpfr_cmp_ui_2exp (z, 1, -1) != 0)
176     {
177       printf ("Error for atan2u(-1,-0,2)\n");
178       printf ("expected 1/2\n");
179       printf ("got     "); mpfr_dump (z);
180       exit (1);
181     }
182 
183   /* atan2Pi(±y, −∞) is ±1 for finite y > 0 */
184   mpfr_set_inf (x, -1);
185   mpfr_set_ui (y, 1, MPFR_RNDN);
186   mpfr_atan2u (z, y, x, 2, MPFR_RNDN);
187   if (mpfr_cmp_ui (z, 1) != 0)
188     {
189       printf ("Error for atan2u(1,-Inf,2)\n");
190       printf ("expected 1\n");
191       printf ("got     "); mpfr_dump (z);
192       exit (1);
193     }
194   mpfr_set_si (y, -1, MPFR_RNDN);
195   mpfr_atan2u (z, y, x, 2, MPFR_RNDN);
196   if (mpfr_cmp_si (z, -1) != 0)
197     {
198       printf ("Error for atan2u(-1,-Inf,2)\n");
199       printf ("expected -1\n");
200       printf ("got     "); mpfr_dump (z);
201       exit (1);
202     }
203 
204   /* atan2Pi(±y, +∞) is ±0 for finite y > 0 */
205   mpfr_set_inf (x, +1);
206   mpfr_set_ui (y, 1, MPFR_RNDN);
207   mpfr_atan2u (z, y, x, 2, MPFR_RNDN);
208   if (!MPFR_IS_ZERO(z) || MPFR_IS_NEG(z))
209     {
210       printf ("Error for atan2u(1,+Inf,2)\n");
211       printf ("expected +0\n");
212       printf ("got     "); mpfr_dump (z);
213       exit (1);
214     }
215   mpfr_set_si (y, -1, MPFR_RNDN);
216   mpfr_atan2u (z, y, x, 2, MPFR_RNDN);
217   if (!MPFR_IS_ZERO(z) || MPFR_IS_POS(z))
218     {
219       printf ("Error for atan2u(-1,+Inf,2)\n");
220       printf ("expected -0\n");
221       printf ("got     "); mpfr_dump (z);
222       exit (1);
223     }
224 
225   /* atan2Pi(±∞, x) is ±½ for finite x */
226   for (i = 0; i < 4; i++)
227     {
228       if (i == 0)
229         mpfr_set_ui (x, 1, MPFR_RNDN);
230       else if (i == 1)
231         mpfr_set_zero (x, 1);
232       else if (i == 2)
233         mpfr_set_zero (x, -1);
234       else
235         mpfr_set_si (x, -1, MPFR_RNDN);
236       mpfr_set_inf (y, 1);
237       mpfr_atan2u (z, y, x, 2, MPFR_RNDN);
238       if (mpfr_cmp_ui_2exp (z, 1, -1) != 0)
239         {
240           printf ("Error for atan2u(+Inf,x,2)\nwith x = ");
241           mpfr_dump (x);
242           printf ("expected 1/2\n");
243           printf ("got     "); mpfr_dump (z);
244           exit (1);
245         }
246       mpfr_set_inf (y, -1);
247       mpfr_atan2u (z, y, x, 2, MPFR_RNDN);
248       if (mpfr_cmp_si_2exp (z, -1, -1) != 0)
249         {
250           printf ("Error for atan2u(-Inf,x,2)\nwith x = ");
251           mpfr_dump (x);
252           printf ("expected -1/2\n");
253           printf ("got     "); mpfr_dump (z);
254           exit (1);
255         }
256     }
257 
258   /* atan2Pi(±∞, −∞) is ±¾ */
259   mpfr_set_inf (x, -1);
260   mpfr_set_inf (y, 1);
261   mpfr_atan2u (z, y, x, 2, MPFR_RNDN);
262   if (mpfr_cmp_ui_2exp (z, 3, -2) != 0)
263     {
264       printf ("Error for atan2u(+Inf,-Inf,2)\n");
265       printf ("expected 3/4\n");
266       printf ("got     "); mpfr_dump (z);
267       exit (1);
268     }
269   mpfr_set_inf (y, -1);
270   mpfr_atan2u (z, y, x, 2, MPFR_RNDN);
271   if (mpfr_cmp_si_2exp (z, -3, -2) != 0)
272     {
273       printf ("Error for atan2u(+Inf,-Inf,2)\n");
274       printf ("expected -3/4\n");
275       printf ("got     "); mpfr_dump (z);
276       exit (1);
277     }
278 
279   /* atan2Pi(±∞, +∞) is ±¼ */
280   mpfr_set_inf (x, 1);
281   mpfr_set_inf (y, 1);
282   mpfr_atan2u (z, y, x, 2, MPFR_RNDN);
283   if (mpfr_cmp_ui_2exp (z, 1, -2) != 0)
284     {
285       printf ("Error for atan2u(+Inf,+Inf,2)\n");
286       printf ("expected 1/4\n");
287       printf ("got     "); mpfr_dump (z);
288       exit (1);
289     }
290   mpfr_set_inf (y, -1);
291   mpfr_atan2u (z, y, x, 2, MPFR_RNDN);
292   if (mpfr_cmp_si_2exp (z, -1, -2) != 0)
293     {
294       printf ("Error for atan2u(+Inf,+Inf,2)\n");
295       printf ("expected -1/4\n");
296       printf ("got     "); mpfr_dump (z);
297       exit (1);
298     }
299 
300   mpfr_clear (x);
301   mpfr_clear (y);
302   mpfr_clear (z);
303 }
304 
305 /* Special cases from LIA-2 (5.3.9.15) not covered by IEEE 754-2019.
306    Warning: in LIA-2, the order of arguments is reversed:
307    arcu (u,x,y) corresponds to atan2u (y,x,u). */
308 static void
check_lia2(void)309 check_lia2 (void)
310 {
311   mpfr_t x, y, z;
312   mpfr_prec_t prec = 9; /* 3*99 must be exactly representable */
313   unsigned long u;
314   int r, inex;
315 
316   mpfr_init2 (x, prec);
317   mpfr_init2 (y, prec);
318   mpfr_init2 (z, prec);
319 
320   /* arcu (u, x, x) = u/8 for x > 0 */
321   for (u = 1; u < 100; u++)
322      RND_LOOP (r)
323        {
324          mpfr_set_ui (x, 1, MPFR_RNDN); /* exact */
325          mpfr_set_ui (y, 1, MPFR_RNDN); /* exact */
326          mpfr_atan2u (z, y, x, u, (mpfr_rnd_t) r);
327          inex = mpfr_set_ui (x, u, MPFR_RNDN);
328          MPFR_ASSERTN(inex == 0);
329          inex = mpfr_div_ui (x, x, 8, (mpfr_rnd_t) r);
330          if ((r != MPFR_RNDF || inex == 0) && !mpfr_equal_p (x, z))
331            {
332              printf ("Error: atan2u(1,1,u) != u/8 for u=%lu and rnd=%s\n",
333                      u, mpfr_print_rnd_mode ((mpfr_rnd_t) r));
334              printf ("got: "); mpfr_dump (z);
335              exit (1);
336            }
337        }
338 
339   /* arcu (u, x, -x) = -u/8 for x > 0 */
340   for (u = 1; u < 100; u++)
341      RND_LOOP (r)
342        {
343          mpfr_set_ui (x, 1, MPFR_RNDN); /* exact */
344          mpfr_set_si (y, -1, MPFR_RNDN); /* exact */
345          mpfr_atan2u (z, y, x, u, (mpfr_rnd_t) r);
346          inex = mpfr_set_ui (x, u, MPFR_RNDN);
347          MPFR_ASSERTN(inex == 0);
348          inex = mpfr_div_si (x, x, -8, (mpfr_rnd_t) r);
349          if ((r != MPFR_RNDF || inex == 0) && !mpfr_equal_p (x, z))
350            {
351              printf ("Error: atan2u(-1,1,u) != -u/8 for u=%lu and rnd=%s\n",
352                      u, mpfr_print_rnd_mode ((mpfr_rnd_t) r));
353              printf ("got: "); mpfr_dump (z);
354              exit (1);
355            }
356        }
357 
358   /* arcu (u, x, −x) = 3 · u/8 for x < 0 */
359   for (u = 1; u < 100; u++)
360      RND_LOOP (r)
361        {
362          mpfr_set_si (x, -1, MPFR_RNDN); /* exact */
363          mpfr_set_ui (y, 1, MPFR_RNDN); /* exact */
364          mpfr_atan2u (z, y, x, u, (mpfr_rnd_t) r);
365          inex = mpfr_set_ui (x, 3 * u, MPFR_RNDN);
366          MPFR_ASSERTN(inex == 0);
367          inex = mpfr_div_ui (x, x, 8, (mpfr_rnd_t) r);
368          if ((r != MPFR_RNDF || inex == 0) && !mpfr_equal_p (x, z))
369            {
370              printf ("Error: atan2u(1,-1,u) != 3u/8 for u=%lu and rnd=%s\n",
371                      u, mpfr_print_rnd_mode ((mpfr_rnd_t) r));
372              printf ("got: "); mpfr_dump (z);
373              exit (1);
374            }
375        }
376 
377   /* arcu (u, x, x) = -3 · u/8 for x < 0 */
378   for (u = 1; u < 100; u++)
379      RND_LOOP (r)
380        {
381          mpfr_set_si (x, -1, MPFR_RNDN); /* exact */
382          mpfr_set_si (y, -1, MPFR_RNDN); /* exact */
383          mpfr_atan2u (z, y, x, u, (mpfr_rnd_t) r);
384          inex = mpfr_set_ui (x, 3 * u, MPFR_RNDN);
385          MPFR_ASSERTN(inex == 0);
386          inex = mpfr_div_si (x, x, -8, (mpfr_rnd_t) r);
387          if ((r != MPFR_RNDF || inex == 0) && !mpfr_equal_p (x, z))
388            {
389              printf ("Error: atan2u(-1,-1,u) != -3u/8 for u=%lu and rnd=%s\n",
390                      u, mpfr_print_rnd_mode ((mpfr_rnd_t) r));
391              printf ("got: "); mpfr_dump (z);
392              exit (1);
393            }
394        }
395 
396   mpfr_clear (x);
397   mpfr_clear (y);
398   mpfr_clear (z);
399 }
400 
401 static void
check_random(void)402 check_random (void)
403 {
404   mpfr_t x, y, z;
405   long i, j, B = 20;
406   unsigned long u;
407   int r;
408 
409   mpfr_init2 (x, 53);
410   mpfr_init2 (y, 53);
411   mpfr_init2 (z, 53);
412 
413   /* hard-coded values */
414 
415   /* first quadrant */
416   mpfr_set_ui (x, 17, MPFR_RNDN);
417   mpfr_set_ui (y, 42, MPFR_RNDN);
418   mpfr_atan2u (z, y, x, 360, MPFR_RNDN); /* in degrees */
419   mpfr_set_str (x, "4.3f6b9d4ccd754p+4", 16, MPFR_RNDN);
420   if (!mpfr_equal_p (z, x))
421     {
422       printf ("Error for atan2u(42,17,360)\n");
423       printf ("expected "); mpfr_dump (x);
424       printf ("got      "); mpfr_dump (z);
425       exit (1);
426     }
427 
428   /* second quadrant */
429   mpfr_set_si (x, -17, MPFR_RNDN);
430   mpfr_set_ui (y, 42, MPFR_RNDN);
431   mpfr_atan2u (z, y, x, 360, MPFR_RNDN); /* in degrees */
432   mpfr_set_str (x, "7.009462b3328acp+4", 16, MPFR_RNDN);
433   if (!mpfr_equal_p (z, x))
434     {
435       printf ("Error for atan2u(42,-17,360)\n");
436       printf ("expected "); mpfr_dump (x);
437       printf ("got      "); mpfr_dump (z);
438       exit (1);
439     }
440 
441   /* third quadrant */
442   mpfr_set_si (x, -17, MPFR_RNDN);
443   mpfr_set_si (y, -42, MPFR_RNDN);
444   mpfr_atan2u (z, y, x, 360, MPFR_RNDN); /* in degrees */
445   mpfr_set_str (x, "-7.009462b3328acp+4", 16, MPFR_RNDN);
446   if (!mpfr_equal_p (z, x))
447     {
448       printf ("Error for atan2u(-42,-17,360)\n");
449       printf ("expected "); mpfr_dump (x);
450       printf ("got      "); mpfr_dump (z);
451       exit (1);
452     }
453 
454   /* fourth quadrant */
455   mpfr_set_ui (x, 17, MPFR_RNDN);
456   mpfr_set_si (y, -42, MPFR_RNDN);
457   mpfr_atan2u (z, y, x, 360, MPFR_RNDN); /* in degrees */
458   mpfr_set_str (x, "-4.3f6b9d4ccd754p+4", 16, MPFR_RNDN);
459   if (!mpfr_equal_p (z, x))
460     {
461       printf ("Error for atan2u(-42,17,360)\n");
462       printf ("expected "); mpfr_dump (x);
463       printf ("got      "); mpfr_dump (z);
464       exit (1);
465     }
466 
467   /* case u=0 with x > 0 */
468   mpfr_set_ui (x, 17, MPFR_RNDN);
469   mpfr_set_ui (y, 42, MPFR_RNDN);
470   mpfr_atan2u (z, y, x, 0, MPFR_RNDN);
471   if (!MPFR_IS_ZERO(z) || MPFR_IS_NEG(z))
472     {
473       printf ("Error for atan2u(42,17,0)\n");
474       printf ("expected +0\n");
475       printf ("got     "); mpfr_dump (z);
476       exit (1);
477     }
478   mpfr_set_si (y, -42, MPFR_RNDN);
479   mpfr_atan2u (z, y, x, 0, MPFR_RNDN);
480   if (!MPFR_IS_ZERO(z) || MPFR_IS_POS(z))
481     {
482       printf ("Error for atan2u(-42,17,0)\n");
483       printf ("expected -0\n");
484       printf ("got     "); mpfr_dump (z);
485       exit (1);
486     }
487 
488   /* case u=0 with x < 0 */
489   mpfr_set_si (x, -17, MPFR_RNDN);
490   mpfr_set_ui (y, 42, MPFR_RNDN);
491   mpfr_atan2u (z, y, x, 0, MPFR_RNDN);
492   if (mpfr_cmp_ui (z, 1) != 0)
493     {
494       printf ("Error for atan2u(42,-17,0)\n");
495       printf ("expected +1\n");
496       printf ("got     "); mpfr_dump (z);
497       exit (1);
498     }
499   mpfr_set_si (y, -42, MPFR_RNDN);
500   mpfr_atan2u (z, y, x, 0, MPFR_RNDN);
501   if (mpfr_cmp_si (z, -1) != 0)
502     {
503       printf ("Error for atan2u(-42,-17,0)\n");
504       printf ("expected -1\n");
505       printf ("got     "); mpfr_dump (z);
506       exit (1);
507     }
508 
509   for (i = -B; i <= B; i++)
510     {
511       mpfr_set_si (x, i, MPFR_RNDN);
512       for (j = -B; j <= B; j++)
513         {
514           mpfr_set_si (y, j, MPFR_RNDN);
515           for (u = 0; u <= B; u++)
516             RND_LOOP (r)
517               mpfr_atan2u (z, y, x, u, (mpfr_rnd_t) r);
518         }
519     }
520 
521   mpfr_clear (x);
522   mpfr_clear (y);
523   mpfr_clear (z);
524 }
525 
526 /* bug found with GMP_CHECK_RANDOMIZE=1612368173909457 */
527 static void
bug20210203(void)528 bug20210203 (void)
529 {
530   /* The "#if" makes sure that 64-bit constants are supported, avoiding
531      a compilation failure. The "if" makes sure that the constant is
532      representable in an unsigned long (this would not be the case with
533      32-bit unsigned long and 64-bit limb). */
534 
535 #if GMP_NUMB_BITS >= 64 || MPFR_PREC_BITS >= 64
536   mpfr_t x, y, z;
537   unsigned long u = 13484982567905493265U;
538 
539   if (u == 13484982567905493265U)
540     {
541       mpfr_init2 (x, 12);
542       mpfr_init2 (y, 12);
543       mpfr_init2 (z, 28);
544       mpfr_set_str_binary (y, "-0.111101100000E-66");
545       mpfr_set_str_binary (x, "0.111011100000E0");
546       mpfr_atan2u (z, y, x, u, MPFR_RNDN);
547       mpfr_set_prec (x, 28);
548       mpfr_set_str_binary (x, "-0.1111011001001001000110001010E-5");
549       if (!mpfr_equal_p (z, x))
550         {
551           printf ("Error in bug20210203\n");
552           printf ("expected "); mpfr_dump (x);
553           printf ("got      "); mpfr_dump (z);
554           exit (1);
555         }
556       mpfr_clear (x);
557       mpfr_clear (y);
558       mpfr_clear (z);
559     }
560 #endif
561 }
562 
563 int
main(void)564 main (void)
565 {
566   tests_start_mpfr ();
567 
568   bug20210203 ();
569 
570   check_ieee754 ();
571 
572   check_lia2 ();
573 
574   check_random ();
575 
576   test_generic (MPFR_PREC_MIN, 100, 100);
577 
578   tests_end_mpfr ();
579   return 0;
580 }
581