1 /*
2  * IBM Accurate Mathematical Library
3  * written by International Business Machines Corp.
4  * Copyright (C) 2001-2022 Free Software Foundation, Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2.1 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, see <https://www.gnu.org/licenses/>.
18  */
19 /************************************************************************/
20 /*  MODULE_NAME: atnat.c                                                */
21 /*                                                                      */
22 /*  FUNCTIONS:  uatan                                                   */
23 /*              signArctan                                              */
24 /*                                                                      */
25 /*  FILES NEEDED: dla.h endian.h mydefs.h atnat.h                       */
26 /*                uatan.tbl                                             */
27 /*                                                                      */
28 /************************************************************************/
29 
30 #include <dla.h>
31 #include "mydefs.h"
32 #include "uatan.tbl"
33 #include "atnat.h"
34 #include <fenv.h>
35 #include <float.h>
36 #include <libm-alias-double.h>
37 #include <math.h>
38 #include <fenv_private.h>
39 #include <math-underflow.h>
40 
41 #define  TWO52     0x1.0p52
42 
43   /* Fix the sign of y and return */
44 static double
__signArctan(double x,double y)45 __signArctan (double x, double y)
46 {
47   return copysign (y, x);
48 }
49 
50 /* atan with max ULP of ~0.523 based on random sampling.  */
51 double
__atan(double x)52 __atan (double x)
53 {
54   double cor, t1, t2, t3, u,
55 	 v, w, ww, y, yy, z;
56   int i, ux, dx;
57   mynumber num;
58 
59   num.d = x;
60   ux = num.i[HIGH_HALF];
61   dx = num.i[LOW_HALF];
62 
63   /* x=NaN */
64   if (((ux & 0x7ff00000) == 0x7ff00000)
65       && (((ux & 0x000fffff) | dx) != 0x00000000))
66     return x + x;
67 
68   /* Regular values of x, including denormals +-0 and +-INF */
69   SET_RESTORE_ROUND (FE_TONEAREST);
70   u = (x < 0) ? -x : x;
71   if (u < C)
72     {
73       if (u < B)
74 	{
75 	  if (u < A)
76 	    {
77 	      math_check_force_underflow_nonneg (u);
78 	      return x;
79 	    }
80 	  else
81 	    {			/* A <= u < B */
82 	      v = x * x;
83 	      yy = d11.d + v * d13.d;
84 	      yy = d9.d + v * yy;
85 	      yy = d7.d + v * yy;
86 	      yy = d5.d + v * yy;
87 	      yy = d3.d + v * yy;
88 	      yy *= x * v;
89 
90 	      y = x + yy;
91 	      /* Max ULP is 0.511.  */
92 	      return y;
93 	    }
94 	}
95       else
96 	{			/* B <= u < C */
97 	  i = (TWO52 + 256 * u) - TWO52;
98 	  i -= 16;
99 	  z = u - cij[i][0].d;
100 	  yy = cij[i][5].d + z * cij[i][6].d;
101 	  yy = cij[i][4].d + z * yy;
102 	  yy = cij[i][3].d + z * yy;
103 	  yy = cij[i][2].d + z * yy;
104 	  yy *= z;
105 
106 	  t1 = cij[i][1].d;
107 	  y = t1 + yy;
108 	  /* Max ULP is 0.56.  */
109 	  return __signArctan (x, y);
110 	}
111     }
112   else
113     {
114       if (u < D)
115 	{			/* C <= u < D */
116 	  w = 1 / u;
117 	  EMULV (w, u, t1, t2);
118 	  ww = w * ((1 - t1) - t2);
119 	  i = (TWO52 + 256 * w) - TWO52;
120 	  i -= 16;
121 	  z = (w - cij[i][0].d) + ww;
122 
123 	  yy = cij[i][5].d + z * cij[i][6].d;
124 	  yy = cij[i][4].d + z * yy;
125 	  yy = cij[i][3].d + z * yy;
126 	  yy = cij[i][2].d + z * yy;
127 	  yy = HPI1 - z * yy;
128 
129 	  t1 = HPI - cij[i][1].d;
130 	  y = t1 + yy;
131 	  /* Max ULP is 0.503.  */
132 	  return __signArctan (x, y);
133 	}
134       else
135 	{
136 	  if (u < E)
137 	    {                   /* D <= u < E */
138 	      w = 1 / u;
139 	      v = w * w;
140 	      EMULV (w, u, t1, t2);
141 
142 	      yy = d11.d + v * d13.d;
143 	      yy = d9.d + v * yy;
144 	      yy = d7.d + v * yy;
145 	      yy = d5.d + v * yy;
146 	      yy = d3.d + v * yy;
147 	      yy *= w * v;
148 
149 	      ww = w * ((1 - t1) - t2);
150 	      ESUB (HPI, w, t3, cor);
151 	      yy = ((HPI1 + cor) - ww) - yy;
152 	      y = t3 + yy;
153 	      /* Max ULP is 0.5003.  */
154 	      return __signArctan (x, y);
155 	    }
156 	  else
157 	    {
158 	      /* u >= E */
159 	      if (x > 0)
160 		return HPI;
161 	      else
162 		return MHPI;
163 	    }
164 	}
165     }
166 }
167 
168 #ifndef __atan
169 libm_alias_double (__atan, atan)
170 #endif
171