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