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