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