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

Generated by: LCOV version 1.11