|
1 // Copyright (c) 2010-2010 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\nkern\nklib.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 #include <e32atomics.h> |
|
19 #include <nklib.h> |
|
20 |
|
21 #ifndef __SRATIO_MACHINE_CODED__ |
|
22 void SRatio::Set(TUint32 aInt, TInt aDivisorExp) |
|
23 { |
|
24 iSpare1 = 0; |
|
25 iSpare2 = 0; |
|
26 iM = aInt; |
|
27 if (iM) |
|
28 { |
|
29 TInt ms1 = __e32_find_ms1_32(iM); |
|
30 TInt shift = 31 - ms1; |
|
31 iM <<= shift; |
|
32 iX = (TInt16)(-shift - aDivisorExp); |
|
33 } |
|
34 else |
|
35 iX = 0; |
|
36 } |
|
37 |
|
38 TInt SRatio::Reciprocal() |
|
39 { |
|
40 if (iM==0) |
|
41 return KErrDivideByZero; |
|
42 // Calculate 2^32/iM |
|
43 TInt exp=0; |
|
44 if (iM == 0x80000000u) |
|
45 { |
|
46 // ratio = 2^(31+iX) so reciprocal = 2^(-31-iX) = 2^(31 + (-62-iX)) |
|
47 exp = -62-iX; |
|
48 } |
|
49 else |
|
50 { |
|
51 // 2^32/iM = 1.xxx |
|
52 TUint64 r64 = MAKE_TUINT64(0u-iM,0); |
|
53 TUint32 q32 = (TUint32)(r64/TUint64(iM)); // next 32 bits of result |
|
54 iM = 0x80000000u | (q32>>1); |
|
55 exp = -63-iX; |
|
56 if (q32 & 1) |
|
57 { |
|
58 if (++iM==0) |
|
59 iM=0x80000000u, ++exp; |
|
60 } |
|
61 } |
|
62 if (exp < -32768) |
|
63 { |
|
64 iM = 0; |
|
65 iX = 0; |
|
66 return KErrUnderflow; |
|
67 } |
|
68 if (exp > 32767) |
|
69 { |
|
70 iM = 0xffffffffu; |
|
71 iX = 32767; |
|
72 return KErrOverflow; |
|
73 } |
|
74 iX = (TInt16)exp; |
|
75 return KErrNone; |
|
76 } |
|
77 |
|
78 TInt SRatio::Mult(TUint32& aInt32) |
|
79 { |
|
80 TUint64 x = aInt32; |
|
81 x *= TUint64(iM); |
|
82 if (x==0) |
|
83 { |
|
84 aInt32 = 0; |
|
85 return KErrNone; |
|
86 } |
|
87 TInt ms1 = __e32_find_ms1_64(x); |
|
88 TInt ms1b = ms1 + iX; |
|
89 if (ms1b>=32) |
|
90 { |
|
91 aInt32 = ~0u; |
|
92 return KErrOverflow; |
|
93 } |
|
94 if (ms1b<-1) |
|
95 { |
|
96 aInt32 = 0; |
|
97 return KErrUnderflow; |
|
98 } |
|
99 TInt shift = ms1b - ms1 + 31; |
|
100 if (shift > 0) |
|
101 x <<= shift; |
|
102 else if (shift < 0) |
|
103 x >>= (-shift); |
|
104 x += MAKE_TUINT64(0,0x40000000u); |
|
105 if (x >> 63) |
|
106 { |
|
107 aInt32 = ~0u; |
|
108 return KErrOverflow; |
|
109 } |
|
110 aInt32 = (TUint32)(x>>31); |
|
111 return aInt32 ? KErrNone : KErrUnderflow; |
|
112 } |
|
113 |
|
114 //TInt SRatio::Mult(TUint64& aInt64) |
|
115 // { |
|
116 // } |
|
117 #endif |
|
118 |
|
119 void SRatioInv::Set(const SRatio* a) |
|
120 { |
|
121 if (a) |
|
122 { |
|
123 iR = *a; |
|
124 iI = iR; |
|
125 iI.Reciprocal(); |
|
126 } |
|
127 else |
|
128 { |
|
129 iR.Set(1); |
|
130 iI.Set(1); |
|
131 } |
|
132 } |
|
133 |
|
134 |
|
135 |