|
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_sin.cpp |
|
15 // Floating point sine and cosine functions |
|
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 |
|
26 #ifndef __USE_VFP_MATH |
|
27 |
|
28 LOCAL_D const TUint32 SinCoeffs[] = |
|
29 { |
|
30 0x2168C235,0xC90FDAA2,0x80000000, // polynomial approximation to sin(pi*x) |
|
31 0x2DF200BF,0xA55DE731,0x80010001, // for |x| <= 0.25 |
|
32 0xAC273AA1,0xA335E33B,0x80000000, |
|
33 0x5AB23F44,0x99696671,0x7FFE0001, |
|
34 0xD585EAFE,0xA83C17D9,0x7FFB0000, |
|
35 0xA30DE7AD,0xF1802BAC,0x7FF70001, |
|
36 0xF57FD821,0xF1F6A1C9,0x7FF30000 |
|
37 }; |
|
38 |
|
39 LOCAL_D const TUint32 CosCoeffs[] = |
|
40 { |
|
41 0x00000000,0x80000000,0x7FFF0000, // polynomial approximation to cos(pi*x) |
|
42 0xF22EF286,0x9DE9E64D,0x80010001, // for |x| <= 0.25 |
|
43 0xDAD59F90,0x81E0F840,0x80010000, |
|
44 0xE4E45144,0xAAE9E3F1,0x7FFF0001, |
|
45 0x3232D733,0xF0FA8342,0x7FFC0000, |
|
46 0x03E16BB8,0xD368F6A3,0x7FF90001, |
|
47 0x712FD084,0xFCE66DE2,0x7FF50000, |
|
48 0x9E5353EE,0xD94951B0,0x7FF10001 |
|
49 }; |
|
50 |
|
51 LOCAL_D const TUint32 PiInvdata[] = {0x4E44152A,0xA2F9836E,0x7FFD0000}; // 1/pi |
|
52 LOCAL_D const TUint32 Halfdata[] = {0x00000000,0x80000000,0x7FFE0000}; // 0.5 |
|
53 LOCAL_D const TUint32 Onedata[] = {0x00000000,0x80000000,0x7FFF0000}; // 1.0 |
|
54 |
|
55 LOCAL_C TInt CalcSinCos(TReal& aTrg, TRealX& aSrc, TBool aCos) |
|
56 { |
|
57 // Calculate sin(aSrc) if aCos=false or cos(aSrc) if aCos=true |
|
58 // and write result to aTrg. |
|
59 // Algorithm: |
|
60 // Divide aSrc by pi and throw away integer part, but change sign |
|
61 // of result if integer part odd. Replace aSrc with remainder. |
|
62 // ( use identities sin(x+n*pi)=(-1)^n*sin(x) |
|
63 // cos(x+n*pi)=(-1)^n*cos(x) ) |
|
64 // If aSrc>=0.5 replace aSrc with 1-aSrc, and change sign of result |
|
65 // if cos required. |
|
66 // ( use identities sin(pi-x)=sin(x), cos(pi-x)=-cos(x) ) |
|
67 // If aSrc>=0.25 replace aSrc with 0.5-aSrc and swap sin and cos |
|
68 // ( use identities sin(pi/2-x)=cos(x), cos(pi/2-x)=sin(x) ) |
|
69 // Use polynomial approximation to evaluate sin(pi*x) or cos(pi*x) |
|
70 // for |x|<=0.25 |
|
71 |
|
72 const TRealX& One = *(const TRealX*)Onedata; |
|
73 const TRealX& Half = *(const TRealX*)Halfdata; |
|
74 const TRealX& PiInv = *(const TRealX*)PiInvdata; |
|
75 |
|
76 TRealX y; |
|
77 aSrc*=PiInv; |
|
78 TInt n=(TInt)aSrc; |
|
79 if (n<KMaxTInt && n>KMinTInt) |
|
80 { |
|
81 aSrc-=TRealX(n); |
|
82 TInt sign=0; |
|
83 if (!aCos) |
|
84 sign=aSrc.iSign & 1; |
|
85 sign^=n; |
|
86 aSrc.iSign=0; |
|
87 if (aSrc.iExp>=0x7FFE) // if remainder>=pi/2 |
|
88 { |
|
89 aSrc=One-aSrc; |
|
90 if (aCos) |
|
91 sign^=1; |
|
92 } |
|
93 if (aSrc.iExp>=0x7FFD) // if remainder>=pi/4 |
|
94 { |
|
95 aSrc=Half-aSrc; // take complementary angle |
|
96 aCos=!aCos; // and swap sin and cos |
|
97 } |
|
98 if (aCos) |
|
99 Math::PolyX(y,aSrc*aSrc,7,(const TRealX*)CosCoeffs); |
|
100 else |
|
101 { |
|
102 Math::PolyX(y,aSrc*aSrc,6,(const TRealX*)SinCoeffs); |
|
103 y*=aSrc; |
|
104 } |
|
105 if (sign & 1) |
|
106 y=-y; |
|
107 return y.GetTReal(aTrg); |
|
108 } |
|
109 return KErrArgument; |
|
110 } |
|
111 |
|
112 |
|
113 |
|
114 |
|
115 EXPORT_C TInt Math::Sin(TReal& aTrg, const TReal& aSrc) |
|
116 /** |
|
117 Calculates the sine of a number. |
|
118 |
|
119 @param aTrg A reference containing the result. |
|
120 @param aSrc The argument of the sin function in radians. |
|
121 |
|
122 @return KErrNone if successful, otherwise another of |
|
123 the system-wide error codes. |
|
124 */ |
|
125 { |
|
126 TRealX x; |
|
127 TInt r=x.Set(aSrc); |
|
128 if (r==KErrNone) |
|
129 r=CalcSinCos(aTrg,x,EFalse); |
|
130 if (r==KErrNone) |
|
131 return r; |
|
132 SetNaN(aTrg); |
|
133 return KErrArgument; |
|
134 } |
|
135 |
|
136 |
|
137 |
|
138 |
|
139 EXPORT_C TInt Math::Cos(TReal& aTrg, const TReal& aSrc) |
|
140 /** |
|
141 Calculates the cosine of a number. |
|
142 |
|
143 @param aTrg A reference containing the result. |
|
144 @param aSrc The argument of the cos function in radians |
|
145 |
|
146 @return KErrNone if successful, otherwise another of |
|
147 the system-wide error codes. |
|
148 */ |
|
149 { |
|
150 TRealX x; |
|
151 TInt r=x.Set(aSrc); |
|
152 if (r==KErrNone) |
|
153 r=CalcSinCos(aTrg,x,ETrue); |
|
154 if (r==KErrNone) |
|
155 return r; |
|
156 SetNaN(aTrg); |
|
157 return KErrArgument; |
|
158 } |
|
159 |
|
160 #else // __USE_VFP_MATH |
|
161 |
|
162 // definitions come from RVCT math library |
|
163 extern "C" TReal sin(TReal); |
|
164 extern "C" TReal cos(TReal); |
|
165 |
|
166 EXPORT_C TInt Math::Sin(TReal& aTrg, const TReal& aSrc) |
|
167 { |
|
168 if (aSrc<KMaxTInt && aSrc>KMinTInt) |
|
169 { |
|
170 aTrg = sin(aSrc); |
|
171 if (Math::IsFinite(aTrg)) |
|
172 return KErrNone; |
|
173 } |
|
174 SetNaN(aTrg); |
|
175 return KErrArgument; |
|
176 } |
|
177 |
|
178 EXPORT_C TInt Math::Cos(TReal& aTrg, const TReal& aSrc) |
|
179 { |
|
180 if (aSrc<KMaxTInt && aSrc>KMinTInt) |
|
181 { |
|
182 aTrg = cos(aSrc); |
|
183 if (Math::IsFinite(aTrg)) |
|
184 return KErrNone; |
|
185 } |
|
186 SetNaN(aTrg); |
|
187 return KErrArgument; |
|
188 } |
|
189 |
|
190 #endif |