|
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 // e32test\math\largeint.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 #include "largeint.h" |
|
19 |
|
20 TLargeIntBase::TLargeIntBase(TInt n) |
|
21 : iC(n) |
|
22 { |
|
23 Mem::FillZ(iX,n*sizeof(TUint32)); |
|
24 } |
|
25 |
|
26 TLargeIntBase::TLargeIntBase(TInt n, TInt32 aSigned32) |
|
27 : iC(n) |
|
28 { |
|
29 TUint f = (aSigned32<0) ? 0xff : 0; |
|
30 Mem::Fill(iX,n*sizeof(TUint32),f); |
|
31 iX[0]=aSigned32; |
|
32 } |
|
33 |
|
34 TLargeIntBase::TLargeIntBase(TInt n, TUint32 aUnsigned32) |
|
35 : iC(n) |
|
36 { |
|
37 Mem::FillZ(iX,n*sizeof(TUint32)); |
|
38 iX[0]=aUnsigned32; |
|
39 } |
|
40 |
|
41 TLargeIntBase::TLargeIntBase(TInt n, const TLargeIntBase& aSrc, TMode aMode) |
|
42 : iC(n) |
|
43 { |
|
44 __ASSERT(aMode==ETruncate||n>=aSrc.iC); // if not truncating, dest can't be shorter than source |
|
45 __ASSERT(aMode!=ETruncate||n<=aSrc.iC); // if truncating, dest can't be longer than source |
|
46 TInt min = Min(n,aSrc.iC); |
|
47 TInt i; |
|
48 for (i=0; i<min; ++i) |
|
49 iX[i] = aSrc.iX[i]; |
|
50 if (aMode==ETruncate || n==aSrc.iC) |
|
51 return; |
|
52 TUint32 f = (aMode==ESignExtend && (iX[i-1] & 0x80000000u)) ? 0xffffffffu : 0; |
|
53 for (; i<n; ++i) |
|
54 iX[i] = f; |
|
55 } |
|
56 |
|
57 TLargeIntBase::TLargeIntBase(TInt n, const TUint32* aPtr) |
|
58 : iC(n) |
|
59 { |
|
60 Mem::Copy(iX, aPtr, n*sizeof(TUint32)); |
|
61 } |
|
62 |
|
63 TLargeIntBase::TLargeIntBase(TInt n, const Int64& aSigned64) |
|
64 : iC(n) |
|
65 { |
|
66 __ASSERT(n>=2); |
|
67 Mem::Copy(iX, &aSigned64, 8); |
|
68 TUint f = (iX[1] & 0x80000000u) ? 0xff : 0; |
|
69 Mem::Fill(iX+2,(n-2)*sizeof(TUint32),f); |
|
70 } |
|
71 |
|
72 TLargeIntBase::TLargeIntBase(TInt n, const Uint64& aUnsigned64) |
|
73 : iC(n) |
|
74 { |
|
75 __ASSERT(n>=2); |
|
76 Mem::Copy(iX, &aUnsigned64, 8); |
|
77 Mem::FillZ(iX+2,(n-2)*sizeof(TUint32)); |
|
78 } |
|
79 |
|
80 void TLargeIntBase::Not() |
|
81 { |
|
82 TInt i; |
|
83 for (i=0; i<iC; ++i) |
|
84 iX[i] = ~iX[i]; |
|
85 } |
|
86 |
|
87 void TLargeIntBase::Neg() |
|
88 { |
|
89 Not(); |
|
90 Inc(); |
|
91 } |
|
92 |
|
93 void TLargeIntBase::Abs() |
|
94 { |
|
95 if (iX[iC-1] & 0x80000000u) |
|
96 Neg(); |
|
97 } |
|
98 |
|
99 void TLargeIntBase::Inc() |
|
100 { |
|
101 TInt i; |
|
102 for (i=0; i<iC && ++iX[i]==0; ++i) {} |
|
103 } |
|
104 |
|
105 void TLargeIntBase::Dec() |
|
106 { |
|
107 TInt i; |
|
108 for (i=0; i<iC && --iX[i]==0xffffffffu; ++i) {} |
|
109 } |
|
110 |
|
111 TUint32 TLargeIntBase::Lsl() |
|
112 { |
|
113 TInt i; |
|
114 TUint32 c = 0; |
|
115 for (i=0; i<iC; ++i) |
|
116 { |
|
117 TUint32 x = (iX[i]<<1) | (c>>31); |
|
118 c = iX[i]; |
|
119 iX[i] = x; |
|
120 } |
|
121 return c>>31; |
|
122 } |
|
123 |
|
124 TUint32 TLargeIntBase::Lsr() |
|
125 { |
|
126 TInt i; |
|
127 TUint32 c = 0; |
|
128 for (i=iC-1; i>=0; --i) |
|
129 { |
|
130 TUint32 x = (iX[i]>>1) | (c<<31); |
|
131 c = iX[i]; |
|
132 iX[i] = x; |
|
133 } |
|
134 return c&1; |
|
135 } |
|
136 |
|
137 TUint32 TLargeIntBase::Asr() |
|
138 { |
|
139 TInt i=iC-1; |
|
140 TUint32 c = iX[i]>>31; |
|
141 for (; i>=0; --i) |
|
142 { |
|
143 TUint32 x = (iX[i]>>1) | (c<<31); |
|
144 c = iX[i]; |
|
145 iX[i] = x; |
|
146 } |
|
147 return c&1; |
|
148 } |
|
149 |
|
150 void TLargeIntBase::Lsl(TInt aCount) |
|
151 { |
|
152 while(--aCount>=0) |
|
153 Lsl(); |
|
154 } |
|
155 |
|
156 void TLargeIntBase::Lsr(TInt aCount) |
|
157 { |
|
158 while(--aCount>=0) |
|
159 Lsr(); |
|
160 } |
|
161 |
|
162 void TLargeIntBase::Asr(TInt aCount) |
|
163 { |
|
164 while(--aCount>=0) |
|
165 Asr(); |
|
166 } |
|
167 |
|
168 void TLargeIntBase::Add(const TLargeIntBase& a) |
|
169 { |
|
170 __ASSERT(a.iC==iC); |
|
171 TInt i; |
|
172 TUint32 c = 0; |
|
173 for (i=0; i<iC; ++i) |
|
174 { |
|
175 TUint32 x = iX[i]; |
|
176 TUint32 y = a.iX[i]; |
|
177 TUint32 s = x + y; |
|
178 iX[i] = (s + (c>>31)); |
|
179 TUint32 g = (x & y) | ((x | y) &~ s); |
|
180 TUint32 p = ~s ? 0 : s; |
|
181 c = g | (c & p); |
|
182 } |
|
183 } |
|
184 |
|
185 void TLargeIntBase::Sub(const TLargeIntBase& a) |
|
186 { |
|
187 __ASSERT(a.iC==iC); |
|
188 TInt i; |
|
189 TUint32 c = 0x80000000u; |
|
190 for (i=0; i<iC; ++i) |
|
191 { |
|
192 TUint32 x = iX[i]; |
|
193 TUint32 y = ~a.iX[i]; |
|
194 TUint32 s = x + y; |
|
195 iX[i] = (s + (c>>31)); |
|
196 TUint32 g = (x & y) | ((x | y) &~ s); |
|
197 TUint32 p = ~s ? 0 : s; |
|
198 c = g | (c & p); |
|
199 } |
|
200 } |
|
201 |
|
202 void TLargeIntBase::Mul(const TLargeIntBase& a) |
|
203 { |
|
204 __ASSERT(a.iC==iC); |
|
205 TUint32 temp[64]; // HACK!! |
|
206 Mem::Copy(temp, this, (iC+1)*sizeof(TUint32)); |
|
207 TLargeIntBase& b = *(TLargeIntBase*)temp; |
|
208 new (this) TLargeIntBase(iC,TUint32(0u)); |
|
209 TInt i; |
|
210 for (i=0; i<32*iC; ++i) |
|
211 { |
|
212 Lsl(); |
|
213 if (b.Lsl()) |
|
214 Add(a); |
|
215 } |
|
216 } |
|
217 |
|
218 void TLargeIntBase::DivU(const TLargeIntBase& aDivisor, TLargeIntBase& aRem) |
|
219 { |
|
220 __ASSERT(aDivisor.iC==iC); |
|
221 __ASSERT(aRem.iC==iC); |
|
222 new (&aRem) TLargeIntBase(iC,TUint32(0u)); |
|
223 TInt i; |
|
224 for (i=0; i<iC*32; ++i) |
|
225 { |
|
226 aRem.Lsl(); |
|
227 if (Lsl()) |
|
228 aRem.Inc(); |
|
229 if (aRem.Hs(aDivisor)) |
|
230 aRem.Sub(aDivisor), Inc(); |
|
231 } |
|
232 } |
|
233 |
|
234 void TLargeIntBase::DivS(const TLargeIntBase& aDivisor, TLargeIntBase& aRem) |
|
235 { |
|
236 __ASSERT(aDivisor.iC==iC); |
|
237 __ASSERT(aRem.iC==iC); |
|
238 TUint32 temp[64]; // HACK!! |
|
239 Mem::Copy(temp, &aDivisor, (iC+1)*sizeof(TUint32)); |
|
240 TLargeIntBase& divisor = *(TLargeIntBase*)temp; |
|
241 TUint32 rs = iX[iC-1]; |
|
242 TUint32 qs = divisor.iX[iC-1] ^ rs; |
|
243 Abs(); |
|
244 divisor.Abs(); |
|
245 DivU(divisor, aRem); |
|
246 if (rs & 0x80000000u) |
|
247 aRem.Neg(); |
|
248 if (qs & 0x80000000u) |
|
249 Neg(); |
|
250 } |
|
251 |
|
252 TInt TLargeIntBase::CompareU(const TLargeIntBase& a) const |
|
253 { |
|
254 __ASSERT(a.iC==iC); |
|
255 TInt i; |
|
256 for (i=iC-1; i>=0; --i) |
|
257 { |
|
258 TUint32 x = iX[i]; |
|
259 TUint32 y = a.iX[i]; |
|
260 if (x>y) |
|
261 return 1; |
|
262 if (x<y) |
|
263 return -1; |
|
264 } |
|
265 return 0; |
|
266 } |
|
267 |
|
268 TInt TLargeIntBase::CompareS(const TLargeIntBase& a) const |
|
269 { |
|
270 __ASSERT(a.iC==iC); |
|
271 TInt i; |
|
272 TUint32 m = 0x80000000u; |
|
273 for (i=iC-1; i>=0; --i) |
|
274 { |
|
275 TUint32 x = iX[i] ^ m; |
|
276 TUint32 y = a.iX[i] ^ m; |
|
277 m = 0; |
|
278 if (x>y) |
|
279 return 1; |
|
280 if (x<y) |
|
281 return -1; |
|
282 } |
|
283 return 0; |
|
284 } |
|
285 |