LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/tools/source/generic - bigint.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 221 489 45.2 %
Date: 2013-07-09 Functions: 18 27 66.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10