|
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". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // e32\euser\maths\um_asin.cpp |
|
15 // Arc sin. |
|
16 // |
|
17 // |
|
18 |
|
19 #include "um_std.h" |
|
20 |
|
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 |
|
23 #endif |
|
24 |
|
25 #ifndef __USE_VFP_MATH |
|
26 |
|
27 LOCAL_D const TUint32 ArcsinCoeffs[] = |
|
28 { |
|
29 0x00000000,0x80000000,0x7FFF0000, // polynomial approximation to arcsin(x) |
|
30 0xAA893CD8,0xAAAAAAAA,0x7FFC0000, // for -0.5<=x<=0.5 |
|
31 0xD07ED410,0x99999999,0x7FFB0000, |
|
32 0xB6C64A72,0xB6DB6D94,0x7FFA0000, |
|
33 0xF5527DD4,0xF8E3995C,0x7FF90000, |
|
34 0xA87499FB,0xB744B969,0x7FF90000, |
|
35 0x2E8953AD,0x8E392B24,0x7FF90000, |
|
36 0xFEDBB4E4,0xE3481C4A,0x7FF80000, |
|
37 0x4A32ED70,0xC89998E1,0x7FF80000, |
|
38 0x848A2B53,0xCCAE4AE5,0x7FF70000, |
|
39 0x09C1F387,0xA587A043,0x7FF90000, |
|
40 0x722B9041,0x8C9BD20B,0x7FF90001, |
|
41 0xC88B75CC,0x850CE779,0x7FFA0000 |
|
42 }; |
|
43 |
|
44 LOCAL_D const TUint32 Onedata[] = {0x00000000,0x80000000,0x7FFF0000}; // 1.0 |
|
45 LOCAL_D const TUint32 Halfdata[] = {0x00000000,0x80000000,0x7FFE0000}; // 0.5 |
|
46 LOCAL_D const TUint32 Pidata[] = {0x2168C235,0xC90FDAA2,0x80000000}; // pi |
|
47 LOCAL_D const TUint32 PiBy2data[] = {0x2168C235,0xC90FDAA2,0x7FFF0000}; // pi/2 |
|
48 |
|
49 LOCAL_C TInt CalcArcsinArccos(TReal& aTrg, TRealX& x, TBool aCos) |
|
50 { |
|
51 // Calculate arcsin (if aCos false) or arccos (if aCos true) of x |
|
52 // and write result to aTrg. |
|
53 // Algorithm (arcsin): |
|
54 // If x>0.5, replace x with Sqrt((1-x)/2) |
|
55 // ( use identity cos(x)=2(cos(x/2))^2-1 ) |
|
56 // Use polynomial approximation for arcsin(x), 0<=x<=0.5 |
|
57 // If original x>0.5, replace result y with pi/2-2y |
|
58 |
|
59 const TRealX One = *(const TRealX*)Onedata; |
|
60 const TRealX Half = *(const TRealX*)Halfdata; |
|
61 const TRealX Pi = *(const TRealX*)Pidata; |
|
62 const TRealX PiBy2 = *(const TRealX*)PiBy2data; |
|
63 |
|
64 TInt sign=x.iSign&1; |
|
65 x.iSign=0; |
|
66 if (x<=One) |
|
67 { |
|
68 TBool big=(x>Half); |
|
69 if (big) |
|
70 { |
|
71 x=One-x; |
|
72 if (x.iExp>1) |
|
73 x.iExp--; |
|
74 TReal temp; |
|
75 Math::Sqrt(temp, (TReal)x); |
|
76 x=temp; |
|
77 } |
|
78 TRealX y; |
|
79 Math::PolyX(y,x*x,12,(const TRealX*)ArcsinCoeffs); |
|
80 y*=x; |
|
81 if (big) |
|
82 { |
|
83 if (y.iExp) |
|
84 y.iExp++; |
|
85 if (aCos) |
|
86 { |
|
87 if (sign) |
|
88 y=Pi-y; |
|
89 } |
|
90 else |
|
91 { |
|
92 y=PiBy2-y; |
|
93 y.iSign=TInt8(sign); |
|
94 } |
|
95 } |
|
96 else |
|
97 { |
|
98 y.iSign=TInt8(sign); |
|
99 if (aCos) |
|
100 y=PiBy2-y; |
|
101 } |
|
102 return y.GetTReal(aTrg); |
|
103 } |
|
104 return KErrArgument; |
|
105 } |
|
106 |
|
107 |
|
108 |
|
109 |
|
110 EXPORT_C TInt Math::ASin(TReal& aTrg, const TReal& aSrc) |
|
111 /** |
|
112 Calculates the principal value of the inverse sine of a number. |
|
113 |
|
114 @param aTrg A reference containing the result in radians, |
|
115 a value between -pi/2 and +pi/2. |
|
116 @param aSrc The argument of the arcsin function, a value |
|
117 between -1 and +1 inclusive. |
|
118 |
|
119 @return KErrNone if successful, otherwise another of the system-wide |
|
120 error codes. |
|
121 */ |
|
122 { |
|
123 TRealX x; |
|
124 TInt r=x.Set(aSrc); |
|
125 if (r==KErrNone) |
|
126 r=CalcArcsinArccos(aTrg,x,EFalse); |
|
127 if (r==KErrNone) |
|
128 return r; |
|
129 SetNaN(aTrg); |
|
130 return KErrArgument; |
|
131 } |
|
132 |
|
133 |
|
134 |
|
135 |
|
136 EXPORT_C TInt Math::ACos(TReal& aTrg, const TReal& aSrc) |
|
137 /** |
|
138 Calculates the principal value of the inverse cosine of a number. |
|
139 |
|
140 @param aTrg A reference containing the result in radians, |
|
141 a value between 0 and pi. |
|
142 @param aSrc The argument of the arccos function, a value |
|
143 between -1 and +1 inclusive. |
|
144 |
|
145 @return KErrNone if successful, otherwise another of the system-wide |
|
146 error codes. |
|
147 */ |
|
148 { |
|
149 TRealX x; |
|
150 TInt r=x.Set(aSrc); |
|
151 if (r==KErrNone) |
|
152 r=CalcArcsinArccos(aTrg,x,ETrue); |
|
153 if (r==KErrNone) |
|
154 return r; |
|
155 SetNaN(aTrg); |
|
156 return KErrArgument; |
|
157 } |
|
158 |
|
159 #else // __USE_VFP_MATH |
|
160 |
|
161 // definitions come from RVCT math library |
|
162 extern "C" TReal asin(TReal); |
|
163 extern "C" TReal acos(TReal); |
|
164 |
|
165 EXPORT_C TInt Math::ASin(TReal& aTrg, const TReal& aSrc) |
|
166 { |
|
167 aTrg = asin(aSrc); |
|
168 if (Math::IsFinite(aTrg)) |
|
169 return KErrNone; |
|
170 SetNaN(aTrg); |
|
171 return KErrArgument; |
|
172 } |
|
173 |
|
174 EXPORT_C TInt Math::ACos(TReal& aTrg, const TReal& aSrc) |
|
175 { |
|
176 aTrg = acos(aSrc); |
|
177 if (Math::IsFinite(aTrg)) |
|
178 return KErrNone; |
|
179 SetNaN(aTrg); |
|
180 return KErrArgument; |
|
181 } |
|
182 |
|
183 #endif |