1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
23 #include <rtl/ustrbuf.hxx>
24 #include <osl/diagnose.h>
25 #include <tools/bigint.hxx>
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
;
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.
43 // TODO: Needs conversion to sal_uInt16/INT16/sal_uInt32/sal_Int32
44 void BigInt::MakeBigInt( const BigInt
& rVal
)
48 memcpy( (void*)this, (const void*)&rVal
, sizeof( BigInt
) );
49 while ( nLen
> 1 && nNum
[nLen
-1] == 0 )
54 long nTmp
= rVal
.nVal
;
66 nNum
[0] = (sal_uInt16
)(nTmp
& 0xffffL
);
67 nNum
[1] = (sal_uInt16
)(nTmp
>> 16);
68 if ( nTmp
& 0xffff0000L
)
75 void BigInt::Normalize()
79 while ( nLen
> 1 && nNum
[nLen
-1] == 0 )
86 else if ( nNum
[1] & 0x8000 )
89 nVal
= ((long)nNum
[1] << 16) + nNum
[0];
96 // else nVal is undefined !!! W.P.
98 // why? nVal is undefined ??? W.P.
99 else if ( nVal
& 0xFFFF0000L
)
105 void BigInt::Mult( const BigInt
&rVal
, sal_uInt16 nMul
)
108 for ( int i
= 0; i
< rVal
.nLen
; i
++ )
110 sal_uInt32 nTmp
= (sal_uInt32
)rVal
.nNum
[i
] * (sal_uInt32
)nMul
+ nK
;
111 nK
= (sal_uInt16
)(nTmp
>> 16);
112 nNum
[i
] = (sal_uInt16
)nTmp
;
117 nNum
[rVal
.nLen
] = nK
;
118 nLen
= rVal
.nLen
+ 1;
124 bIsNeg
= rVal
.bIsNeg
;
127 void BigInt::Div( sal_uInt16 nDiv
, sal_uInt16
& rRem
)
130 for ( int i
= nLen
- 1; i
>= 0; i
-- )
132 sal_uInt32 nTmp
= (sal_uInt32
)nNum
[i
] + (nK
<< 16);
133 nNum
[i
] = (sal_uInt16
)(nTmp
/ nDiv
);
136 rRem
= (sal_uInt16
)nK
;
138 if ( nNum
[nLen
-1] == 0 )
142 bool BigInt::IsLess( const BigInt
& rVal
) const
144 if ( rVal
.nLen
< nLen
)
146 if ( rVal
.nLen
> nLen
)
150 for ( i
= nLen
- 1; i
> 0 && nNum
[i
] == rVal
.nNum
[i
]; i
-- )
153 return rVal
.nNum
[i
] < nNum
[i
];
156 void BigInt::AddLong( BigInt
& rB
, BigInt
& rErg
)
158 if ( bIsNeg
== rB
.bIsNeg
)
163 // if length of the two values differ, fill remaining positions
164 // of the smaller value with zeros.
168 for (i
= rB
.nLen
; i
< len
; i
++)
174 for (i
= nLen
; i
< len
; i
++)
178 // Add numerals, starting from the back
181 for (i
= 0, k
= 0; i
< len
; i
++) {
182 nZ
= (long)nNum
[i
] + (long)rB
.nNum
[i
] + k
;
187 rErg
.nNum
[i
] = (sal_uInt16
)(nZ
& 0xffffL
);
189 // If an overflow occurred, add to solution
190 if (nZ
& 0xff0000L
) // or if(k)
195 // Set length and sign
197 rErg
.bIsNeg
= bIsNeg
&& rB
.bIsNeg
;
200 // If one of the values is negative, perform subtraction instead
204 rB
.SubLong(*this, rErg
);
215 void BigInt::SubLong( BigInt
& rB
, BigInt
& rErg
)
217 if ( bIsNeg
== rB
.bIsNeg
)
223 // if length of the two values differ, fill remaining positions
224 // of the smaller value with zeros.
228 for (i
= rB
.nLen
; i
< len
; i
++)
234 for (i
= nLen
; i
< len
; i
++)
240 for (i
= 0, k
= 0; i
< len
; i
++)
242 nZ
= (long)nNum
[i
] - (long)rB
.nNum
[i
] + k
;
247 rErg
.nNum
[i
] = (sal_uInt16
)(nZ
& 0xffffL
);
249 rErg
.bIsNeg
= bIsNeg
;
253 for (i
= 0, k
= 0; i
< len
; i
++)
255 nZ
= (long)rB
.nNum
[i
] - (long)nNum
[i
] + k
;
260 rErg
.nNum
[i
] = (sal_uInt16
)(nZ
& 0xffffL
);
262 // if a < b, revert sign
263 rErg
.bIsNeg
= !bIsNeg
;
268 // If one of the values is negative, perform addition instead
285 void BigInt::MultLong( const BigInt
& rB
, BigInt
& rErg
) const
290 rErg
.bIsNeg
= bIsNeg
!= rB
.bIsNeg
;
292 rErg
.nLen
= nLen
+ rB
.nLen
;
294 for (i
= 0; i
< rErg
.nLen
; i
++)
297 for (j
= 0; j
< rB
.nLen
; j
++)
299 for (i
= 0, k
= 0; i
< nLen
; i
++)
301 nZ
= (sal_uInt32
)nNum
[i
] * (sal_uInt32
)rB
.nNum
[j
] +
302 (sal_uInt32
)rErg
.nNum
[i
+ j
] + k
;
303 rErg
.nNum
[i
+ j
] = (sal_uInt16
)(nZ
& 0xffffUL
);
306 rErg
.nNum
[i
+ j
] = (sal_uInt16
)k
;
310 void BigInt::DivLong( const BigInt
& rB
, BigInt
& rErg
) const
313 sal_uInt16 nK
, nQ
, nMult
;
314 short nLenB
= rB
.nLen
;
315 short nLenB1
= rB
.nLen
- 1;
318 nMult
= (sal_uInt16
)(0x10000L
/ ((long)rB
.nNum
[nLenB1
] + 1));
320 aTmpA
.Mult( *this, nMult
);
321 if ( aTmpA
.nLen
== nLen
)
323 aTmpA
.nNum
[aTmpA
.nLen
] = 0;
327 aTmpB
.Mult( rB
, nMult
);
329 for (j
= aTmpA
.nLen
- 1; j
>= nLenB
; j
--)
331 long nTmp
= ( (long)aTmpA
.nNum
[j
] << 16 ) + aTmpA
.nNum
[j
- 1];
332 if (aTmpA
.nNum
[j
] == aTmpB
.nNum
[nLenB1
])
335 nQ
= (sal_uInt16
)(((sal_uInt32
)nTmp
) / aTmpB
.nNum
[nLenB1
]);
337 if ( ((sal_uInt32
)aTmpB
.nNum
[nLenB1
- 1] * nQ
) >
338 ((((sal_uInt32
)nTmp
) - aTmpB
.nNum
[nLenB1
] * nQ
) << 16) + aTmpA
.nNum
[j
- 2])
343 for (i
= 0; i
< nLenB
; i
++)
345 nTmp
= (long)aTmpA
.nNum
[j
- nLenB
+ i
]
346 - ((long)aTmpB
.nNum
[i
] * nQ
)
348 aTmpA
.nNum
[j
- nLenB
+ i
] = (sal_uInt16
)nTmp
;
349 nK
= (sal_uInt16
) (nTmp
>> 16);
351 nK
= (sal_uInt16
)(0x10000UL
- nK
);
353 unsigned short& rNum( aTmpA
.nNum
[j
- nLenB
+ i
] );
354 rNum
= rNum
- nK
; // MSVC yields a warning on -= here, so don't use it
355 if (aTmpA
.nNum
[j
- nLenB
+ i
] == 0)
356 rErg
.nNum
[j
- nLenB
] = nQ
;
359 rErg
.nNum
[j
- nLenB
] = nQ
- 1;
361 for (i
= 0; i
< nLenB
; i
++)
363 nTmp
= aTmpA
.nNum
[j
- nLenB
+ i
] + aTmpB
.nNum
[i
] + nK
;
364 aTmpA
.nNum
[j
- nLenB
+ i
] = (sal_uInt16
)(nTmp
& 0xFFFFL
);
365 if (nTmp
& 0xFFFF0000L
)
373 rErg
.bIsNeg
= bIsNeg
!= rB
.bIsNeg
;
375 rErg
.nLen
= nLen
- rB
.nLen
+ 1;
378 void BigInt::ModLong( const BigInt
& rB
, BigInt
& rErg
) const
381 sal_uInt16 nK
, nQ
, nMult
;
382 short nLenB
= rB
.nLen
;
383 short nLenB1
= rB
.nLen
- 1;
386 nMult
= (sal_uInt16
)(0x10000L
/ ((long)rB
.nNum
[nLenB1
] + 1));
388 aTmpA
.Mult( *this, nMult
);
389 if ( aTmpA
.nLen
== nLen
)
391 aTmpA
.nNum
[aTmpA
.nLen
] = 0;
395 aTmpB
.Mult( rB
, nMult
);
397 for (j
= aTmpA
.nLen
- 1; j
>= nLenB
; j
--)
399 long nTmp
= ( (long)aTmpA
.nNum
[j
] << 16 ) + aTmpA
.nNum
[j
- 1];
400 if (aTmpA
.nNum
[j
] == aTmpB
.nNum
[nLenB1
])
403 nQ
= (sal_uInt16
)(((sal_uInt32
)nTmp
) / aTmpB
.nNum
[nLenB1
]);
405 if ( ((sal_uInt32
)aTmpB
.nNum
[nLenB1
- 1] * nQ
) >
406 ((((sal_uInt32
)nTmp
) - aTmpB
.nNum
[nLenB1
] * nQ
) << 16) + aTmpA
.nNum
[j
- 2])
411 for (i
= 0; i
< nLenB
; i
++)
413 nTmp
= (long)aTmpA
.nNum
[j
- nLenB
+ i
]
414 - ((long)aTmpB
.nNum
[i
] * nQ
)
416 aTmpA
.nNum
[j
- nLenB
+ i
] = (sal_uInt16
)nTmp
;
417 nK
= (sal_uInt16
) (nTmp
>> 16);
419 nK
= (sal_uInt16
)(0x10000UL
- nK
);
421 unsigned short& rNum( aTmpA
.nNum
[j
- nLenB
+ i
] );
423 if (aTmpA
.nNum
[j
- nLenB
+ i
] == 0)
424 rErg
.nNum
[j
- nLenB
] = nQ
;
427 rErg
.nNum
[j
- nLenB
] = nQ
- 1;
429 for (i
= 0; i
< nLenB
; i
++) {
430 nTmp
= aTmpA
.nNum
[j
- nLenB
+ i
] + aTmpB
.nNum
[i
] + nK
;
431 aTmpA
.nNum
[j
- nLenB
+ i
] = (sal_uInt16
)(nTmp
& 0xFFFFL
);
432 if (nTmp
& 0xFFFF0000L
)
441 rErg
.Div( nMult
, nQ
);
444 bool BigInt::ABS_IsLess( const BigInt
& rB
) const
446 if (bIsBig
|| rB
.bIsBig
)
449 nA
.MakeBigInt( *this );
451 if (nA
.nLen
== nB
.nLen
)
454 for (i
= nA
.nLen
- 1; i
> 0 && nA
.nNum
[i
] == nB
.nNum
[i
]; i
--)
457 return nA
.nNum
[i
] < nB
.nNum
[i
];
460 return nA
.nLen
< nB
.nLen
;
464 return nVal
> rB
.nVal
;
466 return nVal
> -rB
.nVal
;
469 return nVal
< -rB
.nVal
;
471 return nVal
< rB
.nVal
;
474 BigInt::BigInt( const BigInt
& rBigInt
)
478 if ( rBigInt
.bIsBig
)
479 memcpy( (void*)this, (const void*)&rBigInt
, sizeof( BigInt
) );
482 bIsSet
= rBigInt
.bIsSet
;
488 BigInt::BigInt( const OUString
& rString
)
497 const sal_Unicode
* p
= rString
.getStr();
503 while( *p
>= '0' && *p
<= '9' )
515 BigInt::BigInt( double nValue
)
542 while ( ( nValue
> 65536.0 ) && ( i
< MAX_DIGITS
) )
544 nNum
[i
] = (sal_uInt16
) fmod( nValue
, 65536.0 );
549 if ( i
< MAX_DIGITS
)
550 nNum
[i
++] = (sal_uInt16
) nValue
;
559 BigInt::BigInt( sal_uInt32 nValue
)
563 if ( nValue
& 0x80000000UL
)
567 nNum
[0] = (sal_uInt16
)(nValue
& 0xffffUL
);
568 nNum
[1] = (sal_uInt16
)(nValue
>> 16);
580 #if SAL_TYPES_SIZEOFLONG < SAL_TYPES_SIZEOFLONGLONG
581 BigInt::BigInt( long long nValue
)
588 if ((nValue
>= std::numeric_limits
<long>::min()) && (nValue
<= std::numeric_limits
<long>::max()))
591 nVal
= static_cast<long>(nValue
);
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
)
599 nNum
[i
] = static_cast<sal_uInt16
>(nUValue
& 0xffffUL
);
600 nUValue
= nUValue
>> 16;
607 BigInt::operator sal_uIntPtr() const
610 return (sal_uInt32
)nVal
;
611 else if ( nLen
== 2 )
614 nRet
= ((sal_uInt32
)nNum
[1]) << 16;
621 BigInt::operator double() const
624 return (double) nVal
;
628 double nRet
= (double) ((sal_uInt32
)nNum
[i
]);
634 nRet
+= (double) ((sal_uInt32
)nNum
[i
]);
644 BigInt
& BigInt::operator=( const BigInt
& rBigInt
)
646 if (this == &rBigInt
)
649 if ( rBigInt
.bIsBig
)
650 memcpy( (void*)this, (const void*)&rBigInt
, sizeof( BigInt
) );
653 bIsSet
= rBigInt
.bIsSet
;
660 BigInt
& BigInt::operator+=( const BigInt
& rVal
)
662 if ( !bIsBig
&& !rVal
.bIsBig
)
664 if( nVal
<= MY_MAXLONG
&& rVal
.nVal
<= MY_MAXLONG
665 && nVal
>= MY_MINLONG
&& rVal
.nVal
>= MY_MINLONG
)
666 { // No overflows may occur here
671 if( (nVal
< 0) != (rVal
.nVal
< 0) )
672 { // No overflows may occur here
679 aTmp1
.MakeBigInt( *this );
680 aTmp2
.MakeBigInt( rVal
);
681 aTmp1
.AddLong( aTmp2
, *this );
686 BigInt
& BigInt::operator-=( const BigInt
& rVal
)
688 if ( !bIsBig
&& !rVal
.bIsBig
)
690 if ( nVal
<= MY_MAXLONG
&& rVal
.nVal
<= MY_MAXLONG
&&
691 nVal
>= MY_MINLONG
&& rVal
.nVal
>= MY_MINLONG
)
692 { // No overflows may occur here
697 if ( (nVal
< 0) == (rVal
.nVal
< 0) )
698 { // No overflows may occur here
705 aTmp1
.MakeBigInt( *this );
706 aTmp2
.MakeBigInt( rVal
);
707 aTmp1
.SubLong( aTmp2
, *this );
712 BigInt
& BigInt::operator*=( const BigInt
& rVal
)
714 if ( !bIsBig
&& !rVal
.bIsBig
715 && nVal
<= MY_MAXSHORT
&& rVal
.nVal
<= MY_MAXSHORT
716 && nVal
>= MY_MINSHORT
&& rVal
.nVal
>= MY_MINSHORT
)
717 // TODO: not optimal !!! W.P.
718 { // No overflows may occur here
724 aTmp1
.MakeBigInt( rVal
);
725 aTmp2
.MakeBigInt( *this );
726 aTmp1
.MultLong(aTmp2
, *this);
732 BigInt
& BigInt::operator/=( const BigInt
& rVal
)
736 if ( rVal
.nVal
== 0 )
738 OSL_FAIL( "BigInt::operator/ --> divide by zero" );
744 // No overflows may occur here
749 if ( rVal
.nVal
== 1 )
752 if ( rVal
.nVal
== -1 )
758 if ( rVal
.nVal
<= (long)0xFFFF && rVal
.nVal
>= -(long)0xFFFF )
760 // Divide BigInt with an sal_uInt16
764 nTmp
= (sal_uInt16
) -rVal
.nVal
;
768 nTmp
= (sal_uInt16
) rVal
.nVal
;
776 if ( ABS_IsLess( rVal
) )
778 *this = BigInt( (long)0 );
782 // Divide BigInt with BigInt
784 aTmp1
.MakeBigInt( *this );
785 aTmp2
.MakeBigInt( rVal
);
786 aTmp1
.DivLong(aTmp2
, *this);
791 BigInt
& BigInt::operator%=( const BigInt
& rVal
)
795 if ( rVal
.nVal
== 0 )
797 OSL_FAIL( "BigInt::operator/ --> divide by zero" );
803 // No overflows may occur here
808 if ( rVal
.nVal
<= (long)0xFFFF && rVal
.nVal
>= -(long)0xFFFF )
810 // Divide Bigint by short
814 nTmp
= (sal_uInt16
) -rVal
.nVal
;
818 nTmp
= (sal_uInt16
) rVal
.nVal
;
821 *this = BigInt( (long)nTmp
);
826 if ( ABS_IsLess( rVal
) )
829 // Divide BigInt with BigInt
831 aTmp1
.MakeBigInt( *this );
832 aTmp2
.MakeBigInt( rVal
);
833 aTmp1
.ModLong(aTmp2
, *this);
838 bool operator==( const BigInt
& rVal1
, const BigInt
& rVal2
)
840 if ( rVal1
.bIsBig
|| rVal2
.bIsBig
)
843 nA
.MakeBigInt( rVal1
);
844 nB
.MakeBigInt( rVal2
);
845 if ( nA
.bIsNeg
== nB
.bIsNeg
)
847 if ( nA
.nLen
== nB
.nLen
)
850 for ( i
= nA
.nLen
- 1; i
> 0 && nA
.nNum
[i
] == nB
.nNum
[i
]; i
-- )
854 return nA
.nNum
[i
] == nB
.nNum
[i
];
860 return rVal1
.nVal
== rVal2
.nVal
;
863 bool operator<( const BigInt
& rVal1
, const BigInt
& rVal2
)
865 if ( rVal1
.bIsBig
|| rVal2
.bIsBig
)
868 nA
.MakeBigInt( rVal1
);
869 nB
.MakeBigInt( rVal2
);
870 if ( nA
.bIsNeg
== nB
.bIsNeg
)
872 if ( nA
.nLen
== nB
.nLen
)
875 for ( i
= nA
.nLen
- 1; i
> 0 && nA
.nNum
[i
] == nB
.nNum
[i
]; i
-- )
880 return nA
.nNum
[i
] > nB
.nNum
[i
];
882 return nA
.nNum
[i
] < nB
.nNum
[i
];
885 return nA
.nLen
> nB
.nLen
;
887 return nA
.nLen
< nB
.nLen
;
891 return rVal1
.nVal
< rVal2
.nVal
;
894 bool operator >(const BigInt
& rVal1
, const BigInt
& rVal2
)
896 if ( rVal1
.bIsBig
|| rVal2
.bIsBig
)
899 nA
.MakeBigInt( rVal1
);
900 nB
.MakeBigInt( rVal2
);
901 if ( nA
.bIsNeg
== nB
.bIsNeg
)
903 if ( nA
.nLen
== nB
.nLen
)
906 for ( i
= nA
.nLen
- 1; i
> 0 && nA
.nNum
[i
] == nB
.nNum
[i
]; i
-- )
911 return nA
.nNum
[i
] < nB
.nNum
[i
];
913 return nA
.nNum
[i
] > nB
.nNum
[i
];
916 return nA
.nLen
< nB
.nLen
;
918 return nA
.nLen
> nB
.nLen
;
923 return rVal1
.nVal
> rVal2
.nVal
;
926 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */