Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <math.h>
21 :
22 : #include <rtl/ustrbuf.hxx>
23 : #include <tools/tools.h>
24 : #include <tools/bigint.hxx>
25 :
26 :
27 : #include <string.h>
28 : #include <ctype.h>
29 :
30 : static const long MY_MAXLONG = 0x3fffffff;
31 : static const long MY_MINLONG = -MY_MAXLONG;
32 : static const long MY_MAXSHORT = 0x00007fff;
33 : static const long MY_MINSHORT = -MY_MAXSHORT;
34 :
35 : /*
36 : * The algorithms for Addition, Substraction, Multiplication and Divison
37 : * of large numbers originate from SEMINUMERICAL ALGORITHMS by
38 : * DONALD E. KNUTH in the series The Art of Computer Programming:
39 : * chapter 4.3.1. The Classical Algorithms.
40 : */
41 :
42 : // TODO: Needs conversion to sal_uInt16/INT16/sal_uInt32/sal_Int32
43 736480 : void BigInt::MakeBigInt( const BigInt& rVal )
44 : {
45 736480 : if ( rVal.bIsBig )
46 : {
47 637 : memcpy( (void*)this, (const void*)&rVal, sizeof( BigInt ) );
48 1274 : while ( nLen > 1 && nNum[nLen-1] == 0 )
49 0 : nLen--;
50 : }
51 : else
52 : {
53 735843 : long nTmp = rVal.nVal;
54 :
55 735843 : nVal = rVal.nVal;
56 735843 : bIsBig = sal_True;
57 735843 : if ( nTmp < 0 )
58 : {
59 1 : bIsNeg = sal_True;
60 1 : nTmp = -nTmp;
61 : }
62 : else
63 735842 : bIsNeg = sal_False;
64 :
65 735843 : nNum[0] = (sal_uInt16)(nTmp & 0xffffL);
66 735843 : nNum[1] = (sal_uInt16)(nTmp >> 16);
67 735843 : if ( nTmp & 0xffff0000L )
68 366386 : nLen = 2;
69 : else
70 369457 : nLen = 1;
71 : }
72 736480 : }
73 :
74 368079 : void BigInt::Normalize()
75 : {
76 368079 : if ( bIsBig )
77 : {
78 986023 : while ( nLen > 1 && nNum[nLen-1] == 0 )
79 249865 : nLen--;
80 :
81 368079 : if ( nLen < 3 )
82 : {
83 250120 : if ( nLen < 2 )
84 1547 : nVal = nNum[0];
85 248573 : else if ( nNum[1] & 0x8000 )
86 389078 : return;
87 : else
88 227574 : nVal = ((long)nNum[1] << 16) + nNum[0];
89 :
90 229121 : bIsBig = sal_False;
91 :
92 229121 : if ( bIsNeg )
93 1 : nVal = -nVal;
94 : }
95 : // else nVal is undefined !!! W.P.
96 : }
97 : // why? nVal is undefined ??? W.P.
98 0 : else if ( nVal & 0xFFFF0000L )
99 0 : nLen = 2;
100 : else
101 0 : nLen = 1;
102 : }
103 :
104 192 : void BigInt::Mult( const BigInt &rVal, sal_uInt16 nMul )
105 : {
106 192 : sal_uInt16 nK = 0;
107 740 : for ( int i = 0; i < rVal.nLen; i++ )
108 : {
109 548 : sal_uInt32 nTmp = (sal_uInt32)rVal.nNum[i] * (sal_uInt32)nMul + nK;
110 548 : nK = (sal_uInt16)(nTmp >> 16);
111 548 : nNum[i] = (sal_uInt16)nTmp;
112 : }
113 :
114 192 : if ( nK )
115 : {
116 44 : nNum[rVal.nLen] = nK;
117 44 : nLen = rVal.nLen + 1;
118 : }
119 : else
120 148 : nLen = rVal.nLen;
121 :
122 192 : bIsBig = sal_True;
123 192 : bIsNeg = rVal.bIsNeg;
124 192 : }
125 :
126 58 : void BigInt::Div( sal_uInt16 nDiv, sal_uInt16& rRem )
127 : {
128 58 : sal_uInt32 nK = 0;
129 232 : for ( int i = nLen - 1; i >= 0; i-- )
130 : {
131 174 : sal_uInt32 nTmp = (sal_uInt32)nNum[i] + (nK << 16);
132 174 : nNum[i] = (sal_uInt16)(nTmp / nDiv);
133 174 : nK = nTmp % nDiv;
134 : }
135 58 : rRem = (sal_uInt16)nK;
136 :
137 58 : if ( nNum[nLen-1] == 0 )
138 2 : nLen -= 1;
139 58 : }
140 :
141 0 : bool BigInt::IsLess( const BigInt& rVal ) const
142 : {
143 0 : if ( rVal.nLen < nLen)
144 0 : return true;
145 0 : if ( rVal.nLen > nLen )
146 0 : return false;
147 :
148 : int i;
149 0 : for ( i = nLen - 1; i > 0 && nNum[i] == rVal.nNum[i]; i-- )
150 : {
151 : }
152 0 : return rVal.nNum[i] < nNum[i];
153 : }
154 :
155 98 : void BigInt::AddLong( BigInt& rB, BigInt& rErg )
156 : {
157 98 : if ( bIsNeg == rB.bIsNeg )
158 : {
159 : int i;
160 : char len;
161 :
162 : // if length of the two values differ, fill remaining positions
163 : // of the smaller value with zeros.
164 98 : if (nLen >= rB.nLen)
165 : {
166 98 : len = nLen;
167 154 : for (i = rB.nLen; i < len; i++)
168 56 : rB.nNum[i] = 0;
169 : }
170 : else
171 : {
172 0 : len = rB.nLen;
173 0 : for (i = nLen; i < len; i++)
174 0 : nNum[i] = 0;
175 : }
176 :
177 : // Add numerals, starting from the back
178 : long k;
179 98 : long nZ = 0;
180 404 : for (i = 0, k = 0; i < len; i++) {
181 306 : nZ = (long)nNum[i] + (long)rB.nNum[i] + k;
182 306 : if (nZ & 0xff0000L)
183 52 : k = 1;
184 : else
185 254 : k = 0;
186 306 : rErg.nNum[i] = (sal_uInt16)(nZ & 0xffffL);
187 : }
188 : // If an overflow occurred, add to solution
189 98 : if (nZ & 0xff0000L) // or if(k)
190 : {
191 0 : rErg.nNum[i] = 1;
192 0 : len++;
193 : }
194 : // Set length and sign
195 98 : rErg.nLen = len;
196 98 : rErg.bIsNeg = bIsNeg && rB.bIsNeg;
197 98 : rErg.bIsBig = sal_True;
198 : }
199 : // If one of the values is negative, perform substraction instead
200 0 : else if (bIsNeg)
201 : {
202 0 : bIsNeg = sal_False;
203 0 : rB.SubLong(*this, rErg);
204 0 : bIsNeg = sal_True;
205 : }
206 : else
207 : {
208 0 : rB.bIsNeg = sal_False;
209 0 : SubLong(rB, rErg);
210 0 : rB.bIsNeg = sal_True;
211 : }
212 98 : }
213 :
214 0 : void BigInt::SubLong( BigInt& rB, BigInt& rErg )
215 : {
216 0 : if ( bIsNeg == rB.bIsNeg )
217 : {
218 : int i;
219 : char len;
220 : long nZ, k;
221 :
222 : // if length of the two values differ, fill remaining positions
223 : // of the smaller value with zeros.
224 0 : if (nLen >= rB.nLen)
225 : {
226 0 : len = nLen;
227 0 : for (i = rB.nLen; i < len; i++)
228 0 : rB.nNum[i] = 0;
229 : }
230 : else
231 : {
232 0 : len = rB.nLen;
233 0 : for (i = nLen; i < len; i++)
234 0 : nNum[i] = 0;
235 : }
236 :
237 0 : if ( IsLess(rB) )
238 : {
239 0 : for (i = 0, k = 0; i < len; i++)
240 : {
241 0 : nZ = (long)nNum[i] - (long)rB.nNum[i] + k;
242 0 : if (nZ < 0)
243 0 : k = -1;
244 : else
245 0 : k = 0;
246 0 : rErg.nNum[i] = (sal_uInt16)(nZ & 0xffffL);
247 : }
248 0 : rErg.bIsNeg = bIsNeg;
249 : }
250 : else
251 : {
252 0 : for (i = 0, k = 0; i < len; i++)
253 : {
254 0 : nZ = (long)rB.nNum[i] - (long)nNum[i] + k;
255 0 : if (nZ < 0)
256 0 : k = -1;
257 : else
258 0 : k = 0;
259 0 : rErg.nNum[i] = (sal_uInt16)(nZ & 0xffffL);
260 : }
261 : // if a < b, revert sign
262 0 : rErg.bIsNeg = !bIsNeg;
263 : }
264 0 : rErg.nLen = len;
265 0 : rErg.bIsBig = sal_True;
266 : }
267 : // If one of the values is negative, perform addition instead
268 0 : else if (bIsNeg)
269 : {
270 0 : bIsNeg = sal_False;
271 0 : AddLong(rB, rErg);
272 0 : bIsNeg = sal_True;
273 0 : rErg.bIsNeg = sal_True;
274 : }
275 : else
276 : {
277 0 : rB.bIsNeg = sal_False;
278 0 : AddLong(rB, rErg);
279 0 : rB.bIsNeg = sal_True;
280 0 : rErg.bIsNeg = sal_False;
281 : }
282 0 : }
283 :
284 367827 : void BigInt::MultLong( const BigInt& rB, BigInt& rErg ) const
285 : {
286 : int i, j;
287 : sal_uInt32 nZ, k;
288 :
289 367827 : rErg.bIsNeg = bIsNeg != rB.bIsNeg;
290 367827 : rErg.bIsBig = sal_True;
291 367827 : rErg.nLen = nLen + rB.nLen;
292 :
293 1469740 : for (i = 0; i < rErg.nLen; i++)
294 1101913 : rErg.nNum[i] = 0;
295 :
296 736956 : for (j = 0; j < rB.nLen; j++)
297 : {
298 1103215 : for (i = 0, k = 0; i < nLen; i++)
299 : {
300 1468172 : nZ = (sal_uInt32)nNum[i] * (sal_uInt32)rB.nNum[j] +
301 1468172 : (sal_uInt32)rErg.nNum[i + j] + k;
302 734086 : rErg.nNum[i + j] = (sal_uInt16)(nZ & 0xffffUL);
303 734086 : k = nZ >> 16;
304 : }
305 369129 : rErg.nNum[i + j] = (sal_uInt16)k;
306 : }
307 367827 : }
308 :
309 96 : void BigInt::DivLong( const BigInt& rB, BigInt& rErg ) const
310 : {
311 : int i, j;
312 : long nTmp;
313 : sal_uInt16 nK, nQ, nMult;
314 96 : short nLenB = rB.nLen;
315 96 : short nLenB1 = rB.nLen - 1;
316 96 : BigInt aTmpA, aTmpB;
317 :
318 96 : nMult = (sal_uInt16)(0x10000L / ((long)rB.nNum[nLenB1] + 1));
319 :
320 96 : aTmpA.Mult( *this, nMult );
321 96 : if ( aTmpA.nLen == nLen )
322 : {
323 52 : aTmpA.nNum[aTmpA.nLen] = 0;
324 52 : aTmpA.nLen++;
325 : }
326 :
327 96 : aTmpB.Mult( rB, nMult );
328 :
329 244 : for (j = aTmpA.nLen - 1; j >= nLenB; j--)
330 : { // guess divisor
331 148 : nTmp = ( (long)aTmpA.nNum[j] << 16 ) + aTmpA.nNum[j - 1];
332 148 : if (aTmpA.nNum[j] == aTmpB.nNum[nLenB1])
333 0 : nQ = 0xFFFF;
334 : else
335 148 : nQ = (sal_uInt16)(((sal_uInt32)nTmp) / aTmpB.nNum[nLenB1]);
336 :
337 296 : if ( ((sal_uInt32)aTmpB.nNum[nLenB1 - 1] * nQ) >
338 148 : ((((sal_uInt32)nTmp) - aTmpB.nNum[nLenB1] * nQ) << 16) + aTmpA.nNum[j - 2])
339 0 : nQ--;
340 : // Start division
341 148 : nK = 0;
342 148 : nTmp = 0;
343 552 : for (i = 0; i < nLenB; i++)
344 : {
345 404 : nTmp = (long)aTmpA.nNum[j - nLenB + i]
346 404 : - ((long)aTmpB.nNum[i] * nQ)
347 404 : - nK;
348 404 : aTmpA.nNum[j - nLenB + i] = (sal_uInt16)nTmp;
349 404 : nK = (sal_uInt16) (nTmp >> 16);
350 404 : if ( nK )
351 248 : nK = (sal_uInt16)(0x10000UL - nK);
352 : }
353 148 : unsigned short& rNum( aTmpA.nNum[j - nLenB + i] );
354 148 : rNum = rNum - nK; // MSVC yields a warning on -= here, so don't use it
355 148 : if (aTmpA.nNum[j - nLenB + i] == 0)
356 148 : rErg.nNum[j - nLenB] = nQ;
357 : else
358 : {
359 0 : rErg.nNum[j - nLenB] = nQ - 1;
360 0 : nK = 0;
361 0 : for (i = 0; i < nLenB; i++)
362 : {
363 0 : nTmp = aTmpA.nNum[j - nLenB + i] + aTmpB.nNum[i] + nK;
364 0 : aTmpA.nNum[j - nLenB + i] = (sal_uInt16)(nTmp & 0xFFFFL);
365 0 : if (nTmp & 0xFFFF0000L)
366 0 : nK = 1;
367 : else
368 0 : nK = 0;
369 : }
370 : }
371 : }
372 :
373 96 : rErg.bIsNeg = bIsNeg != rB.bIsNeg;
374 96 : rErg.bIsBig = sal_True;
375 96 : rErg.nLen = nLen - rB.nLen + 1;
376 96 : }
377 :
378 0 : void BigInt::ModLong( const BigInt& rB, BigInt& rErg ) const
379 : {
380 : short i, j;
381 : long nTmp;
382 : sal_uInt16 nK, nQ, nMult;
383 0 : short nLenB = rB.nLen;
384 0 : short nLenB1 = rB.nLen - 1;
385 0 : BigInt aTmpA, aTmpB;
386 :
387 0 : nMult = (sal_uInt16)(0x10000L / ((long)rB.nNum[nLenB1] + 1));
388 :
389 0 : aTmpA.Mult( *this, nMult);
390 0 : if ( aTmpA.nLen == nLen )
391 : {
392 0 : aTmpA.nNum[aTmpA.nLen] = 0;
393 0 : aTmpA.nLen++;
394 : }
395 :
396 0 : aTmpB.Mult( rB, nMult);
397 :
398 0 : for (j = aTmpA.nLen - 1; j >= nLenB; j--)
399 : { // Guess divisor
400 0 : nTmp = ( (long)aTmpA.nNum[j] << 16 ) + aTmpA.nNum[j - 1];
401 0 : if (aTmpA.nNum[j] == aTmpB.nNum[nLenB1])
402 0 : nQ = 0xFFFF;
403 : else
404 0 : nQ = (sal_uInt16)(((sal_uInt32)nTmp) / aTmpB.nNum[nLenB1]);
405 :
406 0 : if ( ((sal_uInt32)aTmpB.nNum[nLenB1 - 1] * nQ) >
407 0 : ((((sal_uInt32)nTmp) - aTmpB.nNum[nLenB1] * nQ) << 16) + aTmpA.nNum[j - 2])
408 0 : nQ--;
409 : // Start division
410 0 : nK = 0;
411 0 : nTmp = 0;
412 0 : for (i = 0; i < nLenB; i++)
413 : {
414 0 : nTmp = (long)aTmpA.nNum[j - nLenB + i]
415 0 : - ((long)aTmpB.nNum[i] * nQ)
416 0 : - nK;
417 0 : aTmpA.nNum[j - nLenB + i] = (sal_uInt16)nTmp;
418 0 : nK = (sal_uInt16) (nTmp >> 16);
419 0 : if ( nK )
420 0 : nK = (sal_uInt16)(0x10000UL - nK);
421 : }
422 0 : unsigned short& rNum( aTmpA.nNum[j - nLenB + i] );
423 0 : rNum = rNum - nK;
424 0 : if (aTmpA.nNum[j - nLenB + i] == 0)
425 0 : rErg.nNum[j - nLenB] = nQ;
426 : else
427 : {
428 0 : rErg.nNum[j - nLenB] = nQ - 1;
429 0 : nK = 0;
430 0 : for (i = 0; i < nLenB; i++) {
431 0 : nTmp = aTmpA.nNum[j - nLenB + i] + aTmpB.nNum[i] + nK;
432 0 : aTmpA.nNum[j - nLenB + i] = (sal_uInt16)(nTmp & 0xFFFFL);
433 0 : if (nTmp & 0xFFFF0000L)
434 0 : nK = 1;
435 : else
436 0 : nK = 0;
437 : }
438 : }
439 : }
440 :
441 0 : rErg = aTmpA;
442 0 : rErg.Div( nMult, nQ );
443 0 : }
444 :
445 96 : bool BigInt::ABS_IsLess( const BigInt& rB ) const
446 : {
447 96 : if (bIsBig || rB.bIsBig)
448 : {
449 96 : BigInt nA, nB;
450 96 : nA.MakeBigInt( *this );
451 96 : nB.MakeBigInt( rB );
452 96 : if (nA.nLen == nB.nLen)
453 : {
454 : int i;
455 44 : for (i = nA.nLen - 1; i > 0 && nA.nNum[i] == nB.nNum[i]; i--)
456 : {
457 : }
458 44 : return nA.nNum[i] < nB.nNum[i];
459 : }
460 : else
461 52 : return nA.nLen < nB.nLen;
462 : }
463 0 : if ( nVal < 0 )
464 0 : if ( rB.nVal < 0 )
465 0 : return nVal > rB.nVal;
466 : else
467 0 : return nVal > -rB.nVal;
468 : else
469 0 : if ( rB.nVal < 0 )
470 0 : return nVal < -rB.nVal;
471 : else
472 0 : return nVal < rB.nVal;
473 : }
474 :
475 2647 : BigInt::BigInt( const BigInt& rBigInt )
476 : {
477 2647 : if ( rBigInt.bIsBig )
478 56 : memcpy( (void*)this, (const void*)&rBigInt, sizeof( BigInt ) );
479 : else
480 : {
481 2591 : bIsSet = rBigInt.bIsSet;
482 2591 : bIsBig = sal_False;
483 2591 : nVal = rBigInt.nVal;
484 : }
485 2647 : }
486 :
487 0 : BigInt::BigInt( const OUString& rString )
488 : {
489 0 : bIsSet = sal_True;
490 0 : bIsNeg = sal_False;
491 0 : bIsBig = sal_False;
492 0 : nVal = 0;
493 :
494 0 : bool bNeg = false;
495 0 : const sal_Unicode* p = rString.getStr();
496 0 : if ( *p == '-' )
497 : {
498 0 : bNeg = true;
499 0 : p++;
500 : }
501 0 : while( *p >= '0' && *p <= '9' )
502 : {
503 0 : *this *= 10;
504 0 : *this += *p - '0';
505 0 : p++;
506 : }
507 0 : if ( bIsBig )
508 0 : bIsNeg = bNeg ? sal_True : sal_False;
509 0 : else if( bNeg )
510 0 : nVal = -nVal;
511 0 : }
512 :
513 0 : BigInt::BigInt( double nValue )
514 : {
515 0 : bIsSet = sal_True;
516 :
517 0 : if ( nValue < 0 )
518 : {
519 0 : nValue *= -1;
520 0 : bIsNeg = sal_True;
521 : }
522 : else
523 : {
524 0 : bIsNeg = sal_False;
525 : }
526 :
527 0 : if ( nValue < 1 )
528 : {
529 0 : bIsBig = sal_False;
530 0 : nVal = 0;
531 : }
532 : else
533 : {
534 0 : bIsBig = sal_True;
535 :
536 0 : int i=0;
537 :
538 0 : while ( ( nValue > 65536.0 ) && ( i < MAX_DIGITS ) )
539 : {
540 0 : nNum[i] = (sal_uInt16) fmod( nValue, 65536.0 );
541 0 : nValue -= nNum[i];
542 0 : nValue /= 65536.0;
543 0 : i++;
544 : }
545 0 : if ( i < MAX_DIGITS )
546 0 : nNum[i++] = (sal_uInt16) nValue;
547 :
548 0 : nLen = i;
549 :
550 0 : if ( i < 3 )
551 0 : Normalize();
552 : }
553 0 : }
554 :
555 369 : BigInt::BigInt( sal_uInt32 nValue )
556 : {
557 369 : bIsSet = sal_True;
558 369 : if ( nValue & 0x80000000UL )
559 : {
560 123 : bIsBig = sal_True;
561 123 : bIsNeg = sal_False;
562 123 : nNum[0] = (sal_uInt16)(nValue & 0xffffUL);
563 123 : nNum[1] = (sal_uInt16)(nValue >> 16);
564 123 : nLen = 2;
565 : }
566 : else
567 : {
568 246 : bIsBig = sal_False;
569 246 : nVal = nValue;
570 : }
571 369 : }
572 :
573 123 : BigInt::operator sal_uIntPtr() const
574 : {
575 123 : if ( !bIsBig )
576 123 : return (sal_uInt32)nVal;
577 0 : else if ( nLen == 2 )
578 : {
579 : sal_uInt32 nRet;
580 0 : nRet = ((sal_uInt32)nNum[1]) << 16;
581 0 : nRet += nNum[0];
582 0 : return nRet;
583 : }
584 0 : return 0;
585 : }
586 :
587 0 : BigInt::operator double() const
588 : {
589 0 : if ( !bIsBig )
590 0 : return (double) nVal;
591 : else
592 : {
593 0 : int i = nLen-1;
594 0 : double nRet = (double) ((sal_uInt32)nNum[i]);
595 :
596 0 : while ( i )
597 : {
598 0 : nRet *= 65536.0;
599 0 : i--;
600 0 : nRet += (double) ((sal_uInt32)nNum[i]);
601 : }
602 :
603 0 : if ( bIsNeg )
604 0 : nRet *= -1;
605 :
606 0 : return nRet;
607 : }
608 : }
609 :
610 0 : OUString BigInt::GetString() const
611 : {
612 :
613 0 : if ( !bIsBig )
614 : {
615 0 : return OUString::number( nVal );
616 : }
617 : else
618 : {
619 0 : BigInt aTmp( *this );
620 0 : BigInt a1000000000( 1000000000L );
621 0 : aTmp.Abs();
622 0 : OUStringBuffer sBuff(30);
623 0 : do
624 : {
625 0 : BigInt a = aTmp;
626 0 : a %= a1000000000;
627 0 : aTmp /= a1000000000;
628 0 : if ( a.nVal < 100000000L )
629 : {
630 : // to get leading 0s
631 0 : OUString aStr(OUString::number( a.nVal + 1000000000L ));
632 0 : sBuff.insert(0, aStr.getStr() + 1);
633 : }
634 : else
635 : {
636 0 : sBuff.insert(0, OUString::number( a.nVal ));
637 : }
638 : }
639 : while( aTmp.bIsBig );
640 :
641 0 : if ( bIsNeg )
642 : {
643 0 : sBuff.insert(0, OUString::number( -aTmp.nVal ));
644 : }
645 : else
646 : {
647 0 : sBuff.insert(0, OUString::number( aTmp.nVal ));
648 : }
649 0 : return sBuff.makeStringAndClear();
650 : }
651 : }
652 :
653 1476 : BigInt& BigInt::operator=( const BigInt& rBigInt )
654 : {
655 1476 : if ( rBigInt.bIsBig )
656 0 : memcpy( (void*)this, (const void*)&rBigInt, sizeof( BigInt ) );
657 : else
658 : {
659 1476 : bIsSet = rBigInt.bIsSet;
660 1476 : bIsBig = sal_False;
661 1476 : nVal = rBigInt.nVal;
662 : }
663 1476 : return *this;
664 : }
665 :
666 3861218 : BigInt& BigInt::operator+=( const BigInt& rVal )
667 : {
668 3861218 : if ( !bIsBig && !rVal.bIsBig )
669 : {
670 3861120 : if( nVal <= MY_MAXLONG && rVal.nVal <= MY_MAXLONG
671 3861120 : && nVal >= MY_MINLONG && rVal.nVal >= MY_MINLONG )
672 : { // No overflows may occur here
673 3861120 : nVal += rVal.nVal;
674 3861120 : return *this;
675 : }
676 :
677 0 : if( (nVal < 0) != (rVal.nVal < 0) )
678 : { // No overflows may occur here
679 0 : nVal += rVal.nVal;
680 0 : return *this;
681 : }
682 : }
683 :
684 98 : BigInt aTmp1, aTmp2;
685 98 : aTmp1.MakeBigInt( *this );
686 98 : aTmp2.MakeBigInt( rVal );
687 98 : aTmp1.AddLong( aTmp2, *this );
688 98 : Normalize();
689 98 : return *this;
690 : }
691 :
692 67 : BigInt& BigInt::operator-=( const BigInt& rVal )
693 : {
694 67 : if ( !bIsBig && !rVal.bIsBig )
695 : {
696 134 : if ( nVal <= MY_MAXLONG && rVal.nVal <= MY_MAXLONG &&
697 134 : nVal >= MY_MINLONG && rVal.nVal >= MY_MINLONG )
698 : { // No overflows may occur here
699 67 : nVal -= rVal.nVal;
700 67 : return *this;
701 : }
702 :
703 0 : if ( (nVal < 0) == (rVal.nVal < 0) )
704 : { // No overflows may occur here
705 0 : nVal -= rVal.nVal;
706 0 : return *this;
707 : }
708 : }
709 :
710 0 : BigInt aTmp1, aTmp2;
711 0 : aTmp1.MakeBigInt( *this );
712 0 : aTmp2.MakeBigInt( rVal );
713 0 : aTmp1.SubLong( aTmp2, *this );
714 0 : Normalize();
715 0 : return *this;
716 : }
717 :
718 5678262 : BigInt& BigInt::operator*=( const BigInt& rVal )
719 : {
720 5678262 : if ( !bIsBig && !rVal.bIsBig
721 5678206 : && nVal <= MY_MAXSHORT && rVal.nVal <= MY_MAXSHORT
722 5310436 : && nVal >= MY_MINSHORT && rVal.nVal >= MY_MINSHORT )
723 : // TODO: not optimal !!! W.P.
724 : { // No overflows may occur here
725 5310435 : nVal *= rVal.nVal;
726 : }
727 : else
728 : {
729 367827 : BigInt aTmp1, aTmp2;
730 367827 : aTmp1.MakeBigInt( rVal );
731 367827 : aTmp2.MakeBigInt( *this );
732 367827 : aTmp1.MultLong(aTmp2, *this);
733 367827 : Normalize();
734 : }
735 5678262 : return *this;
736 : }
737 :
738 3861702 : BigInt& BigInt::operator/=( const BigInt& rVal )
739 : {
740 3861702 : if ( !rVal.bIsBig )
741 : {
742 3861646 : if ( rVal.nVal == 0 )
743 : {
744 : OSL_FAIL( "BigInt::operator/ --> divide by zero" );
745 0 : return *this;
746 : }
747 :
748 3861646 : if ( !bIsBig )
749 : {
750 : // No overflows may occur here
751 3861548 : nVal /= rVal.nVal;
752 3861548 : return *this;
753 : }
754 :
755 98 : if ( rVal.nVal == 1 )
756 0 : return *this;
757 :
758 98 : if ( rVal.nVal == -1 )
759 : {
760 0 : bIsNeg = !bIsNeg;
761 0 : return *this;
762 : }
763 :
764 98 : if ( rVal.nVal <= (long)0xFFFF && rVal.nVal >= -(long)0xFFFF )
765 : {
766 : // Divide BigInt with an sal_uInt16
767 : sal_uInt16 nTmp;
768 58 : if ( rVal.nVal < 0 )
769 : {
770 0 : nTmp = (sal_uInt16) -rVal.nVal;
771 0 : bIsNeg = !bIsNeg;
772 : }
773 : else
774 58 : nTmp = (sal_uInt16) rVal.nVal;
775 :
776 58 : Div( nTmp, nTmp );
777 58 : Normalize();
778 58 : return *this;
779 : }
780 : }
781 :
782 96 : if ( ABS_IsLess( rVal ) )
783 : {
784 0 : *this = BigInt( (long)0 );
785 0 : return *this;
786 : }
787 :
788 : // Divide BigInt with BigInt
789 96 : BigInt aTmp1, aTmp2;
790 96 : aTmp1.MakeBigInt( *this );
791 96 : aTmp2.MakeBigInt( rVal );
792 96 : aTmp1.DivLong(aTmp2, *this);
793 96 : Normalize();
794 96 : return *this;
795 : }
796 :
797 0 : BigInt& BigInt::operator%=( const BigInt& rVal )
798 : {
799 0 : if ( !rVal.bIsBig )
800 : {
801 0 : if ( rVal.nVal == 0 )
802 : {
803 : OSL_FAIL( "BigInt::operator/ --> divide by zero" );
804 0 : return *this;
805 : }
806 :
807 0 : if ( !bIsBig )
808 : {
809 : // No overflows may occur here
810 0 : nVal %= rVal.nVal;
811 0 : return *this;
812 : }
813 :
814 0 : if ( rVal.nVal <= (long)0xFFFF && rVal.nVal >= -(long)0xFFFF )
815 : {
816 : // Divide Bigint by short
817 : sal_uInt16 nTmp;
818 0 : if ( rVal.nVal < 0 )
819 : {
820 0 : nTmp = (sal_uInt16) -rVal.nVal;
821 0 : bIsNeg = !bIsNeg;
822 : }
823 : else
824 0 : nTmp = (sal_uInt16) rVal.nVal;
825 :
826 0 : Div( nTmp, nTmp );
827 0 : *this = BigInt( (long)nTmp );
828 0 : return *this;
829 : }
830 : }
831 :
832 0 : if ( ABS_IsLess( rVal ) )
833 0 : return *this;
834 :
835 : // Divide BigInt with BigInt
836 0 : BigInt aTmp1, aTmp2;
837 0 : aTmp1.MakeBigInt( *this );
838 0 : aTmp2.MakeBigInt( rVal );
839 0 : aTmp1.ModLong(aTmp2, *this);
840 0 : Normalize();
841 0 : return *this;
842 : }
843 :
844 0 : bool operator==( const BigInt& rVal1, const BigInt& rVal2 )
845 : {
846 0 : if ( rVal1.bIsBig || rVal2.bIsBig )
847 : {
848 0 : BigInt nA, nB;
849 0 : nA.MakeBigInt( rVal1 );
850 0 : nB.MakeBigInt( rVal2 );
851 0 : if ( nA.bIsNeg == nB.bIsNeg )
852 : {
853 0 : if ( nA.nLen == nB.nLen )
854 : {
855 : int i;
856 0 : for ( i = nA.nLen - 1; i > 0 && nA.nNum[i] == nB.nNum[i]; i-- )
857 : {
858 : }
859 :
860 0 : return nA.nNum[i] == nB.nNum[i];
861 : }
862 0 : return false;
863 : }
864 0 : return false;
865 : }
866 0 : return rVal1.nVal == rVal2.nVal;
867 : }
868 :
869 660 : bool operator<( const BigInt& rVal1, const BigInt& rVal2 )
870 : {
871 660 : if ( rVal1.bIsBig || rVal2.bIsBig )
872 : {
873 123 : BigInt nA, nB;
874 123 : nA.MakeBigInt( rVal1 );
875 123 : nB.MakeBigInt( rVal2 );
876 123 : if ( nA.bIsNeg == nB.bIsNeg )
877 : {
878 123 : if ( nA.nLen == nB.nLen )
879 : {
880 : int i;
881 119 : for ( i = nA.nLen - 1; i > 0 && nA.nNum[i] == nB.nNum[i]; i-- )
882 : {
883 : }
884 :
885 119 : if ( nA.bIsNeg )
886 0 : return nA.nNum[i] > nB.nNum[i];
887 : else
888 119 : return nA.nNum[i] < nB.nNum[i];
889 : }
890 4 : if ( nA.bIsNeg )
891 0 : return nA.nLen > nB.nLen;
892 : else
893 4 : return nA.nLen < nB.nLen;
894 : }
895 0 : return !nB.bIsNeg;
896 : }
897 537 : return rVal1.nVal < rVal2.nVal;
898 : }
899 :
900 410 : bool operator >(const BigInt& rVal1, const BigInt& rVal2 )
901 : {
902 410 : if ( rVal1.bIsBig || rVal2.bIsBig )
903 : {
904 0 : BigInt nA, nB;
905 0 : nA.MakeBigInt( rVal1 );
906 0 : nB.MakeBigInt( rVal2 );
907 0 : if ( nA.bIsNeg == nB.bIsNeg )
908 : {
909 0 : if ( nA.nLen == nB.nLen )
910 : {
911 : int i;
912 0 : for ( i = nA.nLen - 1; i > 0 && nA.nNum[i] == nB.nNum[i]; i-- )
913 : {
914 : }
915 :
916 0 : if ( nA.bIsNeg )
917 0 : return nA.nNum[i] < nB.nNum[i];
918 : else
919 0 : return nA.nNum[i] > nB.nNum[i];
920 : }
921 0 : if ( nA.bIsNeg )
922 0 : return nA.nLen < nB.nLen;
923 : else
924 0 : return nA.nLen > nB.nLen;
925 : }
926 0 : return !nA.bIsNeg;
927 : }
928 :
929 410 : return rVal1.nVal > rVal2.nVal;
930 : }
931 :
932 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|