|
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 "Symbian Foundation License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // e32\euser\maths\um_exp.cpp |
|
15 // Floating point exponentiation |
|
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 ExpCoeffs[] = |
|
28 { |
|
29 0x00000000,0x80000000,0x7FFF0000, // polynomial approximation to 2^(x/8) |
|
30 0xD1CF79AC,0xB17217F7,0x7FFB0000, // for 0<=x<=1 |
|
31 0x1591EF2B,0xF5FDEFFC,0x7FF60000, |
|
32 0x23B940A9,0xE35846B9,0x7FF10000, |
|
33 0xDD73C23F,0x9D955ADE,0x7FEC0000, |
|
34 0x8728EBE7,0xAEC4616C,0x7FE60000, |
|
35 0xAF177130,0xA1646F7D,0x7FE00000, |
|
36 0xC44EAC22,0x8542C46E,0x7FDA0000 |
|
37 }; |
|
38 |
|
39 LOCAL_D const TUint32 TwoToNover8[] = |
|
40 { |
|
41 0xEA8BD6E7,0x8B95C1E3,0x7FFF0000, // 2^0.125 |
|
42 0x8DB8A96F,0x9837F051,0x7FFF0000, // 2^0.250 |
|
43 0xB15138EA,0xA5FED6A9,0x7FFF0000, // 2^0.375 |
|
44 0xF9DE6484,0xB504F333,0x7FFF0000, // 2^0.500 |
|
45 0x5506DADD,0xC5672A11,0x7FFF0000, // 2^0.625 |
|
46 0xD69D6AF4,0xD744FCCA,0x7FFF0000, // 2^0.750 |
|
47 0xDD24392F,0xEAC0C6E7,0x7FFF0000 // 2^0.875 |
|
48 }; |
|
49 |
|
50 LOCAL_D const TUint32 EightLog2edata[] = {0x5C17F0BC,0xB8AA3B29,0x80020000}; // 8/ln2 |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 EXPORT_C TInt Math::Exp(TReal& aTrg, const TReal& aSrc) |
|
56 /** |
|
57 Calculates the value of e to the power of x. |
|
58 |
|
59 @param aTrg A reference containing the result. |
|
60 @param aSrc The power to which e is to be raised. |
|
61 |
|
62 @return KErrNone if successful, otherwise another of |
|
63 the system-wide error codes. |
|
64 */ |
|
65 { |
|
66 // Calculate exp(aSrc) and write result to aTrg |
|
67 // Algorithm: |
|
68 // Let x=aSrc/ln2 and calculate 2^x |
|
69 // 2^x = 2^int(x).2^frac(x) |
|
70 // 2^int(x) just adds int(x) to the final result exponent |
|
71 // Reduce frac(x) to the range [0,0.125] (modulo 0.125) |
|
72 // Use polynomial to calculate 2^x for 0<=x<=0.125 |
|
73 // Multiply by 2^(n/8) for n=0,1,2,3,4,5,6,7 to give 2^frac(x) |
|
74 |
|
75 const TRealX& EightLog2e=*(const TRealX*)EightLog2edata; |
|
76 |
|
77 TRealX x; |
|
78 TRealX y; |
|
79 TInt r=x.Set(aSrc); |
|
80 if (r==KErrNone) |
|
81 { |
|
82 x*=EightLog2e; |
|
83 TInt n=(TInt)x; |
|
84 if (n<16384 && n>-16384) |
|
85 { |
|
86 if (x.iSign&1) |
|
87 n--; |
|
88 x-=TRealX(n); |
|
89 PolyX(y,x,7,(const TRealX*)ExpCoeffs); |
|
90 y.iExp=TUint16(TInt(y.iExp)+(n>>3)); |
|
91 n&=7; |
|
92 if (n) |
|
93 y*= (*(const TRealX*)(TwoToNover8+3*n-3)); |
|
94 return y.GetTReal(aTrg); |
|
95 } |
|
96 else |
|
97 { |
|
98 if (n<0) |
|
99 { |
|
100 SetZero(aTrg); |
|
101 r=KErrUnderflow; |
|
102 } |
|
103 else |
|
104 { |
|
105 SetInfinite(aTrg,0); |
|
106 r=KErrOverflow; |
|
107 } |
|
108 return r; |
|
109 } |
|
110 } |
|
111 else |
|
112 { |
|
113 if (r==KErrArgument) |
|
114 SetNaN(aTrg); |
|
115 if (r==KErrOverflow) |
|
116 { |
|
117 if (x.iSign&1) |
|
118 { |
|
119 SetZero(aTrg); |
|
120 r=KErrUnderflow; |
|
121 } |
|
122 else |
|
123 { |
|
124 SetInfinite(aTrg,0); |
|
125 } |
|
126 } |
|
127 return r; |
|
128 } |
|
129 } |
|
130 |
|
131 #else // __USE_VFP_MATH |
|
132 |
|
133 // definitions come from RVCT math library |
|
134 extern "C" TReal exp(TReal); |
|
135 |
|
136 EXPORT_C TInt Math::Exp(TReal& aTrg, const TReal& aSrc) |
|
137 { |
|
138 aTrg = exp(aSrc); |
|
139 if (Math::IsZero(aTrg)) |
|
140 return KErrUnderflow; |
|
141 if (Math::IsFinite(aTrg)) |
|
142 return KErrNone; |
|
143 if (Math::IsInfinite(aTrg)) |
|
144 return KErrOverflow; |
|
145 SetNaN(aTrg); |
|
146 return KErrArgument; |
|
147 } |
|
148 |
|
149 #endif |