1425bb815Sopenharmony_ci/* Copyright JS Foundation and other contributors, http://js.foundation
2425bb815Sopenharmony_ci *
3425bb815Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4425bb815Sopenharmony_ci * you may not use this file except in compliance with the License.
5425bb815Sopenharmony_ci * You may obtain a copy of the License at
6425bb815Sopenharmony_ci *
7425bb815Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8425bb815Sopenharmony_ci *
9425bb815Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10425bb815Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS
11425bb815Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12425bb815Sopenharmony_ci * See the License for the specific language governing permissions and
13425bb815Sopenharmony_ci * limitations under the License.
14425bb815Sopenharmony_ci *
15425bb815Sopenharmony_ci * This file is based on work under the following copyright and permission
16425bb815Sopenharmony_ci * notice:
17425bb815Sopenharmony_ci *
18425bb815Sopenharmony_ci *     Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
19425bb815Sopenharmony_ci *
20425bb815Sopenharmony_ci *     Developed at SunSoft, a Sun Microsystems, Inc. business.
21425bb815Sopenharmony_ci *     Permission to use, copy, modify, and distribute this
22425bb815Sopenharmony_ci *     software is freely granted, provided that this notice
23425bb815Sopenharmony_ci *     is preserved.
24425bb815Sopenharmony_ci *
25425bb815Sopenharmony_ci *     @(#)e_atan2.c 1.3 95/01/18
26425bb815Sopenharmony_ci */
27425bb815Sopenharmony_ci
28425bb815Sopenharmony_ci#include "jerry-libm-internal.h"
29425bb815Sopenharmony_ci
30425bb815Sopenharmony_ci/* atan2(y,x)
31425bb815Sopenharmony_ci *
32425bb815Sopenharmony_ci * Method:
33425bb815Sopenharmony_ci *      1. Reduce y to positive by atan2(y,x)=-atan2(-y,x).
34425bb815Sopenharmony_ci *      2. Reduce x to positive by (if x and y are unexceptional):
35425bb815Sopenharmony_ci *              ARG (x+iy) = arctan(y/x)           ... if x > 0,
36425bb815Sopenharmony_ci *              ARG (x+iy) = pi - arctan[y/(-x)]   ... if x < 0,
37425bb815Sopenharmony_ci *
38425bb815Sopenharmony_ci * Special cases:
39425bb815Sopenharmony_ci *      ATAN2((anything), NaN ) is NaN;
40425bb815Sopenharmony_ci *      ATAN2(NAN , (anything) ) is NaN;
41425bb815Sopenharmony_ci *      ATAN2(+-0, +(anything but NaN)) is +-0  ;
42425bb815Sopenharmony_ci *      ATAN2(+-0, -(anything but NaN)) is +-pi ;
43425bb815Sopenharmony_ci *      ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2;
44425bb815Sopenharmony_ci *      ATAN2(+-(anything but INF and NaN), +INF) is +-0 ;
45425bb815Sopenharmony_ci *      ATAN2(+-(anything but INF and NaN), -INF) is +-pi;
46425bb815Sopenharmony_ci *      ATAN2(+-INF,+INF ) is +-pi/4 ;
47425bb815Sopenharmony_ci *      ATAN2(+-INF,-INF ) is +-3pi/4;
48425bb815Sopenharmony_ci *      ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2;
49425bb815Sopenharmony_ci *
50425bb815Sopenharmony_ci * Constants:
51425bb815Sopenharmony_ci * The hexadecimal values are the intended ones for the following
52425bb815Sopenharmony_ci * constants. The decimal values may be used, provided that the
53425bb815Sopenharmony_ci * compiler will convert from decimal to binary accurately enough
54425bb815Sopenharmony_ci * to produce the hexadecimal values shown.
55425bb815Sopenharmony_ci */
56425bb815Sopenharmony_ci
57425bb815Sopenharmony_ci#define tiny   1.0e-300
58425bb815Sopenharmony_ci#define zero   0.0
59425bb815Sopenharmony_ci#define pi_o_4 7.8539816339744827900E-01 /* 0x3FE921FB, 0x54442D18 */
60425bb815Sopenharmony_ci#define pi_o_2 1.5707963267948965580E+00 /* 0x3FF921FB, 0x54442D18 */
61425bb815Sopenharmony_ci#define pi     3.1415926535897931160E+00 /* 0x400921FB, 0x54442D18 */
62425bb815Sopenharmony_ci#define pi_lo  1.2246467991473531772E-16 /* 0x3CA1A626, 0x33145C07 */
63425bb815Sopenharmony_ci
64425bb815Sopenharmony_cidouble
65425bb815Sopenharmony_ciatan2 (double y, double x)
66425bb815Sopenharmony_ci{
67425bb815Sopenharmony_ci  double_accessor z;
68425bb815Sopenharmony_ci  int k, m, hx, hy, ix, iy;
69425bb815Sopenharmony_ci  unsigned lx, ly;
70425bb815Sopenharmony_ci
71425bb815Sopenharmony_ci  hx = __HI (x);
72425bb815Sopenharmony_ci  ix = hx & 0x7fffffff;
73425bb815Sopenharmony_ci  lx = __LO (x);
74425bb815Sopenharmony_ci  hy = __HI (y);
75425bb815Sopenharmony_ci  iy = hy & 0x7fffffff;
76425bb815Sopenharmony_ci  ly = __LO (y);
77425bb815Sopenharmony_ci  if (((ix | ((lx | -lx) >> 31)) > 0x7ff00000) || ((iy | ((ly | -ly) >> 31)) > 0x7ff00000)) /* x or y is NaN */
78425bb815Sopenharmony_ci  {
79425bb815Sopenharmony_ci    return x + y;
80425bb815Sopenharmony_ci  }
81425bb815Sopenharmony_ci  if (((hx - 0x3ff00000) | lx) == 0) /* x = 1.0 */
82425bb815Sopenharmony_ci  {
83425bb815Sopenharmony_ci    return atan (y);
84425bb815Sopenharmony_ci  }
85425bb815Sopenharmony_ci  m = ((hy < 0) ? 1 : 0) + ((hx < 0) ? 2 : 0); /* 2 * sign(x) + sign(y) */
86425bb815Sopenharmony_ci
87425bb815Sopenharmony_ci  /* when y = 0 */
88425bb815Sopenharmony_ci  if ((iy | ly) == 0)
89425bb815Sopenharmony_ci  {
90425bb815Sopenharmony_ci    switch (m)
91425bb815Sopenharmony_ci    {
92425bb815Sopenharmony_ci      case 0:
93425bb815Sopenharmony_ci      case 1:
94425bb815Sopenharmony_ci      {
95425bb815Sopenharmony_ci        return y; /* atan(+-0,+anything) = +-0 */
96425bb815Sopenharmony_ci      }
97425bb815Sopenharmony_ci      case 2:
98425bb815Sopenharmony_ci      {
99425bb815Sopenharmony_ci        return pi + tiny; /* atan(+0,-anything) = pi */
100425bb815Sopenharmony_ci      }
101425bb815Sopenharmony_ci      case 3:
102425bb815Sopenharmony_ci      {
103425bb815Sopenharmony_ci        return -pi - tiny; /* atan(-0,-anything) = -pi */
104425bb815Sopenharmony_ci      }
105425bb815Sopenharmony_ci    }
106425bb815Sopenharmony_ci  }
107425bb815Sopenharmony_ci  /* when x = 0 */
108425bb815Sopenharmony_ci  if ((ix | lx) == 0)
109425bb815Sopenharmony_ci  {
110425bb815Sopenharmony_ci    return (hy < 0) ? -pi_o_2 - tiny : pi_o_2 + tiny;
111425bb815Sopenharmony_ci  }
112425bb815Sopenharmony_ci
113425bb815Sopenharmony_ci  /* when x is INF */
114425bb815Sopenharmony_ci  if (ix == 0x7ff00000)
115425bb815Sopenharmony_ci  {
116425bb815Sopenharmony_ci    if (iy == 0x7ff00000)
117425bb815Sopenharmony_ci    {
118425bb815Sopenharmony_ci      switch (m)
119425bb815Sopenharmony_ci      {
120425bb815Sopenharmony_ci        case 0: /* atan(+INF,+INF) */
121425bb815Sopenharmony_ci        {
122425bb815Sopenharmony_ci          return pi_o_4 + tiny;
123425bb815Sopenharmony_ci        }
124425bb815Sopenharmony_ci        case 1: /* atan(-INF,+INF) */
125425bb815Sopenharmony_ci        {
126425bb815Sopenharmony_ci          return -pi_o_4 - tiny;
127425bb815Sopenharmony_ci        }
128425bb815Sopenharmony_ci        case 2: /* atan(+INF,-INF) */
129425bb815Sopenharmony_ci        {
130425bb815Sopenharmony_ci          return 3.0 * pi_o_4 + tiny;
131425bb815Sopenharmony_ci        }
132425bb815Sopenharmony_ci        case 3: /* atan(-INF,-INF) */
133425bb815Sopenharmony_ci        {
134425bb815Sopenharmony_ci          return -3.0 * pi_o_4 - tiny;
135425bb815Sopenharmony_ci        }
136425bb815Sopenharmony_ci      }
137425bb815Sopenharmony_ci    }
138425bb815Sopenharmony_ci    else
139425bb815Sopenharmony_ci    {
140425bb815Sopenharmony_ci      switch (m)
141425bb815Sopenharmony_ci      {
142425bb815Sopenharmony_ci        case 0: /* atan(+...,+INF) */
143425bb815Sopenharmony_ci        {
144425bb815Sopenharmony_ci          return zero;
145425bb815Sopenharmony_ci        }
146425bb815Sopenharmony_ci        case 1: /* atan(-...,+INF) */
147425bb815Sopenharmony_ci        {
148425bb815Sopenharmony_ci          return -zero;
149425bb815Sopenharmony_ci        }
150425bb815Sopenharmony_ci        case 2: /* atan(+...,-INF) */
151425bb815Sopenharmony_ci        {
152425bb815Sopenharmony_ci          return pi + tiny;
153425bb815Sopenharmony_ci        }
154425bb815Sopenharmony_ci        case 3: /* atan(-...,-INF) */
155425bb815Sopenharmony_ci        {
156425bb815Sopenharmony_ci          return -pi - tiny;
157425bb815Sopenharmony_ci        }
158425bb815Sopenharmony_ci      }
159425bb815Sopenharmony_ci    }
160425bb815Sopenharmony_ci  }
161425bb815Sopenharmony_ci  /* when y is INF */
162425bb815Sopenharmony_ci  if (iy == 0x7ff00000)
163425bb815Sopenharmony_ci  {
164425bb815Sopenharmony_ci    return (hy < 0) ? -pi_o_2 - tiny : pi_o_2 + tiny;
165425bb815Sopenharmony_ci  }
166425bb815Sopenharmony_ci
167425bb815Sopenharmony_ci  /* compute y / x */
168425bb815Sopenharmony_ci  k = (iy - ix) >> 20;
169425bb815Sopenharmony_ci  if (k > 60) /* |y / x| > 2**60 */
170425bb815Sopenharmony_ci  {
171425bb815Sopenharmony_ci    z.dbl = pi_o_2 + 0.5 * pi_lo;
172425bb815Sopenharmony_ci  }
173425bb815Sopenharmony_ci  else if (hx < 0 && k < -60) /* |y| / x < -2**60 */
174425bb815Sopenharmony_ci  {
175425bb815Sopenharmony_ci    z.dbl = 0.0;
176425bb815Sopenharmony_ci  }
177425bb815Sopenharmony_ci  else /* safe to do y / x */
178425bb815Sopenharmony_ci  {
179425bb815Sopenharmony_ci    z.dbl = atan (fabs (y / x));
180425bb815Sopenharmony_ci  }
181425bb815Sopenharmony_ci  switch (m)
182425bb815Sopenharmony_ci  {
183425bb815Sopenharmony_ci    case 0: /* atan(+,+) */
184425bb815Sopenharmony_ci    {
185425bb815Sopenharmony_ci      return z.dbl;
186425bb815Sopenharmony_ci    }
187425bb815Sopenharmony_ci    case 1: /* atan(-,+) */
188425bb815Sopenharmony_ci    {
189425bb815Sopenharmony_ci      z.as_int.hi ^= 0x80000000;
190425bb815Sopenharmony_ci      return z.dbl;
191425bb815Sopenharmony_ci    }
192425bb815Sopenharmony_ci    case 2: /* atan(+,-) */
193425bb815Sopenharmony_ci    {
194425bb815Sopenharmony_ci      return pi - (z.dbl - pi_lo);
195425bb815Sopenharmony_ci    }
196425bb815Sopenharmony_ci    /* case 3: */
197425bb815Sopenharmony_ci    default: /* atan(-,-) */
198425bb815Sopenharmony_ci    {
199425bb815Sopenharmony_ci      return (z.dbl - pi_lo) - pi;
200425bb815Sopenharmony_ci    }
201425bb815Sopenharmony_ci  }
202425bb815Sopenharmony_ci} /* atan2 */
203425bb815Sopenharmony_ci
204425bb815Sopenharmony_ci#undef tiny
205425bb815Sopenharmony_ci#undef zero
206425bb815Sopenharmony_ci#undef pi_o_4
207425bb815Sopenharmony_ci#undef pi_o_2
208425bb815Sopenharmony_ci#undef pi
209425bb815Sopenharmony_ci#undef pi_lo
210