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 <tools/tools.h>
23 #include <tools/bigint.hxx>
24 #include <tools/string.hxx>
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
;
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.
41 // TODO: Needs conversion to sal_uInt16/INT16/sal_uInt32/sal_Int32
42 void BigInt::MakeBigInt( const BigInt
& rVal
)
46 memcpy( (void*)this, (const void*)&rVal
, sizeof( BigInt
) );
47 while ( nLen
> 1 && nNum
[nLen
-1] == 0 )
52 long nTmp
= rVal
.nVal
;
64 nNum
[0] = (sal_uInt16
)(nTmp
& 0xffffL
);
65 nNum
[1] = (sal_uInt16
)(nTmp
>> 16);
66 if ( nTmp
& 0xffff0000L
)
73 void BigInt::Normalize()
77 while ( nLen
> 1 && nNum
[nLen
-1] == 0 )
84 else if ( nNum
[1] & 0x8000 )
87 nVal
= ((long)nNum
[1] << 16) + nNum
[0];
94 // else nVal is undefined !!! W.P.
96 // why? nVal is undefined ??? W.P.
97 else if ( nVal
& 0xFFFF0000L
)
103 void BigInt::Mult( const BigInt
&rVal
, sal_uInt16 nMul
)
106 for ( int i
= 0; i
< rVal
.nLen
; i
++ )
108 sal_uInt32 nTmp
= (sal_uInt32
)rVal
.nNum
[i
] * (sal_uInt32
)nMul
+ nK
;
109 nK
= (sal_uInt16
)(nTmp
>> 16);
110 nNum
[i
] = (sal_uInt16
)nTmp
;
115 nNum
[rVal
.nLen
] = nK
;
116 nLen
= rVal
.nLen
+ 1;
122 bIsNeg
= rVal
.bIsNeg
;
125 void BigInt::Div( sal_uInt16 nDiv
, sal_uInt16
& rRem
)
128 for ( int i
= nLen
- 1; i
>= 0; i
-- )
130 sal_uInt32 nTmp
= (sal_uInt32
)nNum
[i
] + (nK
<< 16);
131 nNum
[i
] = (sal_uInt16
)(nTmp
/ nDiv
);
134 rRem
= (sal_uInt16
)nK
;
136 if ( nNum
[nLen
-1] == 0 )
140 sal_Bool
BigInt::IsLess( const BigInt
& rVal
) const
142 if ( rVal
.nLen
< nLen
)
144 if ( rVal
.nLen
> nLen
)
148 for ( i
= nLen
- 1; i
> 0 && nNum
[i
] == rVal
.nNum
[i
]; i
-- )
151 return rVal
.nNum
[i
] < nNum
[i
];
154 void BigInt::AddLong( BigInt
& rB
, BigInt
& rErg
)
156 if ( bIsNeg
== rB
.bIsNeg
)
161 // if length of the two values differ, fill remaining positions
162 // of the smaller value with zeros.
166 for (i
= rB
.nLen
; i
< len
; i
++)
172 for (i
= nLen
; i
< len
; i
++)
176 // Add numerals, starting from the back
179 for (i
= 0, k
= 0; i
< len
; i
++) {
180 nZ
= (long)nNum
[i
] + (long)rB
.nNum
[i
] + k
;
185 rErg
.nNum
[i
] = (sal_uInt16
)(nZ
& 0xffffL
);
187 // If an overflow occurred, add to solution
188 if (nZ
& 0xff0000L
) // or if(k)
193 // Set length and sign
195 rErg
.bIsNeg
= bIsNeg
&& rB
.bIsNeg
;
196 rErg
.bIsBig
= sal_True
;
198 // If one of the values is negative, perform substraction instead
202 rB
.SubLong(*this, rErg
);
207 rB
.bIsNeg
= sal_False
;
209 rB
.bIsNeg
= sal_True
;
213 void BigInt::SubLong( BigInt
& rB
, BigInt
& rErg
)
215 if ( bIsNeg
== rB
.bIsNeg
)
221 // if length of the two values differ, fill remaining positions
222 // of the smaller value with zeros.
226 for (i
= rB
.nLen
; i
< len
; i
++)
232 for (i
= nLen
; i
< len
; i
++)
238 for (i
= 0, k
= 0; i
< len
; i
++)
240 nZ
= (long)nNum
[i
] - (long)rB
.nNum
[i
] + k
;
245 rErg
.nNum
[i
] = (sal_uInt16
)(nZ
& 0xffffL
);
247 rErg
.bIsNeg
= bIsNeg
;
251 for (i
= 0, k
= 0; i
< len
; i
++)
253 nZ
= (long)rB
.nNum
[i
] - (long)nNum
[i
] + k
;
258 rErg
.nNum
[i
] = (sal_uInt16
)(nZ
& 0xffffL
);
260 // if a < b, revert sign
261 rErg
.bIsNeg
= !bIsNeg
;
264 rErg
.bIsBig
= sal_True
;
266 // If one of the values is negative, perform addition instead
272 rErg
.bIsNeg
= sal_True
;
276 rB
.bIsNeg
= sal_False
;
278 rB
.bIsNeg
= sal_True
;
279 rErg
.bIsNeg
= sal_False
;
283 void BigInt::MultLong( const BigInt
& rB
, BigInt
& rErg
) const
288 rErg
.bIsNeg
= bIsNeg
!= rB
.bIsNeg
;
289 rErg
.bIsBig
= sal_True
;
290 rErg
.nLen
= nLen
+ rB
.nLen
;
292 for (i
= 0; i
< rErg
.nLen
; i
++)
295 for (j
= 0; j
< rB
.nLen
; j
++)
297 for (i
= 0, k
= 0; i
< nLen
; i
++)
299 nZ
= (sal_uInt32
)nNum
[i
] * (sal_uInt32
)rB
.nNum
[j
] +
300 (sal_uInt32
)rErg
.nNum
[i
+ j
] + k
;
301 rErg
.nNum
[i
+ j
] = (sal_uInt16
)(nZ
& 0xffffUL
);
304 rErg
.nNum
[i
+ j
] = (sal_uInt16
)k
;
308 void BigInt::DivLong( const BigInt
& rB
, BigInt
& rErg
) const
312 sal_uInt16 nK
, nQ
, nMult
;
313 short nLenB
= rB
.nLen
;
314 short nLenB1
= rB
.nLen
- 1;
317 nMult
= (sal_uInt16
)(0x10000L
/ ((long)rB
.nNum
[nLenB1
] + 1));
319 aTmpA
.Mult( *this, nMult
);
320 if ( aTmpA
.nLen
== nLen
)
322 aTmpA
.nNum
[aTmpA
.nLen
] = 0;
326 aTmpB
.Mult( rB
, nMult
);
328 for (j
= aTmpA
.nLen
- 1; j
>= nLenB
; j
--)
330 nTmp
= ( (long)aTmpA
.nNum
[j
] << 16 ) + aTmpA
.nNum
[j
- 1];
331 if (aTmpA
.nNum
[j
] == aTmpB
.nNum
[nLenB1
])
334 nQ
= (sal_uInt16
)(((sal_uInt32
)nTmp
) / aTmpB
.nNum
[nLenB1
]);
336 if ( ((sal_uInt32
)aTmpB
.nNum
[nLenB1
- 1] * nQ
) >
337 ((((sal_uInt32
)nTmp
) - aTmpB
.nNum
[nLenB1
] * nQ
) << 16) + aTmpA
.nNum
[j
- 2])
342 for (i
= 0; i
< nLenB
; i
++)
344 nTmp
= (long)aTmpA
.nNum
[j
- nLenB
+ i
]
345 - ((long)aTmpB
.nNum
[i
] * nQ
)
347 aTmpA
.nNum
[j
- nLenB
+ i
] = (sal_uInt16
)nTmp
;
348 nK
= (sal_uInt16
) (nTmp
>> 16);
350 nK
= (sal_uInt16
)(0x10000UL
- nK
);
352 unsigned short& rNum( aTmpA
.nNum
[j
- nLenB
+ i
] );
353 rNum
= rNum
- nK
; // MSVC yields a warning on -= here, so don't use it
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
] = (sal_uInt16
)(nTmp
& 0xFFFFL
);
364 if (nTmp
& 0xFFFF0000L
)
372 rErg
.bIsNeg
= bIsNeg
!= rB
.bIsNeg
;
373 rErg
.bIsBig
= sal_True
;
374 rErg
.nLen
= nLen
- rB
.nLen
+ 1;
377 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 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 sal_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
)
476 if ( rBigInt
.bIsBig
)
477 memcpy( (void*)this, (const void*)&rBigInt
, sizeof( BigInt
) );
480 bIsSet
= rBigInt
.bIsSet
;
486 BigInt::BigInt( const OUString
& rString
)
493 sal_Bool bNeg
= sal_False
;
494 const sal_Unicode
* p
= rString
.getStr();
500 while( *p
>= '0' && *p
<= '9' )
512 BigInt::BigInt( double nValue
)
537 while ( ( nValue
> 65536.0 ) && ( i
< MAX_DIGITS
) )
539 nNum
[i
] = (sal_uInt16
) fmod( nValue
, 65536.0 );
544 if ( i
< MAX_DIGITS
)
545 nNum
[i
++] = (sal_uInt16
) nValue
;
554 BigInt::BigInt( sal_uInt32 nValue
)
557 if ( nValue
& 0x80000000UL
)
561 nNum
[0] = (sal_uInt16
)(nValue
& 0xffffUL
);
562 nNum
[1] = (sal_uInt16
)(nValue
>> 16);
572 BigInt::operator sal_uIntPtr() const
575 return (sal_uInt32
)nVal
;
576 else if ( nLen
== 2 )
579 nRet
= ((sal_uInt32
)nNum
[1]) << 16;
586 BigInt::operator double() const
589 return (double) nVal
;
593 double nRet
= (double) ((sal_uInt32
)nNum
[i
]);
599 nRet
+= (double) ((sal_uInt32
)nNum
[i
]);
609 OUString
BigInt::GetString() const
614 aString
= OUString::number( nVal
);
617 BigInt
aTmp( *this );
618 BigInt
a1000000000( 1000000000L );
627 String aStr
= aString
;
628 if ( a
.nVal
< 100000000L )
630 aString
= OUString::number( a
.nVal
+ 1000000000L );
634 aString
= OUString::number( a
.nVal
);
637 while( aTmp
.bIsBig
);
639 String aStr
= aString
;
641 aString
= OUString::number( -aTmp
.nVal
);
643 aString
= OUString::number( aTmp
.nVal
);
650 BigInt
& BigInt::operator=( const BigInt
& rBigInt
)
652 if ( rBigInt
.bIsBig
)
653 memcpy( (void*)this, (const void*)&rBigInt
, sizeof( BigInt
) );
656 bIsSet
= rBigInt
.bIsSet
;
663 BigInt
& BigInt::operator+=( const BigInt
& rVal
)
665 if ( !bIsBig
&& !rVal
.bIsBig
)
667 if( nVal
<= MY_MAXLONG
&& rVal
.nVal
<= MY_MAXLONG
668 && nVal
>= MY_MINLONG
&& rVal
.nVal
>= MY_MINLONG
)
669 { // No overflows may occur here
674 if( (nVal
< 0) != (rVal
.nVal
< 0) )
675 { // No overflows may occur here
682 aTmp1
.MakeBigInt( *this );
683 aTmp2
.MakeBigInt( rVal
);
684 aTmp1
.AddLong( aTmp2
, *this );
689 BigInt
& BigInt::operator-=( const BigInt
& rVal
)
691 if ( !bIsBig
&& !rVal
.bIsBig
)
693 if ( nVal
<= MY_MAXLONG
&& rVal
.nVal
<= MY_MAXLONG
&&
694 nVal
>= MY_MINLONG
&& rVal
.nVal
>= MY_MINLONG
)
695 { // No overflows may occur here
700 if ( (nVal
< 0) == (rVal
.nVal
< 0) )
701 { // No overflows may occur here
708 aTmp1
.MakeBigInt( *this );
709 aTmp2
.MakeBigInt( rVal
);
710 aTmp1
.SubLong( aTmp2
, *this );
715 BigInt
& BigInt::operator*=( const BigInt
& rVal
)
717 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
727 aTmp1
.MakeBigInt( rVal
);
728 aTmp2
.MakeBigInt( *this );
729 aTmp1
.MultLong(aTmp2
, *this);
735 BigInt
& BigInt::operator/=( const BigInt
& rVal
)
739 if ( rVal
.nVal
== 0 )
741 OSL_FAIL( "BigInt::operator/ --> divide by zero" );
747 // No overflows may occur here
752 if ( rVal
.nVal
== 1 )
755 if ( rVal
.nVal
== -1 )
761 if ( rVal
.nVal
<= (long)0xFFFF && rVal
.nVal
>= -(long)0xFFFF )
763 // Divide BigInt with an sal_uInt16
767 nTmp
= (sal_uInt16
) -rVal
.nVal
;
771 nTmp
= (sal_uInt16
) rVal
.nVal
;
779 if ( ABS_IsLess( rVal
) )
781 *this = BigInt( (long)0 );
785 // Divide BigInt with BigInt
787 aTmp1
.MakeBigInt( *this );
788 aTmp2
.MakeBigInt( rVal
);
789 aTmp1
.DivLong(aTmp2
, *this);
794 BigInt
& BigInt::operator%=( const BigInt
& rVal
)
798 if ( rVal
.nVal
== 0 )
800 OSL_FAIL( "BigInt::operator/ --> divide by zero" );
806 // No overflows may occur here
811 if ( rVal
.nVal
<= (long)0xFFFF && rVal
.nVal
>= -(long)0xFFFF )
813 // Divide Bigint by short
817 nTmp
= (sal_uInt16
) -rVal
.nVal
;
821 nTmp
= (sal_uInt16
) rVal
.nVal
;
824 *this = BigInt( (long)nTmp
);
829 if ( ABS_IsLess( rVal
) )
832 // Divide BigInt with BigInt
834 aTmp1
.MakeBigInt( *this );
835 aTmp2
.MakeBigInt( rVal
);
836 aTmp1
.ModLong(aTmp2
, *this);
841 sal_Bool
operator==( const BigInt
& rVal1
, const BigInt
& rVal2
)
843 if ( rVal1
.bIsBig
|| rVal2
.bIsBig
)
846 nA
.MakeBigInt( rVal1
);
847 nB
.MakeBigInt( rVal2
);
848 if ( nA
.bIsNeg
== nB
.bIsNeg
)
850 if ( nA
.nLen
== nB
.nLen
)
853 for ( i
= nA
.nLen
- 1; i
> 0 && nA
.nNum
[i
] == nB
.nNum
[i
]; i
-- )
857 return nA
.nNum
[i
] == nB
.nNum
[i
];
863 return rVal1
.nVal
== rVal2
.nVal
;
866 sal_Bool
operator<( const BigInt
& rVal1
, const BigInt
& rVal2
)
868 if ( rVal1
.bIsBig
|| rVal2
.bIsBig
)
871 nA
.MakeBigInt( rVal1
);
872 nB
.MakeBigInt( rVal2
);
873 if ( nA
.bIsNeg
== nB
.bIsNeg
)
875 if ( nA
.nLen
== nB
.nLen
)
878 for ( i
= nA
.nLen
- 1; i
> 0 && nA
.nNum
[i
] == nB
.nNum
[i
]; i
-- )
883 return nA
.nNum
[i
] > nB
.nNum
[i
];
885 return nA
.nNum
[i
] < nB
.nNum
[i
];
888 return nA
.nLen
> nB
.nLen
;
890 return nA
.nLen
< nB
.nLen
;
894 return rVal1
.nVal
< rVal2
.nVal
;
897 sal_Bool
operator >(const BigInt
& rVal1
, const BigInt
& rVal2
)
899 if ( rVal1
.bIsBig
|| rVal2
.bIsBig
)
902 nA
.MakeBigInt( rVal1
);
903 nB
.MakeBigInt( rVal2
);
904 if ( nA
.bIsNeg
== nB
.bIsNeg
)
906 if ( nA
.nLen
== nB
.nLen
)
909 for ( i
= nA
.nLen
- 1; i
> 0 && nA
.nNum
[i
] == nB
.nNum
[i
]; i
-- )
914 return nA
.nNum
[i
] < nB
.nNum
[i
];
916 return nA
.nNum
[i
] > nB
.nNum
[i
];
919 return nA
.nLen
< nB
.nLen
;
921 return nA
.nLen
> nB
.nLen
;
926 return rVal1
.nVal
> rVal2
.nVal
;
929 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */