Update contrib.
1 // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32\euser\maths\um_atan.cpp
15 // Floating point arc tangent
21 #if defined(__USE_VFP_MATH) && !defined(__CPU_HAS_VFP)
22 #error __USE_VFP_MATH was defined but not __CPU_HAS_VFP - impossible combination, check variant.mmh
25 #ifndef __USE_VFP_MATH
27 LOCAL_D const TUint32 ArctanCoeffs[] =
29 0x00000000,0x80000000,0x7FFF0000, // polynomial approximation to arctan(x)
30 0xAA84D6EE,0xAAAAAAAA,0x7FFD0001, // for -(sqr2-1) <= x <= (sqr2-1)
31 0x89C77453,0xCCCCCCCC,0x7FFC0000,
32 0xEBC0261C,0x9249247B,0x7FFC0001,
33 0x940BC4DB,0xE38E3121,0x7FFB0000,
34 0x141C32F1,0xBA2DBF36,0x7FFB0001,
35 0xA90615E7,0x9D7C807E,0x7FFB0000,
36 0x1C632E93,0x87F6A873,0x7FFB0001,
37 0x310FCFFD,0xE8BE5D0A,0x7FFA0000,
38 0x92289F15,0xB17B930B,0x7FFA0001,
39 0x546FE7CE,0xABDE562D,0x7FF90000
42 LOCAL_D const TUint32 Sqr2m1data[] = {0xE7799211,0xD413CCCF,0x7FFD0000}; // sqr2-1
43 LOCAL_D const TUint32 Sqr2p1data[] = {0xFCEF3242,0x9A827999,0x80000000}; // sqr2+1
44 LOCAL_D const TUint32 Onedata[] = {0x00000000,0x80000000,0x7FFF0000}; // 1.0
45 LOCAL_D const TUint32 PiBy8data[] = {0x2168C235,0xC90FDAA2,0x7FFD0000}; // pi/8
46 LOCAL_D const TUint32 PiBy2data[] = {0x2168C235,0xC90FDAA2,0x7FFF0000}; // pi/2
47 LOCAL_D const TUint32 ThreePiBy8data[] = {0x990E91A8,0x96CBE3F9,0x7FFF0000}; // 3*pi/8
49 LOCAL_C void Arctan(TRealX& y, TRealX& x)
51 // Calculate arctan(x), write result to y
53 // If x>1, replace x with 1/x and subtract result from pi/2
54 // ( use identity tan(pi/2-x)=1/tan(x) )
55 // If x>sqr(2)-1, replace x with (x-(sqr(2)-1))/(1-(sqr2-1)x)
56 // ( use identity tan(x-a)=(tanx-tana)/(1-tana.tanx)
57 // where a=pi/8, tan a = sqr2-1
58 // and add pi/8 to result
59 // Use polynomial approximation to calculate arctan(x) for
60 // x in the interval [0,sqr2-1]
62 const TRealX& Sqr2m1 = *(const TRealX*)Sqr2m1data;
63 const TRealX& Sqr2p1 = *(const TRealX*)Sqr2p1data;
64 const TRealX& One = *(const TRealX*)Onedata;
65 const TRealX& PiBy8 = *(const TRealX*)PiBy8data;
66 const TRealX& PiBy2 = *(const TRealX*)PiBy2data;
67 const TRealX& ThreePiBy8 = *(const TRealX*)ThreePiBy8data;
79 x=(One-Sqr2m1*x)/(x+Sqr2m1);
84 x=(x-Sqr2m1)/(One+Sqr2m1*x);
87 Math::PolyX(y,x*x,10,(const TRealX*)ArctanCoeffs);
101 EXPORT_C TInt Math::ATan(TReal& aTrg, const TReal& aSrc)
103 Calculates the principal value of the inverse tangent of a number.
105 @param aTrg A reference containing the result in radians,
106 a value between -pi/2 and +pi/2.
107 @param aSrc The argument of the arctan function,
108 a value between +infinity and +infinity.
110 @return KErrNone if successful, otherwise another of
111 the system-wide error codes.
120 return y.GetTReal(aTrg);
127 aTrg=KPiBy2; // arctan(+/- infinity) = +/- pi/2
133 LOCAL_D const TUint32 Pidata[] = {0x2168C235,0xC90FDAA2,0x80000000};
134 LOCAL_D const TUint32 PiBy4data[] = {0x2168C235,0xC90FDAA2,0x7FFE0000};
135 LOCAL_D const TUint32 MinusPiBy4data[] = {0x2168C235,0xC90FDAA2,0x7FFE0001};
136 LOCAL_D const TUint32 ThreePiBy4data[] = {0x990E91A8,0x96CBE3F9,0x80000000};
137 LOCAL_D const TUint32 MinusThreePiBy4data[] = {0x990E91A8,0x96CBE3F9,0x80000001};
138 LOCAL_D const TUint32 Zerodata[] = {0x00000000,0x00000000,0x00000000};
143 EXPORT_C TInt Math::ATan(TReal &aTrg,const TReal &aY,const TReal &aX)
145 Calculates the angle between the x-axis and a line drawn from the origin
146 to a point represented by its (x,y) co-ordinates.
148 The co-ordinates are passed as arguments to the function.
149 This function returns the same result as arctan(y/x), but:
151 1. it adds +/-pi to the result, if x is negative
153 2. it sets the result to +/-pi/2, if x is zero but y is non-zero.
155 @param aTrg A reference containing the result in radians,
156 a value between -pi exclusive and +pi inclusive.
157 @param aY The y argument of the arctan(y/x) function.
158 @param aX The x argument of the arctan(y/x) function.
160 @return KErrNone if successful, otherwise another of
161 the system-wide error codes.
164 const TRealX& Zero=*(const TRealX*)Zerodata;
165 const TRealX& Pi=*(const TRealX*)Pidata;
166 const TRealX& PiBy4=*(const TRealX*)PiBy4data;
167 const TRealX& MinusPiBy4=*(const TRealX*)MinusPiBy4data;
168 const TRealX& ThreePiBy4=*(const TRealX*)ThreePiBy4data;
169 const TRealX& MinusThreePiBy4=*(const TRealX*)MinusThreePiBy4data;
174 if (rx!=KErrArgument && ry!=KErrArgument)
180 if (rq!=KErrArgument)
196 // Both x and y must be infinite
197 TInt quadrant=((y.iSign & 1)<<1) + (x.iSign&1);
201 else if (quadrant==1)
203 else if (quadrant==3)
215 #else // __USE_VFP_MATH
217 LOCAL_D const TUint32 PiBy4data[] = {0x54442D18,0x3FE921FB};
218 LOCAL_D const TUint32 MinusPiBy4data[] = {0x54442D18,0xBFE921FB};
219 LOCAL_D const TUint32 ThreePiBy4data[] = {0x7F3321D2,0x4002D97C};
220 LOCAL_D const TUint32 MinusThreePiBy4data[] = {0x7F3321D2,0xC002D97C};
222 // definitions come from RVCT math library
223 extern "C" TReal atan(TReal);
224 extern "C" TReal atan2(TReal,TReal);
226 EXPORT_C TInt Math::ATan(TReal& aTrg, const TReal& aSrc)
229 if (Math::IsFinite(aTrg))
235 EXPORT_C TInt Math::ATan(TReal &aTrg,const TReal &aY,const TReal &aX)
238 if (Math::IsFinite(aTrg))
241 // Return is a NaN, but ARM implementation returns NaN for atan(inf/inf)
242 // whereas implementation above returns multiples of pi/4 - fix up here
243 SReal64 *pY=(SReal64 *)&aY;
244 SReal64 *pX=(SReal64 *)&aX;
246 if ( pY->msm==0 && pY->lsm==0 && pY->exp==KTReal64SpecialExponent
247 && pX->msm==0 && pX->lsm==0 && pX->exp==KTReal64SpecialExponent)
249 TInt quadrant=((pY->sign)<<1) + (pX->sign);
251 aTrg=*(const TReal*)PiBy4data;
252 else if (quadrant==1)
253 aTrg=*(const TReal*)ThreePiBy4data;
254 else if (quadrant==3)
255 aTrg=*(const TReal*)MinusThreePiBy4data;
257 aTrg=*(const TReal*)MinusPiBy4data;
261 // If we get here then the args weren't inf/inf so one of them must've
262 // been a NaN to start with