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