math: rewrite remainder functions (remainder, remquo, fmod, modf)
[musl] / src / math / atan2l.c
1 /* origin: FreeBSD /usr/src/lib/msun/src/e_atan2l.c */
2 /*
3  * ====================================================
4  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5  *
6  * Developed at SunSoft, a Sun Microsystems, Inc. business.
7  * Permission to use, copy, modify, and distribute this
8  * software is freely granted, provided that this notice
9  * is preserved.
10  * ====================================================
11  *
12  */
13 /*
14  * See comments in atan2.c.
15  * Converted to long double by David Schultz <das@FreeBSD.ORG>.
16  */
17
18 #include "libm.h"
19
20 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
21 long double atan2l(long double y, long double x)
22 {
23         return atan2(y, x);
24 }
25 #elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384
26 #include "__invtrigl.h"
27
28 long double atan2l(long double y, long double x)
29 {
30         union IEEEl2bits ux, uy;
31         long double z;
32         int m;
33         uint16_t exptx, expsignx, expty, expsigny;
34
35         if (isnan(x) || isnan(y))
36                 return x+y;
37         if (x == 1)
38                 return atanl(y);
39         uy.e = y;
40         expsigny = uy.xbits.expsign;
41         expty = expsigny & 0x7fff;
42         ux.e = x;
43         expsignx = ux.xbits.expsign;
44         exptx = expsignx & 0x7fff;
45         m = ((expsigny>>15)&1) | ((expsignx>>14)&2);  /* 2*sign(x)+sign(y) */
46
47         if (y == 0) {
48                 switch(m) {
49                 case 0:
50                 case 1: return y;           /* atan(+-0,+anything)=+-0 */
51                 case 2: return  2*pio2_hi+0x1p-120f; /* atan(+0,-anything) = pi */
52                 case 3: return -2*pio2_hi-0x1p-120f; /* atan(-0,-anything) =-pi */
53                 }
54         }
55         if (x == 0)
56                 return m&1 ? -pio2_hi-0x1p-120f : pio2_hi+0x1p-120f;
57         /* when x is INF */
58         if (exptx == 0x7fff) {
59                 if (expty == 0x7fff) {
60                         switch(m) {
61                         case 0: return  pio2_hi*0.5+0x1p-120f; /* atan(+INF,+INF) */
62                         case 1: return -pio2_hi*0.5-0x1p-120f; /* atan(-INF,+INF) */
63                         case 2: return  1.5*pio2_hi+0x1p-120f; /* atan(+INF,-INF) */
64                         case 3: return -1.5*pio2_hi-0x1p-120f; /* atan(-INF,-INF) */
65                         }
66                 } else {
67                         switch(m) {
68                         case 0: return  0.0;        /* atan(+...,+INF) */
69                         case 1: return -0.0;        /* atan(-...,+INF) */
70                         case 2: return  2*pio2_hi+0x1p-120f; /* atan(+...,-INF) */
71                         case 3: return -2*pio2_hi-0x1p-120f; /* atan(-...,-INF) */
72                         }
73                 }
74         }
75         /* when y is INF */
76         if (exptx+120 < expty || expty == 0x7fff)
77                 return m&1 ? -pio2_hi-0x1p-120f : pio2_hi+0x1p-120f;
78
79         if ((m&2) && expty+120 < exptx) /* |y/x| tiny, x<0 */
80                 z = 0.0;
81         else
82                 z = atanl(fabsl(y/x));
83         switch (m) {
84         case 0: return z;               /* atan(+,+) */
85         case 1: return -z;              /* atan(-,+) */
86         case 2: return 2*pio2_hi-(z-2*pio2_lo); /* atan(+,-) */
87         default: /* case 3 */
88                 return (z-2*pio2_lo)-2*pio2_hi; /* atan(-,-) */
89         }
90 }
91 #endif