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 .
22 #include <osl/diagnose.h>
23 #include <tools/bigint.hxx>
29 * The range in which we can perform add/sub without fear of overflow
31 static const sal_Int32 MY_MAXLONG
= 0x3fffffff;
32 static const sal_Int32 MY_MINLONG
= -MY_MAXLONG
;
35 * The algorithms for Addition, Subtraction, Multiplication and Division
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.
41 // TODO: Needs conversion to sal_uInt16/INT16/sal_uInt32/sal_Int32
42 void BigInt::MakeBigInt( const BigInt
& rVal
)
46 memcpy( static_cast<void*>(this), static_cast<const void*>(&rVal
), sizeof( BigInt
) );
47 while ( nLen
> 1 && nNum
[nLen
-1] == 0 )
58 nTmp
= -static_cast<sal_Int64
>(nVal
);
66 nNum
[0] = static_cast<sal_uInt16
>(nTmp
& 0xffffL
);
67 nNum
[1] = static_cast<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
= (static_cast<sal_Int32
>(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
= static_cast<sal_uInt32
>(rVal
.nNum
[i
]) * static_cast<sal_uInt32
>(nMul
) + nK
;
111 nK
= static_cast<sal_uInt16
>(nTmp
>> 16);
112 nNum
[i
] = static_cast<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
= static_cast<sal_uInt32
>(nNum
[i
]) + (nK
<< 16);
133 nNum
[i
] = static_cast<sal_uInt16
>(nTmp
/ nDiv
);
136 rRem
= static_cast<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
= static_cast<sal_Int32
>(nNum
[i
]) + static_cast<sal_Int32
>(rB
.nNum
[i
]) + k
;
187 rErg
.nNum
[i
] = static_cast<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
= static_cast<sal_Int32
>(nNum
[i
]) - static_cast<sal_Int32
>(rB
.nNum
[i
]) + k
;
247 rErg
.nNum
[i
] = static_cast<sal_uInt16
>(nZ
& 0xffffL
);
249 rErg
.bIsNeg
= bIsNeg
;
253 for (i
= 0, k
= 0; i
< len
; i
++)
255 nZ
= static_cast<sal_Int32
>(rB
.nNum
[i
]) - static_cast<sal_Int32
>(nNum
[i
]) + k
;
260 rErg
.nNum
[i
] = static_cast<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
= static_cast<sal_uInt32
>(nNum
[i
]) * static_cast<sal_uInt32
>(rB
.nNum
[j
]) +
302 static_cast<sal_uInt32
>(rErg
.nNum
[i
+ j
]) + k
;
303 rErg
.nNum
[i
+ j
] = static_cast<sal_uInt16
>(nZ
& 0xffffU
);
306 rErg
.nNum
[i
+ j
] = static_cast<sal_uInt16
>(k
);
310 void BigInt::DivLong( const BigInt
& rB
, BigInt
& rErg
) const
313 sal_uInt16 nK
, nQ
, nMult
;
314 sal_uInt16 nLenB
= rB
.nLen
;
315 sal_uInt16 nLenB1
= rB
.nLen
- 1;
318 nMult
= static_cast<sal_uInt16
>(0x10000L
/ (static_cast<sal_Int32
>(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 sal_uInt32 nTmp
= ( static_cast<sal_uInt32
>(aTmpA
.nNum
[j
]) << 16 ) + aTmpA
.nNum
[j
- 1];
332 if (aTmpA
.nNum
[j
] == aTmpB
.nNum
[nLenB1
])
335 nQ
= static_cast<sal_uInt16
>(nTmp
/ aTmpB
.nNum
[nLenB1
]);
337 if ( (static_cast<sal_uInt32
>(aTmpB
.nNum
[nLenB1
- 1]) * nQ
) >
338 ((nTmp
- static_cast<sal_uInt32
>(aTmpB
.nNum
[nLenB1
]) * nQ
) << 16) + aTmpA
.nNum
[j
- 2])
342 for (i
= 0; i
< nLenB
; i
++)
344 nTmp
= static_cast<sal_uInt32
>(aTmpA
.nNum
[j
- nLenB
+ i
])
345 - (static_cast<sal_uInt32
>(aTmpB
.nNum
[i
]) * nQ
)
347 aTmpA
.nNum
[j
- nLenB
+ i
] = static_cast<sal_uInt16
>(nTmp
);
348 nK
= static_cast<sal_uInt16
>(nTmp
>> 16);
350 nK
= static_cast<sal_uInt16
>(0x10000U
- nK
);
352 sal_uInt16
& rNum( aTmpA
.nNum
[j
- nLenB
+ i
] );
354 if (aTmpA
.nNum
[j
- nLenB
+ i
] == 0)
355 rErg
.nNum
[j
- nLenB
] = nQ
;
358 rErg
.nNum
[j
- nLenB
] = nQ
- 1;
360 for (i
= 0; i
< nLenB
; i
++)
362 nTmp
= aTmpA
.nNum
[j
- nLenB
+ i
] + aTmpB
.nNum
[i
] + nK
;
363 aTmpA
.nNum
[j
- nLenB
+ i
] = static_cast<sal_uInt16
>(nTmp
& 0xFFFFL
);
364 if (nTmp
& 0xFFFF0000L
)
372 rErg
.bIsNeg
= bIsNeg
!= rB
.bIsNeg
;
374 rErg
.nLen
= nLen
- rB
.nLen
+ 1;
377 void BigInt::ModLong( const BigInt
& rB
, BigInt
& rErg
) const
380 sal_uInt16 nK
, nQ
, nMult
;
381 sal_Int16 nLenB
= rB
.nLen
;
382 sal_Int16 nLenB1
= rB
.nLen
- 1;
385 nMult
= static_cast<sal_uInt16
>(0x10000L
/ (static_cast<sal_Int32
>(rB
.nNum
[nLenB1
]) + 1));
387 aTmpA
.Mult( *this, nMult
);
388 if ( aTmpA
.nLen
== nLen
)
390 aTmpA
.nNum
[aTmpA
.nLen
] = 0;
394 aTmpB
.Mult( rB
, nMult
);
396 for (j
= aTmpA
.nLen
- 1; j
>= nLenB
; j
--)
398 sal_uInt32 nTmp
= ( static_cast<sal_uInt32
>(aTmpA
.nNum
[j
]) << 16 ) + aTmpA
.nNum
[j
- 1];
399 if (aTmpA
.nNum
[j
] == aTmpB
.nNum
[nLenB1
])
402 nQ
= static_cast<sal_uInt16
>(nTmp
/ aTmpB
.nNum
[nLenB1
]);
404 if ( (static_cast<sal_uInt32
>(aTmpB
.nNum
[nLenB1
- 1]) * nQ
) >
405 ((nTmp
- aTmpB
.nNum
[nLenB1
] * nQ
) << 16) + aTmpA
.nNum
[j
- 2])
409 for (i
= 0; i
< nLenB
; i
++)
411 nTmp
= static_cast<sal_uInt32
>(aTmpA
.nNum
[j
- nLenB
+ i
])
412 - (static_cast<sal_uInt32
>(aTmpB
.nNum
[i
]) * nQ
)
414 aTmpA
.nNum
[j
- nLenB
+ i
] = static_cast<sal_uInt16
>(nTmp
);
415 nK
= static_cast<sal_uInt16
>(nTmp
>> 16);
417 nK
= static_cast<sal_uInt16
>(0x10000U
- nK
);
419 sal_uInt16
& rNum( aTmpA
.nNum
[j
- nLenB
+ i
] );
421 if (aTmpA
.nNum
[j
- nLenB
+ i
] == 0)
422 rErg
.nNum
[j
- nLenB
] = nQ
;
425 rErg
.nNum
[j
- nLenB
] = nQ
- 1;
427 for (i
= 0; i
< nLenB
; i
++) {
428 nTmp
= aTmpA
.nNum
[j
- nLenB
+ i
] + aTmpB
.nNum
[i
] + nK
;
429 aTmpA
.nNum
[j
- nLenB
+ i
] = static_cast<sal_uInt16
>(nTmp
& 0xFFFFL
);
430 if (nTmp
& 0xFFFF0000L
)
439 rErg
.Div( nMult
, nQ
);
442 bool BigInt::ABS_IsLess( const BigInt
& rB
) const
444 if (bIsBig
|| rB
.bIsBig
)
447 nA
.MakeBigInt( *this );
449 if (nA
.nLen
== nB
.nLen
)
452 for (i
= nA
.nLen
- 1; i
> 0 && nA
.nNum
[i
] == nB
.nNum
[i
]; i
--)
455 return nA
.nNum
[i
] < nB
.nNum
[i
];
458 return nA
.nLen
< nB
.nLen
;
462 return nVal
> rB
.nVal
;
464 return nVal
> -rB
.nVal
;
467 return nVal
< -rB
.nVal
;
469 return nVal
< rB
.nVal
;
472 BigInt::BigInt( const BigInt
& rBigInt
)
476 if ( rBigInt
.bIsBig
)
477 memcpy( static_cast<void*>(this), static_cast<const void*>(&rBigInt
), sizeof( BigInt
) );
480 bIsSet
= rBigInt
.bIsSet
;
486 BigInt::BigInt( const OUString
& rString
)
495 const sal_Unicode
* p
= rString
.getStr();
501 while( *p
>= '0' && *p
<= '9' )
513 BigInt::BigInt( double nValue
)
540 while ( ( nValue
> 65536.0 ) && ( i
< MAX_DIGITS
) )
542 nNum
[i
] = static_cast<sal_uInt16
>(fmod( nValue
, 65536.0 ));
547 if ( i
< MAX_DIGITS
)
548 nNum
[i
++] = static_cast<sal_uInt16
>(nValue
);
557 BigInt::BigInt( sal_uInt32 nValue
)
561 if ( nValue
& 0x80000000U
)
565 nNum
[0] = static_cast<sal_uInt16
>(nValue
& 0xffffU
);
566 nNum
[1] = static_cast<sal_uInt16
>(nValue
>> 16);
578 BigInt::BigInt( sal_Int64 nValue
)
585 if ((nValue
>= SAL_MIN_INT32
) && (nValue
<= SAL_MAX_INT32
))
588 nVal
= static_cast<sal_Int32
>(nValue
);
593 sal_uInt64 nUValue
= static_cast<sal_uInt64
>(bIsNeg
? -nValue
: nValue
);
594 for (int i
= 0; (i
!= sizeof(sal_uInt64
) / 2) && (nUValue
!= 0); ++i
)
596 nNum
[i
] = static_cast<sal_uInt16
>(nUValue
& 0xffffUL
);
597 nUValue
= nUValue
>> 16;
603 BigInt::operator double() const
606 return static_cast<double>(nVal
);
610 double nRet
= static_cast<double>(static_cast<sal_uInt32
>(nNum
[i
]));
616 nRet
+= static_cast<double>(static_cast<sal_uInt32
>(nNum
[i
]));
626 BigInt
& BigInt::operator=( const BigInt
& rBigInt
)
628 if (this == &rBigInt
)
631 if ( rBigInt
.bIsBig
)
632 memcpy( static_cast<void*>(this), static_cast<const void*>(&rBigInt
), sizeof( BigInt
) );
635 bIsSet
= rBigInt
.bIsSet
;
642 BigInt
& BigInt::operator+=( const BigInt
& rVal
)
644 if ( !bIsBig
&& !rVal
.bIsBig
)
646 if( nVal
<= MY_MAXLONG
&& rVal
.nVal
<= MY_MAXLONG
647 && nVal
>= MY_MINLONG
&& rVal
.nVal
>= MY_MINLONG
)
648 { // No overflows may occur here
653 if( (nVal
< 0) != (rVal
.nVal
< 0) )
654 { // No overflows may occur here
661 aTmp1
.MakeBigInt( *this );
662 aTmp2
.MakeBigInt( rVal
);
663 aTmp1
.AddLong( aTmp2
, *this );
668 BigInt
& BigInt::operator-=( const BigInt
& rVal
)
670 if ( !bIsBig
&& !rVal
.bIsBig
)
672 if ( nVal
<= MY_MAXLONG
&& rVal
.nVal
<= MY_MAXLONG
&&
673 nVal
>= MY_MINLONG
&& rVal
.nVal
>= MY_MINLONG
)
674 { // No overflows may occur here
679 if ( (nVal
< 0) == (rVal
.nVal
< 0) )
680 { // No overflows may occur here
687 aTmp1
.MakeBigInt( *this );
688 aTmp2
.MakeBigInt( rVal
);
689 aTmp1
.SubLong( aTmp2
, *this );
694 BigInt
& BigInt::operator*=( const BigInt
& rVal
)
696 static const sal_Int32 MY_MAXSHORT
= 0x00007fff;
697 static const sal_Int32 MY_MINSHORT
= -MY_MAXSHORT
;
699 if ( !bIsBig
&& !rVal
.bIsBig
700 && nVal
<= MY_MAXSHORT
&& rVal
.nVal
<= MY_MAXSHORT
701 && nVal
>= MY_MINSHORT
&& rVal
.nVal
>= MY_MINSHORT
)
702 // TODO: not optimal !!! W.P.
703 { // No overflows may occur here
709 aTmp1
.MakeBigInt( rVal
);
710 aTmp2
.MakeBigInt( *this );
711 aTmp1
.MultLong(aTmp2
, *this);
717 BigInt
& BigInt::operator/=( const BigInt
& rVal
)
721 if ( rVal
.nVal
== 0 )
723 OSL_FAIL( "BigInt::operator/ --> divide by zero" );
729 // No overflows may occur here
734 if ( rVal
.nVal
== 1 )
737 if ( rVal
.nVal
== -1 )
743 if ( rVal
.nVal
<= 0xFFFF && rVal
.nVal
>= -0xFFFF )
745 // Divide BigInt with an sal_uInt16
749 nTmp
= static_cast<sal_uInt16
>(-rVal
.nVal
);
753 nTmp
= static_cast<sal_uInt16
>(rVal
.nVal
);
761 if ( ABS_IsLess( rVal
) )
767 // Divide BigInt with BigInt
769 aTmp1
.MakeBigInt( *this );
770 aTmp2
.MakeBigInt( rVal
);
771 aTmp1
.DivLong(aTmp2
, *this);
776 BigInt
& BigInt::operator%=( const BigInt
& rVal
)
780 if ( rVal
.nVal
== 0 )
782 OSL_FAIL( "BigInt::operator/ --> divide by zero" );
788 // No overflows may occur here
793 if ( rVal
.nVal
<= 0xFFFF && rVal
.nVal
>= -0xFFFF )
795 // Divide Bigint by int16
799 nTmp
= static_cast<sal_uInt16
>(-rVal
.nVal
);
803 nTmp
= static_cast<sal_uInt16
>(rVal
.nVal
);
806 *this = BigInt( nTmp
);
811 if ( ABS_IsLess( rVal
) )
814 // Divide BigInt with BigInt
816 aTmp1
.MakeBigInt( *this );
817 aTmp2
.MakeBigInt( rVal
);
818 aTmp1
.ModLong(aTmp2
, *this);
823 bool operator==( const BigInt
& rVal1
, const BigInt
& rVal2
)
825 if ( rVal1
.bIsBig
|| rVal2
.bIsBig
)
828 nA
.MakeBigInt( rVal1
);
829 nB
.MakeBigInt( rVal2
);
830 if ( nA
.bIsNeg
== nB
.bIsNeg
)
832 if ( nA
.nLen
== nB
.nLen
)
835 for ( i
= nA
.nLen
- 1; i
> 0 && nA
.nNum
[i
] == nB
.nNum
[i
]; i
-- )
839 return nA
.nNum
[i
] == nB
.nNum
[i
];
845 return rVal1
.nVal
== rVal2
.nVal
;
848 bool operator<( const BigInt
& rVal1
, const BigInt
& rVal2
)
850 if ( rVal1
.bIsBig
|| rVal2
.bIsBig
)
853 nA
.MakeBigInt( rVal1
);
854 nB
.MakeBigInt( rVal2
);
855 if ( nA
.bIsNeg
== nB
.bIsNeg
)
857 if ( nA
.nLen
== nB
.nLen
)
860 for ( i
= nA
.nLen
- 1; i
> 0 && nA
.nNum
[i
] == nB
.nNum
[i
]; i
-- )
865 return nA
.nNum
[i
] > nB
.nNum
[i
];
867 return nA
.nNum
[i
] < nB
.nNum
[i
];
870 return nA
.nLen
> nB
.nLen
;
872 return nA
.nLen
< nB
.nLen
;
876 return rVal1
.nVal
< rVal2
.nVal
;
879 bool operator >(const BigInt
& rVal1
, const BigInt
& rVal2
)
881 if ( rVal1
.bIsBig
|| rVal2
.bIsBig
)
884 nA
.MakeBigInt( rVal1
);
885 nB
.MakeBigInt( rVal2
);
886 if ( nA
.bIsNeg
== nB
.bIsNeg
)
888 if ( nA
.nLen
== nB
.nLen
)
891 for ( i
= nA
.nLen
- 1; i
> 0 && nA
.nNum
[i
] == nB
.nNum
[i
]; i
-- )
896 return nA
.nNum
[i
] < nB
.nNum
[i
];
898 return nA
.nNum
[i
] > nB
.nNum
[i
];
901 return nA
.nLen
< nB
.nLen
;
903 return nA
.nLen
> nB
.nLen
;
908 return rVal1
.nVal
> rVal2
.nVal
;
911 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */