xref: /titanic_52/usr/src/lib/libm/common/complex/k_atan2.c (revision 25c28e83beb90e7c80452a7c818c5e6f73a07dc8)
1*25c28e83SPiotr Jasiukajtis /*
2*25c28e83SPiotr Jasiukajtis  * CDDL HEADER START
3*25c28e83SPiotr Jasiukajtis  *
4*25c28e83SPiotr Jasiukajtis  * The contents of this file are subject to the terms of the
5*25c28e83SPiotr Jasiukajtis  * Common Development and Distribution License (the "License").
6*25c28e83SPiotr Jasiukajtis  * You may not use this file except in compliance with the License.
7*25c28e83SPiotr Jasiukajtis  *
8*25c28e83SPiotr Jasiukajtis  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*25c28e83SPiotr Jasiukajtis  * or http://www.opensolaris.org/os/licensing.
10*25c28e83SPiotr Jasiukajtis  * See the License for the specific language governing permissions
11*25c28e83SPiotr Jasiukajtis  * and limitations under the License.
12*25c28e83SPiotr Jasiukajtis  *
13*25c28e83SPiotr Jasiukajtis  * When distributing Covered Code, include this CDDL HEADER in each
14*25c28e83SPiotr Jasiukajtis  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*25c28e83SPiotr Jasiukajtis  * If applicable, add the following below this CDDL HEADER, with the
16*25c28e83SPiotr Jasiukajtis  * fields enclosed by brackets "[]" replaced with your own identifying
17*25c28e83SPiotr Jasiukajtis  * information: Portions Copyright [yyyy] [name of copyright owner]
18*25c28e83SPiotr Jasiukajtis  *
19*25c28e83SPiotr Jasiukajtis  * CDDL HEADER END
20*25c28e83SPiotr Jasiukajtis  */
21*25c28e83SPiotr Jasiukajtis /*
22*25c28e83SPiotr Jasiukajtis  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
23*25c28e83SPiotr Jasiukajtis  */
24*25c28e83SPiotr Jasiukajtis /*
25*25c28e83SPiotr Jasiukajtis  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
26*25c28e83SPiotr Jasiukajtis  * Use is subject to license terms.
27*25c28e83SPiotr Jasiukajtis  */
28*25c28e83SPiotr Jasiukajtis 
29*25c28e83SPiotr Jasiukajtis #include "libm.h"		/* __k_atan2 */
30*25c28e83SPiotr Jasiukajtis #include "complex_wrapper.h"
31*25c28e83SPiotr Jasiukajtis 
32*25c28e83SPiotr Jasiukajtis /*
33*25c28e83SPiotr Jasiukajtis  * double __k_atan2(double y, double x, double *e)
34*25c28e83SPiotr Jasiukajtis  *
35*25c28e83SPiotr Jasiukajtis  * Compute atan2 with error terms.
36*25c28e83SPiotr Jasiukajtis  *
37*25c28e83SPiotr Jasiukajtis  * Important formula:
38*25c28e83SPiotr Jasiukajtis  *                  3       5
39*25c28e83SPiotr Jasiukajtis  *                 x       x
40*25c28e83SPiotr Jasiukajtis  * atan(x) = x - ----- + ----- - ...	(for x <= 1)
41*25c28e83SPiotr Jasiukajtis  *                 3       5
42*25c28e83SPiotr Jasiukajtis  *
43*25c28e83SPiotr Jasiukajtis  *           pi     1     1
44*25c28e83SPiotr Jasiukajtis  *         = --- - --- + --- - ...	(for x > 1)
45*25c28e83SPiotr Jasiukajtis  *                         3
46*25c28e83SPiotr Jasiukajtis  *            2     x    3x
47*25c28e83SPiotr Jasiukajtis  *
48*25c28e83SPiotr Jasiukajtis  * Arg(x + y i) = sign(y) * atan2(|y|, x)
49*25c28e83SPiotr Jasiukajtis  *              = sign(y) * atan(|y|/x)		  (for x > 0)
50*25c28e83SPiotr Jasiukajtis  *                sign(y) * (PI - atan(|y|/|x|))  (for x < 0)
51*25c28e83SPiotr Jasiukajtis  * Thus if x >> y (IEEE double: EXP(x) - EXP(y) >= 60):
52*25c28e83SPiotr Jasiukajtis  *	1. (x > 0): atan2(y,x) ~ y/x
53*25c28e83SPiotr Jasiukajtis  *	2. (x < 0): atan2(y,x) ~ sign(y) (PI - |y/x|))
54*25c28e83SPiotr Jasiukajtis  * Otherwise if x << y:
55*25c28e83SPiotr Jasiukajtis  *	atan2(y,x) ~ sign(y)*PI/2 - x/y
56*25c28e83SPiotr Jasiukajtis  *
57*25c28e83SPiotr Jasiukajtis  * __k_atan2 call static functions mx_poly, mx_atan
58*25c28e83SPiotr Jasiukajtis  */
59*25c28e83SPiotr Jasiukajtis 
60*25c28e83SPiotr Jasiukajtis /*
61*25c28e83SPiotr Jasiukajtis  * (void) mx_poly (double *z, double *a, double *e, int n)
62*25c28e83SPiotr Jasiukajtis  * return
63*25c28e83SPiotr Jasiukajtis  *	e = a  + z*(a  + z*(a  + ... z*(a  + e)...))
64*25c28e83SPiotr Jasiukajtis  *	     0       2       4           2n
65*25c28e83SPiotr Jasiukajtis  * Note:
66*25c28e83SPiotr Jasiukajtis  * 1.	e and coefficient ai are represented by two double numbers.
67*25c28e83SPiotr Jasiukajtis  *	For e, the first one contain the leading 24 bits rounded, and the
68*25c28e83SPiotr Jasiukajtis  *	second one contain the remaining 53 bits (total 77 bits accuracy).
69*25c28e83SPiotr Jasiukajtis  *	For ai, the first one contian the leading 53 bits rounded, and the
70*25c28e83SPiotr Jasiukajtis  *	second is the remaining 53 bits (total 106 bits accuracy).
71*25c28e83SPiotr Jasiukajtis  * 2.	z is an array of three doubles.
72*25c28e83SPiotr Jasiukajtis  * 	z[0] :	the rounded value of Z (the intended value of z)
73*25c28e83SPiotr Jasiukajtis  * 	z[1] :	the leading 24 bits of Z rounded
74*25c28e83SPiotr Jasiukajtis  * 	z[2] :	the remaining 53 bits of Z
75*25c28e83SPiotr Jasiukajtis  *		Note that z[0] = z[1]+z[2] rounded.
76*25c28e83SPiotr Jasiukajtis  *
77*25c28e83SPiotr Jasiukajtis  */
78*25c28e83SPiotr Jasiukajtis 
79*25c28e83SPiotr Jasiukajtis static void
80*25c28e83SPiotr Jasiukajtis mx_poly(const double *z, const double *a, double *e, int n) {
81*25c28e83SPiotr Jasiukajtis 	double r, s, t, p_h, p_l, z_h, z_l, p;
82*25c28e83SPiotr Jasiukajtis 	int i;
83*25c28e83SPiotr Jasiukajtis 
84*25c28e83SPiotr Jasiukajtis 	n = n + n;
85*25c28e83SPiotr Jasiukajtis 	p = e[0] + a[n];
86*25c28e83SPiotr Jasiukajtis 	p_l = a[n + 1];
87*25c28e83SPiotr Jasiukajtis 	p_h = (double) ((float) p);
88*25c28e83SPiotr Jasiukajtis 	p   = a[n - 2] + z[0] * p;
89*25c28e83SPiotr Jasiukajtis 	z_h = z[1]; z_l = z[2];
90*25c28e83SPiotr Jasiukajtis 	p_l += e[0] - (p_h - a[n]);
91*25c28e83SPiotr Jasiukajtis 
92*25c28e83SPiotr Jasiukajtis 	for (i = n - 2; i >= 2; i -= 2) {
93*25c28e83SPiotr Jasiukajtis 	/* compute p = ai + z * p */
94*25c28e83SPiotr Jasiukajtis 		t   = z_h * p_h;
95*25c28e83SPiotr Jasiukajtis 		s   = z[0] * p_l + p_h * z_l;
96*25c28e83SPiotr Jasiukajtis 		p_h = (double) ((float) p);
97*25c28e83SPiotr Jasiukajtis 		s  += a[i + 1];
98*25c28e83SPiotr Jasiukajtis 		r   = t - (p_h - a[i]);
99*25c28e83SPiotr Jasiukajtis 		p   = a[i - 2] + z[0] * p;
100*25c28e83SPiotr Jasiukajtis 		p_l = r + s;
101*25c28e83SPiotr Jasiukajtis 	}
102*25c28e83SPiotr Jasiukajtis 	e[0] = (double)((float) p);
103*25c28e83SPiotr Jasiukajtis 	t   = z_h * p_h;
104*25c28e83SPiotr Jasiukajtis 	s   = z[0] * p_l + p_h * z_l;
105*25c28e83SPiotr Jasiukajtis 	r   = t - (e[0] - a[0]);
106*25c28e83SPiotr Jasiukajtis 	e[1] = r + s;
107*25c28e83SPiotr Jasiukajtis }
108*25c28e83SPiotr Jasiukajtis 
109*25c28e83SPiotr Jasiukajtis /*
110*25c28e83SPiotr Jasiukajtis  * Table of constants for atan from 0.125 to 8
111*25c28e83SPiotr Jasiukajtis  *	0.125 -- 0x3fc00000  --- (increment at bit 16)
112*25c28e83SPiotr Jasiukajtis  *		 0x3fc10000
113*25c28e83SPiotr Jasiukajtis  *		 0x3fc20000
114*25c28e83SPiotr Jasiukajtis  *	...	...
115*25c28e83SPiotr Jasiukajtis  *		 0x401f0000
116*25c28e83SPiotr Jasiukajtis  *	8.000 -- 0x40200000	 (total: 97)
117*25c28e83SPiotr Jasiukajtis  * By K.C. Ng, March 9, 1989
118*25c28e83SPiotr Jasiukajtis  */
119*25c28e83SPiotr Jasiukajtis 
120*25c28e83SPiotr Jasiukajtis static const double TBL_atan_hi[] = {
121*25c28e83SPiotr Jasiukajtis 1.243549945467614382e-01, 1.320397616146387620e-01, 1.397088742891636204e-01,
122*25c28e83SPiotr Jasiukajtis 1.473614810886516302e-01, 1.549967419239409727e-01, 1.626138285979485676e-01,
123*25c28e83SPiotr Jasiukajtis 1.702119252854744080e-01, 1.777902289926760471e-01, 1.853479499956947607e-01,
124*25c28e83SPiotr Jasiukajtis 1.928843122579746439e-01, 2.003985538258785115e-01, 2.078899272022629863e-01,
125*25c28e83SPiotr Jasiukajtis 2.153576996977380476e-01, 2.228011537593945213e-01, 2.302195872768437179e-01,
126*25c28e83SPiotr Jasiukajtis 2.376123138654712419e-01, 2.449786631268641435e-01, 2.596296294082575118e-01,
127*25c28e83SPiotr Jasiukajtis 2.741674511196587893e-01, 2.885873618940774099e-01, 3.028848683749714166e-01,
128*25c28e83SPiotr Jasiukajtis 3.170557532091470287e-01, 3.310960767041321029e-01, 3.450021772071051318e-01,
129*25c28e83SPiotr Jasiukajtis 3.587706702705721895e-01, 3.723984466767542023e-01, 3.858826693980737521e-01,
130*25c28e83SPiotr Jasiukajtis 3.992207695752525431e-01, 4.124104415973872673e-01, 4.254496373700422662e-01,
131*25c28e83SPiotr Jasiukajtis 4.383365598579578304e-01, 4.510696559885234436e-01, 4.636476090008060935e-01,
132*25c28e83SPiotr Jasiukajtis 4.883339510564055352e-01, 5.123894603107377321e-01, 5.358112379604637043e-01,
133*25c28e83SPiotr Jasiukajtis 5.585993153435624414e-01, 5.807563535676704136e-01, 6.022873461349641522e-01,
134*25c28e83SPiotr Jasiukajtis 6.231993299340659043e-01, 6.435011087932843710e-01, 6.632029927060932861e-01,
135*25c28e83SPiotr Jasiukajtis 6.823165548747480713e-01, 7.008544078844501923e-01, 7.188299996216245269e-01,
136*25c28e83SPiotr Jasiukajtis 7.362574289814280970e-01, 7.531512809621944138e-01, 7.695264804056582975e-01,
137*25c28e83SPiotr Jasiukajtis 7.853981633974482790e-01, 8.156919233162234217e-01, 8.441539861131710509e-01,
138*25c28e83SPiotr Jasiukajtis 8.709034570756529758e-01, 8.960553845713439269e-01, 9.197196053504168578e-01,
139*25c28e83SPiotr Jasiukajtis 9.420000403794636101e-01, 9.629943306809362058e-01, 9.827937232473290541e-01,
140*25c28e83SPiotr Jasiukajtis 1.001483135694234639e+00, 1.019141344266349725e+00, 1.035841253008800145e+00,
141*25c28e83SPiotr Jasiukajtis 1.051650212548373764e+00, 1.066630365315743623e+00, 1.080839000541168327e+00,
142*25c28e83SPiotr Jasiukajtis 1.094328907321189925e+00, 1.107148717794090409e+00, 1.130953743979160375e+00,
143*25c28e83SPiotr Jasiukajtis 1.152571997215667610e+00, 1.172273881128476303e+00, 1.190289949682531656e+00,
144*25c28e83SPiotr Jasiukajtis 1.206817370285252489e+00, 1.222025323210989667e+00, 1.236059489478081863e+00,
145*25c28e83SPiotr Jasiukajtis 1.249045772398254428e+00, 1.261093382252440387e+00, 1.272297395208717319e+00,
146*25c28e83SPiotr Jasiukajtis 1.282740879744270757e+00, 1.292496667789785336e+00, 1.301628834009196156e+00,
147*25c28e83SPiotr Jasiukajtis 1.310193935047555547e+00, 1.318242051016837113e+00, 1.325817663668032553e+00,
148*25c28e83SPiotr Jasiukajtis 1.339705659598999565e+00, 1.352127380920954636e+00, 1.363300100359693845e+00,
149*25c28e83SPiotr Jasiukajtis 1.373400766945015894e+00, 1.382574821490125894e+00, 1.390942827002418447e+00,
150*25c28e83SPiotr Jasiukajtis 1.398605512271957618e+00, 1.405647649380269870e+00, 1.412141064608495311e+00,
151*25c28e83SPiotr Jasiukajtis 1.418146998399631542e+00, 1.423717971406494032e+00, 1.428899272190732761e+00,
152*25c28e83SPiotr Jasiukajtis 1.433730152484709031e+00, 1.438244794498222623e+00, 1.442473099109101931e+00,
153*25c28e83SPiotr Jasiukajtis 1.446441332248135092e+00,
154*25c28e83SPiotr Jasiukajtis };
155*25c28e83SPiotr Jasiukajtis 
156*25c28e83SPiotr Jasiukajtis static const double TBL_atan_lo[] = {
157*25c28e83SPiotr Jasiukajtis -3.125324142453938311e-18, -1.276925400709959526e-17, 2.479758919089733066e-17,
158*25c28e83SPiotr Jasiukajtis 5.409599147666297957e-18, 9.585415594114323829e-18, 7.784470643106252464e-18,
159*25c28e83SPiotr Jasiukajtis -3.541164079802125137e-18, 2.372599351477449041e-17, 4.180692268843078977e-18,
160*25c28e83SPiotr Jasiukajtis 2.034098543938166622e-17, 3.139954287184449286e-18, 7.333160666520898500e-18,
161*25c28e83SPiotr Jasiukajtis 4.738160130078732886e-19, -5.498822172446843173e-18, 1.231340452914270316e-17,
162*25c28e83SPiotr Jasiukajtis 1.058231431371112987e-17, 1.069875561873445139e-17, 1.923875492461530410e-17,
163*25c28e83SPiotr Jasiukajtis 8.261353575163771936e-18, -1.428369957377257085e-17, -1.101082790300136900e-17,
164*25c28e83SPiotr Jasiukajtis -1.893928924292642146e-17, -7.952610375793798701e-18, -2.293880475557830393e-17,
165*25c28e83SPiotr Jasiukajtis 3.088733564861919217e-17, 1.961231150484565340e-17, 2.378822732491940868e-17,
166*25c28e83SPiotr Jasiukajtis 2.246598105617042065e-17, 3.963462895355093301e-17, 2.331553074189288466e-17,
167*25c28e83SPiotr Jasiukajtis -2.494277030626540909e-17, 3.280735600183735558e-17, 2.269877745296168709e-17,
168*25c28e83SPiotr Jasiukajtis -1.137323618932958456e-17, -2.546278147285580353e-17, -4.063795683482557497e-18,
169*25c28e83SPiotr Jasiukajtis -5.455630548591626394e-18, -1.441464378193066908e-17, 2.950430737228402307e-17,
170*25c28e83SPiotr Jasiukajtis 2.672403885140095079e-17, 1.583478505144428617e-17, -3.076054864429649001e-17,
171*25c28e83SPiotr Jasiukajtis 6.943223671560007740e-18, -1.987626234335816123e-17, -2.147838844445698302e-17,
172*25c28e83SPiotr Jasiukajtis 3.473937648299456719e-17, -2.425693465918206812e-17, -3.704991905602721293e-17,
173*25c28e83SPiotr Jasiukajtis 3.061616997868383018e-17, -1.071456562778743077e-17, -4.841337011934916763e-17,
174*25c28e83SPiotr Jasiukajtis -2.269823590747287052e-17, 2.923876285774304890e-17, -4.057439412852767923e-17,
175*25c28e83SPiotr Jasiukajtis 5.460837485846687627e-17, -3.986660595210752445e-18, 1.390331103123099845e-17,
176*25c28e83SPiotr Jasiukajtis 9.438308023545392000e-17, 1.000401886936679889e-17, 3.194313981784503706e-17,
177*25c28e83SPiotr Jasiukajtis -9.650564731467513515e-17, -5.956589637160374564e-17, -1.567632251135907253e-17,
178*25c28e83SPiotr Jasiukajtis -5.490676155022364226e-18, 9.404471373566379412e-17, 7.123833804538446299e-17,
179*25c28e83SPiotr Jasiukajtis -9.159738508900378819e-17, 8.385188614028674371e-17, 7.683333629842068806e-17,
180*25c28e83SPiotr Jasiukajtis 4.172467638861439118e-17, -2.979162864892849274e-17, 7.879752739459421280e-17,
181*25c28e83SPiotr Jasiukajtis -2.196203799612310905e-18, 3.242139621534960503e-17, 2.245875015034507026e-17,
182*25c28e83SPiotr Jasiukajtis -9.283188754266129476e-18, -6.830804768926660334e-17, -1.236918499824626670e-17,
183*25c28e83SPiotr Jasiukajtis 8.745413734780278834e-17, -6.319394031144676258e-17, -8.824429373951136321e-17,
184*25c28e83SPiotr Jasiukajtis -2.599011860304134377e-17, 2.147674250751150961e-17, 1.093246171526936217e-16,
185*25c28e83SPiotr Jasiukajtis -3.307710355769516504e-17, -3.561490438648230100e-17, -9.843712133488842595e-17,
186*25c28e83SPiotr Jasiukajtis -2.324061182591627982e-17, -8.922630138234492386e-17, -9.573807110557223276e-17,
187*25c28e83SPiotr Jasiukajtis -8.263883782511013632e-17, 8.721870922223967507e-17, -6.457134743238754385e-17,
188*25c28e83SPiotr Jasiukajtis -4.396204466767636187e-17, -2.493019910264565554e-17, -1.105119435430315713e-16,
189*25c28e83SPiotr Jasiukajtis 9.211323971545051565e-17,
190*25c28e83SPiotr Jasiukajtis };
191*25c28e83SPiotr Jasiukajtis 
192*25c28e83SPiotr Jasiukajtis /*
193*25c28e83SPiotr Jasiukajtis  * mx_atan(x,err)
194*25c28e83SPiotr Jasiukajtis  * Table look-up algorithm
195*25c28e83SPiotr Jasiukajtis  * By K.C. Ng, March 9, 1989
196*25c28e83SPiotr Jasiukajtis  *
197*25c28e83SPiotr Jasiukajtis  * Algorithm.
198*25c28e83SPiotr Jasiukajtis  *
199*25c28e83SPiotr Jasiukajtis  * The algorithm is based on atan(x)=atan(y)+atan((x-y)/(1+x*y)).
200*25c28e83SPiotr Jasiukajtis  * We use poly1(x) to approximate atan(x) for x in [0,1/8] with
201*25c28e83SPiotr Jasiukajtis  * error (relative)
202*25c28e83SPiotr Jasiukajtis  * 	|(atan(x)-poly1(x))/x|<= 2^-83.41
203*25c28e83SPiotr Jasiukajtis  *
204*25c28e83SPiotr Jasiukajtis  * and use poly2(x) to approximate atan(x) for x in [0,1/65] with
205*25c28e83SPiotr Jasiukajtis  * error
206*25c28e83SPiotr Jasiukajtis  *	|atan(x)-poly2(x)|<= 2^-86.8
207*25c28e83SPiotr Jasiukajtis  *
208*25c28e83SPiotr Jasiukajtis  * Here poly1 and poly2 are odd polynomial with the following form:
209*25c28e83SPiotr Jasiukajtis  *		x + x^3*(a1+x^2*(a2+...))
210*25c28e83SPiotr Jasiukajtis  *
211*25c28e83SPiotr Jasiukajtis  * (0). Purge off Inf and NaN and 0
212*25c28e83SPiotr Jasiukajtis  * (1). Reduce x to positive by atan(x) = -atan(-x).
213*25c28e83SPiotr Jasiukajtis  * (2). For x <= 1/8, use
214*25c28e83SPiotr Jasiukajtis  *	(2.1) if x < 2^(-prec/2), atan(x) =  x  with inexact flag raised
215*25c28e83SPiotr Jasiukajtis  *	(2.2) Otherwise
216*25c28e83SPiotr Jasiukajtis  *		atan(x) = poly1(x)
217*25c28e83SPiotr Jasiukajtis  * (3). For x >= 8 then (prec = 78)
218*25c28e83SPiotr Jasiukajtis  *	(3.1) if x >= 2^prec,     atan(x) = atan(inf) - pio2lo
219*25c28e83SPiotr Jasiukajtis  *	(3.2) if x >= 2^(prec/3), atan(x) = atan(inf) - 1/x
220*25c28e83SPiotr Jasiukajtis  *	(3.3) if x >  65,         atan(x) = atan(inf) - poly2(1/x)
221*25c28e83SPiotr Jasiukajtis  *	(3.4) Otherwise,	  atan(x) = atan(inf) - poly1(1/x)
222*25c28e83SPiotr Jasiukajtis  *
223*25c28e83SPiotr Jasiukajtis  * (4). Now x is in (0.125, 8)
224*25c28e83SPiotr Jasiukajtis  *      Find y that match x to 4.5 bit after binary (easy).
225*25c28e83SPiotr Jasiukajtis  *	If iy is the high word of y, then
226*25c28e83SPiotr Jasiukajtis  *		single : j = (iy - 0x3e000000) >> 19
227*25c28e83SPiotr Jasiukajtis  *		double : j = (iy - 0x3fc00000) >> 16
228*25c28e83SPiotr Jasiukajtis  *		quad   : j = (iy - 0x3ffc0000) >> 12
229*25c28e83SPiotr Jasiukajtis  *
230*25c28e83SPiotr Jasiukajtis  *	Let s = (x-y)/(1+x*y). Then
231*25c28e83SPiotr Jasiukajtis  *	atan(x) = atan(y) + poly1(s)
232*25c28e83SPiotr Jasiukajtis  *		= _TBL_atan_hi[j] + (_TBL_atan_lo[j] + poly2(s) )
233*25c28e83SPiotr Jasiukajtis  *
234*25c28e83SPiotr Jasiukajtis  *	Note. |s| <= 1.5384615385e-02 = 1/65. Maxium occurs at x = 1.03125
235*25c28e83SPiotr Jasiukajtis  *
236*25c28e83SPiotr Jasiukajtis  */
237*25c28e83SPiotr Jasiukajtis 
238*25c28e83SPiotr Jasiukajtis #define	P1 p[2]
239*25c28e83SPiotr Jasiukajtis #define	P4 p[8]
240*25c28e83SPiotr Jasiukajtis #define	P5 p[9]
241*25c28e83SPiotr Jasiukajtis #define	P6 p[10]
242*25c28e83SPiotr Jasiukajtis #define	P7 p[11]
243*25c28e83SPiotr Jasiukajtis #define	P8 p[12]
244*25c28e83SPiotr Jasiukajtis #define	P9 p[13]
245*25c28e83SPiotr Jasiukajtis static const double p[] = {
246*25c28e83SPiotr Jasiukajtis 	1.0,
247*25c28e83SPiotr Jasiukajtis 	0.0,
248*25c28e83SPiotr Jasiukajtis 	-3.33333333333333314830e-01,	/* p1   = BFD55555 55555555 */
249*25c28e83SPiotr Jasiukajtis 	-1.85030852238476921863e-17,	/* p1_l = BC755525 9783A49C */
250*25c28e83SPiotr Jasiukajtis 	2.00000000000000011102e-01,	/* p2   = 3FC99999 9999999A */
251*25c28e83SPiotr Jasiukajtis 	-1.27263196576150347368e-17,	/* p2_l = BC6D584B 0D874007 */
252*25c28e83SPiotr Jasiukajtis 	-1.42857142857141405923e-01,	/* p3   = BFC24924 9249245E */
253*25c28e83SPiotr Jasiukajtis 	-1.34258204847170493327e-17,	/* p3_l = BC6EF534 A112500D */
254*25c28e83SPiotr Jasiukajtis 	1.11111111110486909803e-01,	/* p4   = 3FBC71C7 1C71176A */
255*25c28e83SPiotr Jasiukajtis 	-9.09090907557387889470e-02,	/* p5   = BFB745D1 73B47A7D */
256*25c28e83SPiotr Jasiukajtis 	7.69230541541713053189e-02,	/* p6   = 3FB3B13A B1E68DE6 */
257*25c28e83SPiotr Jasiukajtis 	-6.66645815401964159097e-02,	/* p7   = BFB110EE 1584446A */
258*25c28e83SPiotr Jasiukajtis 	5.87081768778560317279e-02,	/* p8   = 3FAE0EFF 87657733 */
259*25c28e83SPiotr Jasiukajtis 	-4.90818147456113240690e-02,	/* p9   = BFA92140 6A524B5C */
260*25c28e83SPiotr Jasiukajtis };
261*25c28e83SPiotr Jasiukajtis #define	Q1 q[2]
262*25c28e83SPiotr Jasiukajtis #define	Q3 q[6]
263*25c28e83SPiotr Jasiukajtis #define	Q4 q[7]
264*25c28e83SPiotr Jasiukajtis #define	Q5 q[8]
265*25c28e83SPiotr Jasiukajtis static const double q[] = {
266*25c28e83SPiotr Jasiukajtis 	1.0,
267*25c28e83SPiotr Jasiukajtis 	0.0,
268*25c28e83SPiotr Jasiukajtis 	-3.33333333333333314830e-01,	/* q1   = BFD55555 55555555 */
269*25c28e83SPiotr Jasiukajtis 	-1.85022941571278638733e-17,	/* q1_l = BC7554E9 D20EFA66 */
270*25c28e83SPiotr Jasiukajtis 	1.99999999999999927836e-01,	/* q2   = 3FC99999 99999997 */
271*25c28e83SPiotr Jasiukajtis 	-1.28782564407438833398e-17,	/* q2_l = BC6DB1FB 17217417 */
272*25c28e83SPiotr Jasiukajtis 	-1.42857142855492280642e-01,	/* q3   = BFC24924 92483C46 */
273*25c28e83SPiotr Jasiukajtis 	1.11111097130183356096e-01,	/* q4   = 3FBC71C6 E06595CC */
274*25c28e83SPiotr Jasiukajtis 	-9.08553303569109294013e-02,	/* q5   = BFB7424B 808CDA76 */
275*25c28e83SPiotr Jasiukajtis };
276*25c28e83SPiotr Jasiukajtis static const double
277*25c28e83SPiotr Jasiukajtis one = 1.0,
278*25c28e83SPiotr Jasiukajtis pio2hi = 1.570796326794896558e+00,
279*25c28e83SPiotr Jasiukajtis pio2lo = 6.123233995736765886e-17;
280*25c28e83SPiotr Jasiukajtis 
281*25c28e83SPiotr Jasiukajtis static double
282*25c28e83SPiotr Jasiukajtis mx_atan(double x, double *err) {
283*25c28e83SPiotr Jasiukajtis 	double y, z, r, s, t, w, s_h, s_l, x_h, x_l, zz[3], ee[2], z_h,
284*25c28e83SPiotr Jasiukajtis 		z_l, r_h, r_l, u, v;
285*25c28e83SPiotr Jasiukajtis 	int ix, iy, sign, j;
286*25c28e83SPiotr Jasiukajtis 
287*25c28e83SPiotr Jasiukajtis 	ix = ((int *) &x)[HIWORD];
288*25c28e83SPiotr Jasiukajtis 	sign = ix & 0x80000000;
289*25c28e83SPiotr Jasiukajtis 	ix ^= sign;
290*25c28e83SPiotr Jasiukajtis 
291*25c28e83SPiotr Jasiukajtis 	/* for |x| < 1/8 */
292*25c28e83SPiotr Jasiukajtis 	if (ix < 0x3fc00000) {
293*25c28e83SPiotr Jasiukajtis 		if (ix < 0x3f300000) {	/* when |x| < 2**-12 */
294*25c28e83SPiotr Jasiukajtis 			if (ix < 0x3d800000) {	/* if |x| < 2**-39 */
295*25c28e83SPiotr Jasiukajtis 				*err = (double) ((int) x);
296*25c28e83SPiotr Jasiukajtis 				return (x);
297*25c28e83SPiotr Jasiukajtis 			}
298*25c28e83SPiotr Jasiukajtis 			z = x * x;
299*25c28e83SPiotr Jasiukajtis 			t = x * z * (q[2] + z * (q[4] + z * q[6]));
300*25c28e83SPiotr Jasiukajtis 			r = x + t;
301*25c28e83SPiotr Jasiukajtis 			*err = t - (r - x);
302*25c28e83SPiotr Jasiukajtis 			return (r);
303*25c28e83SPiotr Jasiukajtis 		}
304*25c28e83SPiotr Jasiukajtis 		z = x * x;
305*25c28e83SPiotr Jasiukajtis 
306*25c28e83SPiotr Jasiukajtis 		/* use double precision at p4 and on */
307*25c28e83SPiotr Jasiukajtis 		ee[0] = z *
308*25c28e83SPiotr Jasiukajtis 			(P4 + z *
309*25c28e83SPiotr Jasiukajtis 			(P5 + z * (P6 + z * (P7 + z * (P8 + z * P9)))));
310*25c28e83SPiotr Jasiukajtis 
311*25c28e83SPiotr Jasiukajtis 		x_h = (double) ((float) x);
312*25c28e83SPiotr Jasiukajtis 		z_h = (double) ((float) z);
313*25c28e83SPiotr Jasiukajtis 		x_l = x - x_h;
314*25c28e83SPiotr Jasiukajtis 		z_l = (x_h * x_h - z_h);
315*25c28e83SPiotr Jasiukajtis 		zz[0] = z;
316*25c28e83SPiotr Jasiukajtis 		zz[1] = z_h;
317*25c28e83SPiotr Jasiukajtis 		zz[2] = z_l + x_l * (x + x_h);
318*25c28e83SPiotr Jasiukajtis 
319*25c28e83SPiotr Jasiukajtis 		/*
320*25c28e83SPiotr Jasiukajtis 		 * compute (1+z*(p1+z*(p2+z*(p3+e)))) by call
321*25c28e83SPiotr Jasiukajtis 		 * mx_poly
322*25c28e83SPiotr Jasiukajtis 		 */
323*25c28e83SPiotr Jasiukajtis 
324*25c28e83SPiotr Jasiukajtis 		mx_poly(zz, p, ee, 3);
325*25c28e83SPiotr Jasiukajtis 
326*25c28e83SPiotr Jasiukajtis 		/* finally x*(1+z*(p1+...)) */
327*25c28e83SPiotr Jasiukajtis 		r = x_h * ee[0];
328*25c28e83SPiotr Jasiukajtis 		t = x * ee[1] + x_l * ee[0];
329*25c28e83SPiotr Jasiukajtis 		s = t + r;
330*25c28e83SPiotr Jasiukajtis 		*err = t - (s - r);
331*25c28e83SPiotr Jasiukajtis 		return (s);
332*25c28e83SPiotr Jasiukajtis 	}
333*25c28e83SPiotr Jasiukajtis 	/* for |x| >= 8.0 */
334*25c28e83SPiotr Jasiukajtis 	if (ix >= 0x40200000) {	/* x >=  8 */
335*25c28e83SPiotr Jasiukajtis 		x = fabs(x);
336*25c28e83SPiotr Jasiukajtis 		if (ix >= 0x42600000) {	/* x >=  2**39 */
337*25c28e83SPiotr Jasiukajtis 			if (ix >= 0x44c00000) {	/* x >=  2**77 */
338*25c28e83SPiotr Jasiukajtis 				y = -pio2lo;
339*25c28e83SPiotr Jasiukajtis 			} else
340*25c28e83SPiotr Jasiukajtis 				y = one / x - pio2lo;
341*25c28e83SPiotr Jasiukajtis 			if (sign == 0) {
342*25c28e83SPiotr Jasiukajtis 				t = pio2hi - y;
343*25c28e83SPiotr Jasiukajtis 				*err = -(y - (pio2hi - t));
344*25c28e83SPiotr Jasiukajtis 			} else {
345*25c28e83SPiotr Jasiukajtis 				t = y - pio2hi;
346*25c28e83SPiotr Jasiukajtis 				*err = y - (pio2hi + t);
347*25c28e83SPiotr Jasiukajtis 			}
348*25c28e83SPiotr Jasiukajtis 			return (t);
349*25c28e83SPiotr Jasiukajtis 		} else {
350*25c28e83SPiotr Jasiukajtis 			/* compute r = 1/x */
351*25c28e83SPiotr Jasiukajtis 			r = one / x;
352*25c28e83SPiotr Jasiukajtis 			z = r * r;
353*25c28e83SPiotr Jasiukajtis 			if (ix < 0x40504000) {	/* 8 <  x <  65 */
354*25c28e83SPiotr Jasiukajtis 
355*25c28e83SPiotr Jasiukajtis 				/* use double precision at p4 and on */
356*25c28e83SPiotr Jasiukajtis 				ee[0] = z *
357*25c28e83SPiotr Jasiukajtis 					(P4 + z *
358*25c28e83SPiotr Jasiukajtis 					(P5 + z *
359*25c28e83SPiotr Jasiukajtis 					(P6 + z * (P7 + z * (P8 + z * P9)))));
360*25c28e83SPiotr Jasiukajtis 				x_h = (double) ((float) x);
361*25c28e83SPiotr Jasiukajtis 				r_h = (double) ((float) r);
362*25c28e83SPiotr Jasiukajtis 				z_h = (double) ((float) z);
363*25c28e83SPiotr Jasiukajtis 				r_l = r * ((x_h - x) * r_h - (x_h * r_h - one));
364*25c28e83SPiotr Jasiukajtis 				z_l = (r_h * r_h - z_h);
365*25c28e83SPiotr Jasiukajtis 				zz[0] = z;
366*25c28e83SPiotr Jasiukajtis 				zz[1] = z_h;
367*25c28e83SPiotr Jasiukajtis 				zz[2] = z_l + r_l * (r + r_h);
368*25c28e83SPiotr Jasiukajtis 				/*
369*25c28e83SPiotr Jasiukajtis 				 * compute (1+z*(p1+z*(p2+z*(p3+e)))) by call
370*25c28e83SPiotr Jasiukajtis 				 * mx_poly
371*25c28e83SPiotr Jasiukajtis 				 */
372*25c28e83SPiotr Jasiukajtis 				mx_poly(zz, p, ee, 3);
373*25c28e83SPiotr Jasiukajtis 			} else { /* x < 65 < 2**39 */
374*25c28e83SPiotr Jasiukajtis 				/* use double precision at q3 and on */
375*25c28e83SPiotr Jasiukajtis 				ee[0] = z * (Q3 + z * (Q4 + z * Q5));
376*25c28e83SPiotr Jasiukajtis 				x_h = (double) ((float) x);
377*25c28e83SPiotr Jasiukajtis 				r_h = (double) ((float) r);
378*25c28e83SPiotr Jasiukajtis 				z_h = (double) ((float) z);
379*25c28e83SPiotr Jasiukajtis 				r_l = r * ((x_h - x) * r_h - (x_h * r_h - one));
380*25c28e83SPiotr Jasiukajtis 				z_l = (r_h * r_h - z_h);
381*25c28e83SPiotr Jasiukajtis 				zz[0] = z;
382*25c28e83SPiotr Jasiukajtis 				zz[1] = z_h;
383*25c28e83SPiotr Jasiukajtis 				zz[2] = z_l + r_l * (r + r_h);
384*25c28e83SPiotr Jasiukajtis 				/*
385*25c28e83SPiotr Jasiukajtis 				 * compute (1+z*(q1+z*(q2+e))) by call
386*25c28e83SPiotr Jasiukajtis 				 * mx_poly
387*25c28e83SPiotr Jasiukajtis 				 */
388*25c28e83SPiotr Jasiukajtis 				mx_poly(zz, q, ee, 2);
389*25c28e83SPiotr Jasiukajtis 			}
390*25c28e83SPiotr Jasiukajtis 			/* pio2 - r*(1+...) */
391*25c28e83SPiotr Jasiukajtis 			v = r_h * ee[0];
392*25c28e83SPiotr Jasiukajtis 			t = pio2lo - (r * ee[1] + r_l * ee[0]);
393*25c28e83SPiotr Jasiukajtis 			if (sign == 0) {
394*25c28e83SPiotr Jasiukajtis 				s = pio2hi - v;
395*25c28e83SPiotr Jasiukajtis 				t -= (v - (pio2hi - s));
396*25c28e83SPiotr Jasiukajtis 			} else {
397*25c28e83SPiotr Jasiukajtis 				s = v - pio2hi;
398*25c28e83SPiotr Jasiukajtis 				t = -(t - (v - (s + pio2hi)));
399*25c28e83SPiotr Jasiukajtis 			}
400*25c28e83SPiotr Jasiukajtis 			w = s + t;
401*25c28e83SPiotr Jasiukajtis 			*err = t - (w - s);
402*25c28e83SPiotr Jasiukajtis 			return (w);
403*25c28e83SPiotr Jasiukajtis 		}
404*25c28e83SPiotr Jasiukajtis 	}
405*25c28e83SPiotr Jasiukajtis 	/* now x is between 1/8 and 8 */
406*25c28e83SPiotr Jasiukajtis 	((int *) &x)[HIWORD] = ix;
407*25c28e83SPiotr Jasiukajtis 	iy = (ix + 0x00008000) & 0x7fff0000;
408*25c28e83SPiotr Jasiukajtis 	((int *) &y)[HIWORD] = iy;
409*25c28e83SPiotr Jasiukajtis 	((int *) &y)[LOWORD] = 0;
410*25c28e83SPiotr Jasiukajtis 	j = (iy - 0x3fc00000) >> 16;
411*25c28e83SPiotr Jasiukajtis 
412*25c28e83SPiotr Jasiukajtis 	w = (x - y);
413*25c28e83SPiotr Jasiukajtis 	v = 1 / (one + x * y);
414*25c28e83SPiotr Jasiukajtis 	s = w * v;
415*25c28e83SPiotr Jasiukajtis 	z = s * s;
416*25c28e83SPiotr Jasiukajtis 	/* use double precision at q3 and on */
417*25c28e83SPiotr Jasiukajtis 	ee[0] = z * (Q3 + z * (Q4 + z * Q5));
418*25c28e83SPiotr Jasiukajtis 	s_h = (double) ((float) s);
419*25c28e83SPiotr Jasiukajtis 	z_h = (double) ((float) z);
420*25c28e83SPiotr Jasiukajtis 	x_h = (double) ((float) x);
421*25c28e83SPiotr Jasiukajtis 	t = (double) ((float) (one + x * y));
422*25c28e83SPiotr Jasiukajtis 	r = -((x_h - x) * y - (x_h * y - (t - one)));
423*25c28e83SPiotr Jasiukajtis 	s_l = -v * (s_h * r - (w - s_h * t));
424*25c28e83SPiotr Jasiukajtis 	z_l = (s_h * s_h - z_h);
425*25c28e83SPiotr Jasiukajtis 	zz[0] = z;
426*25c28e83SPiotr Jasiukajtis 	zz[1] = z_h;
427*25c28e83SPiotr Jasiukajtis 	zz[2] = z_l + s_l * (s + s_h);
428*25c28e83SPiotr Jasiukajtis 	/* compute (1+z*(q1+z*(q2+e))) by call mx_poly */
429*25c28e83SPiotr Jasiukajtis 	mx_poly(zz, q, ee, 2);
430*25c28e83SPiotr Jasiukajtis 	v = s_h * ee[0];
431*25c28e83SPiotr Jasiukajtis 	t = TBL_atan_lo[j] + (s * ee[1] + s_l * ee[0]);
432*25c28e83SPiotr Jasiukajtis 	u = TBL_atan_hi[j];
433*25c28e83SPiotr Jasiukajtis 	s = u + v;
434*25c28e83SPiotr Jasiukajtis 	t += (v - (s - u));
435*25c28e83SPiotr Jasiukajtis 	w = s + t;
436*25c28e83SPiotr Jasiukajtis 	*err = t - (w - s);
437*25c28e83SPiotr Jasiukajtis 	if (sign != 0) {
438*25c28e83SPiotr Jasiukajtis 		w = -w;
439*25c28e83SPiotr Jasiukajtis 		*err = -*err;
440*25c28e83SPiotr Jasiukajtis 	}
441*25c28e83SPiotr Jasiukajtis 	return (w);
442*25c28e83SPiotr Jasiukajtis }
443*25c28e83SPiotr Jasiukajtis 
444*25c28e83SPiotr Jasiukajtis static const double
445*25c28e83SPiotr Jasiukajtis 	twom768 = 6.441148769597133308e-232,    /* 2^-768 */
446*25c28e83SPiotr Jasiukajtis 	two768  = 1.552518092300708935e+231,    /* 2^768 */
447*25c28e83SPiotr Jasiukajtis 	pi = 3.1415926535897931159979634685,
448*25c28e83SPiotr Jasiukajtis 	pi_lo = 1.224646799147353177e-16,
449*25c28e83SPiotr Jasiukajtis 	pio2 = 1.570796326794896558e+00,
450*25c28e83SPiotr Jasiukajtis 	pio2_lo = 6.123233995736765886e-17,
451*25c28e83SPiotr Jasiukajtis 	pio4 = 0.78539816339744827899949,
452*25c28e83SPiotr Jasiukajtis 	pio4_lo = 3.061616997868382943e-17,
453*25c28e83SPiotr Jasiukajtis 	pi3o4 = 2.356194490192344836998,
454*25c28e83SPiotr Jasiukajtis 	pi3o4_lo = 9.184850993605148829195e-17;
455*25c28e83SPiotr Jasiukajtis 
456*25c28e83SPiotr Jasiukajtis double
457*25c28e83SPiotr Jasiukajtis __k_atan2(double y, double x, double *w) {
458*25c28e83SPiotr Jasiukajtis 	double t, xh, th, t1, t2, w1, w2;
459*25c28e83SPiotr Jasiukajtis 	int ix, iy, hx, hy, lx, ly;
460*25c28e83SPiotr Jasiukajtis 
461*25c28e83SPiotr Jasiukajtis 	hy = ((int *) &y)[HIWORD];
462*25c28e83SPiotr Jasiukajtis 	ly = ((int *) &y)[LOWORD];
463*25c28e83SPiotr Jasiukajtis 	iy = hy & ~0x80000000;
464*25c28e83SPiotr Jasiukajtis 
465*25c28e83SPiotr Jasiukajtis 	hx = ((int *) &x)[HIWORD];
466*25c28e83SPiotr Jasiukajtis 	lx = ((int *) &x)[LOWORD];
467*25c28e83SPiotr Jasiukajtis 	ix = hx & ~0x80000000;
468*25c28e83SPiotr Jasiukajtis 
469*25c28e83SPiotr Jasiukajtis 	*w = 0.0;
470*25c28e83SPiotr Jasiukajtis 	if (ix >= 0x7ff00000 || iy >= 0x7ff00000) {	/* ignore inexact */
471*25c28e83SPiotr Jasiukajtis 		if (isnan(x) || isnan(y))
472*25c28e83SPiotr Jasiukajtis 			return (x * y);
473*25c28e83SPiotr Jasiukajtis 		else if (iy < 0x7ff00000) {
474*25c28e83SPiotr Jasiukajtis 			if (hx >= 0) {	/* ATAN2(+-finite, +inf) is +-0 */
475*25c28e83SPiotr Jasiukajtis 				*w *= y;
476*25c28e83SPiotr Jasiukajtis 				return (*w);
477*25c28e83SPiotr Jasiukajtis 			} else {	/* ATAN2(+-finite, -inf) is +-pi */
478*25c28e83SPiotr Jasiukajtis 				*w = copysign(pi_lo, y);
479*25c28e83SPiotr Jasiukajtis 				return (copysign(pi, y));
480*25c28e83SPiotr Jasiukajtis 			}
481*25c28e83SPiotr Jasiukajtis 		} else if (ix < 0x7ff00000) {
482*25c28e83SPiotr Jasiukajtis 					/* ATAN2(+-inf, finite) is +-pi/2 */
483*25c28e83SPiotr Jasiukajtis 			*w = (hy >= 0)? pio2_lo : -pio2_lo;
484*25c28e83SPiotr Jasiukajtis 			return ((hy >= 0)? pio2 : -pio2);
485*25c28e83SPiotr Jasiukajtis 		} else if (hx > 0) {	/* ATAN2(+-INF,+INF) = +-pi/4 */
486*25c28e83SPiotr Jasiukajtis 			*w = (hy >= 0)? pio4_lo : -pio4_lo;
487*25c28e83SPiotr Jasiukajtis 			return ((hy >= 0)? pio4 : -pio4);
488*25c28e83SPiotr Jasiukajtis 		} else {		/* ATAN2(+-INF,-INF) = +-3pi/4 */
489*25c28e83SPiotr Jasiukajtis 			*w = (hy >= 0)? pi3o4_lo : -pi3o4_lo;
490*25c28e83SPiotr Jasiukajtis 			return ((hy >= 0)? pi3o4 : -pi3o4);
491*25c28e83SPiotr Jasiukajtis 		}
492*25c28e83SPiotr Jasiukajtis 	} else if ((ix | lx) == 0 || (iy | ly) == 0) {
493*25c28e83SPiotr Jasiukajtis 		if ((iy | ly) == 0) {
494*25c28e83SPiotr Jasiukajtis 			if (hx >= 0) /* ATAN2(+-0, +(0 <= x <= inf)) is +-0 */
495*25c28e83SPiotr Jasiukajtis 				return (y);
496*25c28e83SPiotr Jasiukajtis 			else { 	/* ATAN2(+-0, -(0 <= x <= inf)) is +-pi */
497*25c28e83SPiotr Jasiukajtis 				*w = (hy >= 0)? pi_lo : -pi_lo;
498*25c28e83SPiotr Jasiukajtis 				return ((hy >= 0)? pi : -pi);
499*25c28e83SPiotr Jasiukajtis 			}
500*25c28e83SPiotr Jasiukajtis 		} else { /* ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2 */
501*25c28e83SPiotr Jasiukajtis 			*w = (hy >= 0)? pio2_lo : -pio2_lo;
502*25c28e83SPiotr Jasiukajtis 			return ((hy >= 0)? pio2 : -pio2);
503*25c28e83SPiotr Jasiukajtis 		}
504*25c28e83SPiotr Jasiukajtis 	} else if (iy - ix > 0x06400000) { /* |x/y| < 2 ** -100 */
505*25c28e83SPiotr Jasiukajtis 		*w = (hy >= 0)? pio2_lo : -pio2_lo;
506*25c28e83SPiotr Jasiukajtis 		return ((hy >= 0)? pio2 : -pio2);
507*25c28e83SPiotr Jasiukajtis 	} else if (ix - iy > 0x06400000) { /* |y/x| < 2 ** -100 */
508*25c28e83SPiotr Jasiukajtis 		if (hx < 0) {
509*25c28e83SPiotr Jasiukajtis 			*w = (hy >= 0)? pi_lo : -pi_lo;
510*25c28e83SPiotr Jasiukajtis 			return ((hy >= 0)? pi : -pi);
511*25c28e83SPiotr Jasiukajtis 		} else {
512*25c28e83SPiotr Jasiukajtis 			t = y / x;
513*25c28e83SPiotr Jasiukajtis 			th = t;
514*25c28e83SPiotr Jasiukajtis 			((int *) &th)[LOWORD] &= 0xf8000000;
515*25c28e83SPiotr Jasiukajtis 			xh = x;
516*25c28e83SPiotr Jasiukajtis 			((int *) &xh)[LOWORD] &= 0xf8000000;
517*25c28e83SPiotr Jasiukajtis 			t1 = (x - xh) * t + xh * (t - th);
518*25c28e83SPiotr Jasiukajtis 			t2 = y - xh * th;
519*25c28e83SPiotr Jasiukajtis 			*w = (t2 - t1) / x;
520*25c28e83SPiotr Jasiukajtis 			return (t);
521*25c28e83SPiotr Jasiukajtis 		}
522*25c28e83SPiotr Jasiukajtis 	} else {
523*25c28e83SPiotr Jasiukajtis 		if (ix >= 0x5f300000) {
524*25c28e83SPiotr Jasiukajtis 			x *= twom768;
525*25c28e83SPiotr Jasiukajtis 			y *= twom768;
526*25c28e83SPiotr Jasiukajtis 		} else if (ix < 0x23d00000) {
527*25c28e83SPiotr Jasiukajtis 			x *= two768;
528*25c28e83SPiotr Jasiukajtis 			y *= two768;
529*25c28e83SPiotr Jasiukajtis 		}
530*25c28e83SPiotr Jasiukajtis 		y = fabs(y);
531*25c28e83SPiotr Jasiukajtis 		x = fabs(x);
532*25c28e83SPiotr Jasiukajtis 		t = y / x;
533*25c28e83SPiotr Jasiukajtis 		th = t;
534*25c28e83SPiotr Jasiukajtis 		((int *) &th)[LOWORD] &= 0xf8000000;
535*25c28e83SPiotr Jasiukajtis 		xh = x;
536*25c28e83SPiotr Jasiukajtis 		((int *) &xh)[LOWORD] &= 0xf8000000;
537*25c28e83SPiotr Jasiukajtis 		t1 = (x - xh) * t + xh * (t - th);
538*25c28e83SPiotr Jasiukajtis 		t2 = y - xh * th;
539*25c28e83SPiotr Jasiukajtis 		w1 = mx_atan(t, &w2);
540*25c28e83SPiotr Jasiukajtis 		w2 += (t2 - t1) / (x + y * t);
541*25c28e83SPiotr Jasiukajtis 		if (hx < 0) {
542*25c28e83SPiotr Jasiukajtis 			t1 = pi - w1;
543*25c28e83SPiotr Jasiukajtis 			t2 = pi - t1;
544*25c28e83SPiotr Jasiukajtis 			w2 = (pi_lo - w2) - (w1 - t2);
545*25c28e83SPiotr Jasiukajtis 			w1 = t1;
546*25c28e83SPiotr Jasiukajtis 		}
547*25c28e83SPiotr Jasiukajtis 		*w = (hy >= 0)? w2 : -w2;
548*25c28e83SPiotr Jasiukajtis 		return ((hy >= 0)? w1 : -w1);
549*25c28e83SPiotr Jasiukajtis 	}
550*25c28e83SPiotr Jasiukajtis }
551