LCOV - code coverage report
Current view: top level - tools/source/generic - fract.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 127 203 62.6 %
Date: 2012-08-25 Functions: 13 16 81.2 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 99 304 32.6 %

           Branch data     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.h>
      21                 :            : #include <tools/debug.hxx>
      22                 :            : #include <tools/fract.hxx>
      23                 :            : #include <tools/stream.hxx>
      24                 :            : #include <tools/bigint.hxx>
      25                 :            : 
      26                 :            : /** Compute greates common divisor using Euclidian algorithm
      27                 :            : 
      28                 :            :     As the algorithm works on positive values only, the absolute value
      29                 :            :     of each parameter is used.
      30                 :            : 
      31                 :            :     @param nVal1
      32                 :            :     @param nVal2
      33                 :            : 
      34                 :            :     @note: If one parameter is {0,1}, GetGGT returns 1.
      35                 :            : */
      36                 :    6980723 : static long GetGGT( long nVal1, long nVal2 )
      37                 :            : {
      38                 :    6980723 :     nVal1 = Abs( nVal1 );
      39                 :    6980723 :     nVal2 = Abs( nVal2 );
      40                 :            : 
      41 [ +  + ][ +  + ]:    6980723 :     if ( nVal1 <= 1 || nVal2 <= 1 )
      42                 :    6057523 :         return 1;
      43                 :            : 
      44         [ +  + ]:    5931969 :     while ( nVal1 != nVal2 )
      45                 :            :     {
      46         [ +  + ]:    5870946 :         if ( nVal1 > nVal2 )
      47                 :            :         {
      48                 :    2909161 :             nVal1 %= nVal2;
      49         [ +  + ]:    2909161 :             if ( nVal1 == 0 )
      50                 :     549691 :                 return nVal2;
      51                 :            :         }
      52                 :            :         else
      53                 :            :         {
      54                 :    2961785 :             nVal2 %= nVal1;
      55         [ +  + ]:    2961785 :             if ( nVal2 == 0 )
      56                 :     312486 :                 return nVal1;
      57                 :            :         }
      58                 :            :     }
      59                 :    6980723 :     return nVal1;
      60                 :            : }
      61                 :            : 
      62                 :          0 : static void Reduce( BigInt &rVal1, BigInt &rVal2 )
      63                 :            : {
      64         [ #  # ]:          0 :     BigInt nA( rVal1 );
      65         [ #  # ]:          0 :     BigInt nB( rVal2 );
      66         [ #  # ]:          0 :     nA.Abs();
      67         [ #  # ]:          0 :     nB.Abs();
      68                 :            : 
      69 [ #  # ][ #  # ]:          0 :     if ( nA.IsOne() || nB.IsOne() || nA.IsZero() || nB.IsZero() )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
      70                 :            :         return;
      71                 :            : 
      72 [ #  # ][ #  # ]:          0 :     while ( nA != nB )
      73                 :            :     {
      74 [ #  # ][ #  # ]:          0 :         if ( nA > nB )
      75                 :            :         {
      76         [ #  # ]:          0 :             nA %= nB;
      77 [ #  # ][ #  # ]:          0 :             if ( nA.IsZero() )
      78                 :            :             {
      79         [ #  # ]:          0 :                 rVal1 /= nB;
      80         [ #  # ]:          0 :                 rVal2 /= nB;
      81                 :            :                 return;
      82                 :            :             }
      83                 :            :         }
      84                 :            :         else
      85                 :            :         {
      86         [ #  # ]:          0 :             nB %= nA;
      87 [ #  # ][ #  # ]:          0 :             if ( nB.IsZero() )
      88                 :            :             {
      89         [ #  # ]:          0 :                 rVal1 /= nA;
      90         [ #  # ]:          0 :                 rVal2 /= nA;
      91                 :            :                 return;
      92                 :            :             }
      93                 :            :         }
      94                 :            :     }
      95                 :            : 
      96         [ #  # ]:          0 :     rVal1 /= nA;
      97         [ #  # ]:          0 :     rVal2 /= nB;
      98                 :            : }
      99                 :            : 
     100                 :            : // Initialized by setting nNum as nominator and nDen as denominator
     101                 :            : // Negative values in the denominator are invalid and cause the
     102                 :            : // inversion of both nominator and denominator signs
     103                 :            : // in order to return the correct value.
     104                 :    3719577 : Fraction::Fraction( long nNum, long nDen )
     105                 :            : {
     106                 :    3719577 :     nNumerator = nNum;
     107                 :    3719577 :     nDenominator = nDen;
     108         [ +  + ]:    3719577 :     if ( nDenominator < 0 )
     109                 :            :     {
     110                 :     138982 :         nDenominator = -nDenominator;
     111                 :     138982 :         nNumerator   = -nNumerator;
     112                 :            :     }
     113                 :            : 
     114                 :            :     // Reduce through GCD
     115                 :    3719577 :     long n = GetGGT( nNumerator, nDenominator );
     116                 :    3719577 :     nNumerator   /= n;
     117                 :    3719577 :     nDenominator /= n;
     118                 :    3719577 : }
     119                 :            : 
     120                 :            : // If dVal > LONG_MAX, the fraction is set as invalid.
     121                 :            : // Otherwise, dVal and denominator are multiplied with 10, until one of them
     122                 :            : // is larger than (LONG_MAX / 10) and the fraction is reduced with GCD
     123                 :      22478 : Fraction::Fraction( double dVal )
     124                 :            : {
     125                 :      22478 :     long nDen = 1;
     126                 :      22478 :     long nMAX = LONG_MAX / 10;
     127                 :            : 
     128 [ +  - ][ -  + ]:      22478 :     if ( dVal > LONG_MAX || dVal < LONG_MIN )
     129                 :            :     {
     130                 :          0 :         nNumerator   = 0;
     131                 :          0 :         nDenominator = -1;
     132                 :      22478 :         return;
     133                 :            :     }
     134                 :            : 
     135 [ +  + ][ +  + ]:     224700 :     while ( Abs( (long)dVal ) < nMAX && nDen < nMAX )
                 [ +  + ]
     136                 :            :     {
     137                 :     202222 :         dVal *= 10;
     138                 :     202222 :         nDen *= 10;
     139                 :            :     }
     140                 :      22478 :     nNumerator   = (long)dVal;
     141                 :      22478 :     nDenominator = nDen;
     142                 :            : 
     143                 :            :     // Reduce through GCD
     144                 :      22478 :     long n = GetGGT( nNumerator, nDenominator );
     145                 :      22478 :     nNumerator   /= n;
     146                 :      22478 :     nDenominator /= n;
     147                 :            : }
     148                 :            : 
     149                 :     217814 : Fraction::operator double() const
     150                 :            : {
     151         [ +  - ]:     217814 :     if ( nDenominator > 0 )
     152                 :     217814 :         return (double)nNumerator / (double)nDenominator;
     153                 :            :     else
     154                 :     217814 :         return (double)0;
     155                 :            : }
     156                 :            : 
     157                 :            : // This methods first validates both values.
     158                 :            : // If one of the arguments is invalid, the whole operation is invalid.
     159                 :            : // For addition both fractions are extended to match the denominator,
     160                 :            : // then nominators are added and reduced (through GCD).
     161                 :            : // Internal datatype for computation is SLong to detect overflows,
     162                 :            : // which cause the operation to be marked as invalid
     163                 :          0 : Fraction& Fraction::operator += ( const Fraction& rVal )
     164                 :            : {
     165 [ #  # ][ #  # ]:          0 :     if ( !rVal.IsValid() )
     166                 :            :     {
     167                 :          0 :         nNumerator   = 0;
     168                 :          0 :         nDenominator = -1;
     169                 :            :     }
     170 [ #  # ][ #  # ]:          0 :     if ( !IsValid() )
     171                 :          0 :         return *this;
     172                 :            : 
     173                 :            :     // (a/b) + (c/d) = ( (a*d) + (c*b) ) / (b*d)
     174         [ #  # ]:          0 :     BigInt nN( nNumerator );
     175 [ #  # ][ #  # ]:          0 :     nN *= BigInt( rVal.nDenominator );
     176         [ #  # ]:          0 :     BigInt nW1Temp( nDenominator );
     177 [ #  # ][ #  # ]:          0 :     nW1Temp *= BigInt( rVal.nNumerator );
     178         [ #  # ]:          0 :     nN += nW1Temp;
     179                 :            : 
     180         [ #  # ]:          0 :     BigInt nD( nDenominator );
     181 [ #  # ][ #  # ]:          0 :     nD *= BigInt( rVal.nDenominator );
     182                 :            : 
     183         [ #  # ]:          0 :     Reduce( nN, nD );
     184                 :            : 
     185 [ #  # ][ #  # ]:          0 :     if ( nN.bIsBig || nD.bIsBig )
     186                 :            :     {
     187                 :          0 :         nNumerator   = 0;
     188                 :          0 :         nDenominator = -1;
     189                 :            :     }
     190                 :            :     else
     191                 :            :     {
     192         [ #  # ]:          0 :         nNumerator   = (long)nN,
     193         [ #  # ]:          0 :         nDenominator = (long)nD;
     194                 :            :     }
     195                 :            : 
     196                 :          0 :     return *this;
     197                 :            : }
     198                 :            : 
     199                 :            : // This methods first validates both values.
     200                 :            : // If one of the arguments is invalid, the whole operation is invalid.
     201                 :            : // For substraction, both fractions are extended to match the denominator,
     202                 :            : // then nominators are substracted and reduced (through GCD).
     203                 :            : // Internal datatype for computation is SLong to detect overflows,
     204                 :            : // which cause the operation to be marked as invalid
     205                 :          0 : Fraction& Fraction::operator -= ( const Fraction& rVal )
     206                 :            : {
     207 [ #  # ][ #  # ]:          0 :     if ( !rVal.IsValid() )
     208                 :            :     {
     209                 :          0 :         nNumerator   = 0;
     210                 :          0 :         nDenominator = -1;
     211                 :            :     }
     212 [ #  # ][ #  # ]:          0 :     if ( !IsValid() )
     213                 :          0 :         return *this;
     214                 :            : 
     215                 :            :     // (a/b) - (c/d) = ( (a*d) - (c*b) ) / (b*d)
     216         [ #  # ]:          0 :     BigInt nN( nNumerator );
     217 [ #  # ][ #  # ]:          0 :     nN *= BigInt( rVal.nDenominator );
     218         [ #  # ]:          0 :     BigInt nW1Temp( nDenominator );
     219 [ #  # ][ #  # ]:          0 :     nW1Temp *= BigInt( rVal.nNumerator );
     220         [ #  # ]:          0 :     nN -= nW1Temp;
     221                 :            : 
     222         [ #  # ]:          0 :     BigInt nD( nDenominator );
     223 [ #  # ][ #  # ]:          0 :     nD *= BigInt( rVal.nDenominator );
     224                 :            : 
     225         [ #  # ]:          0 :     Reduce( nN, nD );
     226                 :            : 
     227 [ #  # ][ #  # ]:          0 :     if ( nN.bIsBig || nD.bIsBig )
     228                 :            :     {
     229                 :          0 :         nNumerator   = 0;
     230                 :          0 :         nDenominator = -1;
     231                 :            :     }
     232                 :            :     else
     233                 :            :     {
     234         [ #  # ]:          0 :         nNumerator   = (long)nN,
     235         [ #  # ]:          0 :         nDenominator = (long)nD;
     236                 :            :     }
     237                 :            : 
     238                 :          0 :     return *this;
     239                 :            : }
     240                 :            : 
     241                 :            : // This methods first validates both values.
     242                 :            : // If one of the arguments is invalid, the whole operation is invalid.
     243                 :            : // For mutliplication, nominator and denominators are first reduced
     244                 :            : // (through GCD), and then multiplied.
     245                 :            : // Internal datatype for computation is BigInt to detect overflows,
     246                 :            : // which cause the operation to be marked as invalid
     247                 :    1615367 : Fraction& Fraction::operator *= ( const Fraction& rVal )
     248                 :            : {
     249 [ +  - ][ -  + ]:    1615367 :     if ( !rVal.IsValid() )
     250                 :            :     {
     251                 :          0 :         nNumerator   = 0;
     252                 :          0 :         nDenominator = -1;
     253                 :            :     }
     254 [ +  - ][ -  + ]:    1615367 :     if ( !IsValid() )
     255                 :          0 :         return *this;
     256                 :            : 
     257         [ +  - ]:    1615367 :     long nGGT1 = GetGGT( nNumerator, rVal.nDenominator );
     258         [ +  - ]:    1615367 :     long nGGT2 = GetGGT( rVal.nNumerator, nDenominator );
     259         [ +  - ]:    1615367 :     BigInt nN( nNumerator / nGGT1 );
     260 [ +  - ][ +  - ]:    1615367 :     nN *= BigInt( rVal.nNumerator / nGGT2 );
     261         [ +  - ]:    1615367 :     BigInt nD( nDenominator / nGGT2 );
     262 [ +  - ][ +  - ]:    1615367 :     nD *= BigInt( rVal.nDenominator / nGGT1 );
     263                 :            : 
     264 [ +  - ][ +  + ]:    1615367 :     if ( nN.bIsBig || nD.bIsBig )
     265                 :            :     {
     266                 :     119103 :         nNumerator   = 0;
     267                 :     119103 :         nDenominator = -1;
     268                 :            :     }
     269                 :            :     else
     270                 :            :     {
     271         [ +  - ]:    1496264 :         nNumerator   = (long)nN,
     272         [ +  - ]:    1496264 :         nDenominator = (long)nD;
     273                 :            :     }
     274                 :            : 
     275                 :    1615367 :     return *this;
     276                 :            : }
     277                 :            : 
     278                 :            : // This methods first validates both values.
     279                 :            : // If one of the arguments is invalid, the whole operation is invalid.
     280                 :            : // For dividing a/b, we multiply a with the inverse of b.
     281                 :            : // To avoid overflows, we first reduce both fractions with GCD.
     282                 :            : // Internal datatype for computation is BigInt to detect overflows,
     283                 :            : // which cause the operation to be marked as invalid
     284                 :       2884 : Fraction& Fraction::operator /= ( const Fraction& rVal )
     285                 :            : {
     286 [ +  - ][ -  + ]:       2884 :     if ( !rVal.IsValid() )
     287                 :            :     {
     288                 :          0 :         nNumerator   = 0;
     289                 :          0 :         nDenominator = -1;
     290                 :            :     }
     291 [ +  - ][ -  + ]:       2884 :     if ( !IsValid() )
     292                 :          0 :         return *this;
     293                 :            : 
     294         [ +  - ]:       2884 :     long nGGT1 = GetGGT( nNumerator, rVal.nNumerator );
     295         [ +  - ]:       2884 :     long nGGT2 = GetGGT( rVal.nDenominator, nDenominator );
     296         [ +  - ]:       2884 :     BigInt nN( nNumerator / nGGT1 );
     297 [ +  - ][ +  - ]:       2884 :     nN *= BigInt( rVal.nDenominator / nGGT2 );
     298         [ +  - ]:       2884 :     BigInt nD( nDenominator / nGGT2 );
     299 [ +  - ][ +  - ]:       2884 :     nD *= BigInt( rVal.nNumerator / nGGT1 );
     300                 :            : 
     301 [ +  - ][ -  + ]:       2884 :     if ( nN.bIsBig || nD.bIsBig )
     302                 :            :     {
     303                 :          0 :         nNumerator   = 0;
     304                 :          0 :         nDenominator = -1;
     305                 :            :     }
     306                 :            :     else
     307                 :            :     {
     308         [ +  - ]:       2884 :         nNumerator   = (long)nN,
     309         [ +  - ]:       2884 :         nDenominator = (long)nD;
     310         [ -  + ]:       2884 :         if ( nDenominator < 0 )
     311                 :            :         {
     312                 :          0 :             nDenominator = -nDenominator;
     313                 :          0 :             nNumerator   = -nNumerator;
     314                 :            :         }
     315                 :            :     }
     316                 :            : 
     317                 :       2884 :     return *this;
     318                 :            : }
     319                 :            : 
     320                 :            : // Similar to clz_table that can be googled
     321                 :            : const char nbits_table[32] =
     322                 :            : {
     323                 :            :     32,  1, 23,  2, 29, 24, 14,  3,
     324                 :            :     30, 27, 25, 18, 20, 15, 10,  4,
     325                 :            :     31, 22, 28, 13, 26, 17, 19,  9,
     326                 :            :     21, 12, 16,  8, 11,  7,  6,  5
     327                 :            : };
     328                 :            : 
     329                 :       4332 : static int impl_NumberOfBits( unsigned long nNum )
     330                 :            : {
     331                 :            :     // http://en.wikipedia.org/wiki/De_Bruijn_sequence
     332                 :            :     // background paper: Using de Bruijn Sequences to Index a 1 in a
     333                 :            :     // Computer Word (1998) Charles E. Leiserson,
     334                 :            :     // Harald Prokop, Keith H. Randall
     335                 :            :     // (e.g. http://citeseer.ist.psu.edu/leiserson98using.html)
     336                 :       4332 :     const sal_uInt32 nDeBruijn = 0x7DCD629;
     337                 :            : 
     338         [ -  + ]:       4332 :     if ( nNum == 0 )
     339                 :          0 :         return 0;
     340                 :            : 
     341                 :            :     // Get it to form like 0000001111111111b
     342                 :       4332 :     nNum |= ( nNum >>  1 );
     343                 :       4332 :     nNum |= ( nNum >>  2 );
     344                 :       4332 :     nNum |= ( nNum >>  4 );
     345                 :       4332 :     nNum |= ( nNum >>  8 );
     346                 :       4332 :     nNum |= ( nNum >> 16 );
     347                 :            : 
     348                 :            :     sal_uInt32 nNumber;
     349                 :       4332 :     int nBonus = 0;
     350                 :            : 
     351                 :            : #if SAL_TYPES_SIZEOFLONG == 4
     352                 :       4332 :     nNumber = nNum;
     353                 :            : #elif SAL_TYPES_SIZEOFLONG == 8
     354                 :            :     nNum |= ( nNum >> 32 );
     355                 :            : 
     356                 :            :     if ( nNum & 0x80000000 )
     357                 :            :     {
     358                 :            :         nNumber = sal_uInt32( nNum >> 32 );
     359                 :            :         nBonus = 32;
     360                 :            : 
     361                 :            :         if ( nNumber == 0 )
     362                 :            :             return 32;
     363                 :            :     }
     364                 :            :     else
     365                 :            :         nNumber = sal_uInt32( nNum & 0xFFFFFFFF );
     366                 :            : #else
     367                 :            : #error "Unknown size of long!"
     368                 :            : #endif
     369                 :            : 
     370                 :            :     // De facto shift left of nDeBruijn using multiplication (nNumber
     371                 :            :     // is all ones from topmost bit, thus nDeBruijn + (nDeBruijn *
     372                 :            :     // nNumber) => nDeBruijn * (nNumber+1) clears all those bits to
     373                 :            :     // zero, sets the next bit to one, and thus effectively shift-left
     374                 :            :     // nDeBruijn by lg2(nNumber+1). This generates a distinct 5bit
     375                 :            :     // sequence in the msb for each distinct position of the last
     376                 :            :     // leading 0 bit - that's the property of a de Bruijn number.
     377                 :       4332 :     nNumber = nDeBruijn + ( nDeBruijn * nNumber );
     378                 :            : 
     379                 :            :     // 5-bit window indexes the result
     380                 :       4332 :     return ( nbits_table[nNumber >> 27] ) + nBonus;
     381                 :            : }
     382                 :            : 
     383                 :            : /** Inaccurate cancellation for a fraction.
     384                 :            : 
     385                 :            :     Clip both nominator and denominator to said number of bits. If
     386                 :            :     either of those already have equal or less number of bits used,
     387                 :            :     this method does nothing.
     388                 :            : 
     389                 :            :     @param nSignificantBits denotes, how many significant binary
     390                 :            :     digits to maintain, in both nominator and denominator.
     391                 :            : 
     392                 :            :     @example ReduceInaccurate(8) has an error <1% [1/2^(8-1)] - the
     393                 :            :     largest error occurs with the following pair of values:
     394                 :            : 
     395                 :            :     binary    1000000011111111111111111111111b/1000000000000000000000000000000b
     396                 :            :     =         1082130431/1073741824
     397                 :            :     = approx. 1.007812499
     398                 :            : 
     399                 :            :     A ReduceInaccurate(8) yields 1/1.
     400                 :            : */
     401                 :       2166 : void Fraction::ReduceInaccurate( unsigned nSignificantBits )
     402                 :            : {
     403 [ +  - ][ -  + ]:       2166 :     if ( !nNumerator || !nDenominator )
     404                 :          0 :         return;
     405                 :            : 
     406                 :            :     // Count with unsigned longs only
     407                 :       2166 :     const bool bNeg = ( nNumerator < 0 );
     408         [ -  + ]:       2166 :     unsigned long nMul = (unsigned long)( bNeg? -nNumerator: nNumerator );
     409                 :       2166 :     unsigned long nDiv = (unsigned long)( nDenominator );
     410                 :            : 
     411                 :            :     DBG_ASSERT(nSignificantBits<65, "More than 64 bit of significance is overkill!");
     412                 :            : 
     413                 :            :     // How much bits can we lose?
     414                 :       2166 :     const int nMulBitsToLose = Max( ( impl_NumberOfBits( nMul ) - int( nSignificantBits ) ), 0 );
     415                 :       2166 :     const int nDivBitsToLose = Max( ( impl_NumberOfBits( nDiv ) - int( nSignificantBits ) ), 0 );
     416                 :            : 
     417                 :       2166 :     const int nToLose = Min( nMulBitsToLose, nDivBitsToLose );
     418                 :            : 
     419                 :            :     // Remove the bits
     420                 :       2166 :     nMul >>= nToLose;
     421                 :       2166 :     nDiv >>= nToLose;
     422                 :            : 
     423 [ -  + ][ +  - ]:       2166 :     if ( !nMul || !nDiv )
     424                 :            :     {
     425                 :            :         // Return without reduction
     426                 :            :         OSL_FAIL( "Oops, we reduced too much..." );
     427                 :          0 :         return;
     428                 :            :     }
     429                 :            : 
     430                 :            :     // Reduce
     431                 :       2166 :     long n1 = GetGGT( nMul, nDiv );
     432         [ +  + ]:       2166 :     if ( n1 != 1 )
     433                 :            :     {
     434                 :        959 :         nMul /= n1;
     435                 :        959 :         nDiv /= n1;
     436                 :            :     }
     437                 :            : 
     438         [ -  + ]:       2166 :     nNumerator = bNeg? -long( nMul ): long( nMul );
     439                 :       2166 :     nDenominator = nDiv;
     440                 :            : }
     441                 :            : 
     442                 :     199845 : bool operator == ( const Fraction& rVal1, const Fraction& rVal2 )
     443                 :            : {
     444 [ +  - ][ -  + ]:     199845 :     if ( !rVal1.IsValid() || !rVal2.IsValid() )
                 [ -  + ]
     445                 :          0 :         return false;
     446                 :            : 
     447                 :            :     return rVal1.nNumerator == rVal2.nNumerator
     448 [ +  + ][ +  + ]:     199845 :            && rVal1.nDenominator == rVal2.nDenominator;
     449                 :            : }
     450                 :            : 
     451                 :            : // This methods first validates and reduces both values.
     452                 :            : // To compare (a/b) with (c/d), extend denominators (b*d), then return
     453                 :            : // the result of comparing the nominators (a < c)
     454                 :        458 : bool operator < ( const Fraction& rVal1, const Fraction& rVal2 )
     455                 :            : {
     456 [ +  - ][ +  - ]:        458 :     if ( !rVal1.IsValid() || !rVal2.IsValid() )
         [ +  - ][ -  + ]
                 [ -  + ]
     457                 :          0 :         return false;
     458                 :            : 
     459         [ +  - ]:        458 :     BigInt nN( rVal1.nNumerator );
     460 [ +  - ][ +  - ]:        458 :     nN *= BigInt( rVal2.nDenominator );
     461         [ +  - ]:        458 :     BigInt nD( rVal1.nDenominator );
     462 [ +  - ][ +  - ]:        458 :     nD *= BigInt( rVal2.nNumerator );
     463                 :            : 
     464         [ +  - ]:        458 :     return nN < nD;
     465                 :            : }
     466                 :            : 
     467                 :            : // This methods first validates and reduces both values.
     468                 :            : // To compare (a/b) with (c/d), extend denominators (b*d), then return
     469                 :            : // the result of comparing nominators (a > c)
     470                 :        458 : bool operator > ( const Fraction& rVal1, const Fraction& rVal2 )
     471                 :            : {
     472 [ +  - ][ +  - ]:        458 :     if ( !rVal1.IsValid() || !rVal2.IsValid() )
         [ +  - ][ -  + ]
                 [ -  + ]
     473                 :          0 :         return false;
     474                 :            : 
     475         [ +  - ]:        458 :     BigInt nN( rVal1.nNumerator );
     476 [ +  - ][ +  - ]:        458 :     nN *= BigInt( rVal2.nDenominator );
     477         [ +  - ]:        458 :     BigInt nD( rVal1.nDenominator);
     478 [ +  - ][ +  - ]:        458 :     nD *= BigInt( rVal2.nNumerator );
     479                 :            : 
     480         [ +  - ]:        458 :     return nN > nD;
     481                 :            : }
     482                 :            : 
     483                 :      17690 : SvStream& operator >> ( SvStream& rIStream, Fraction& rFract )
     484                 :            : {
     485                 :            :     //fdo#39428 SvStream no longer supports operator>>(long&)
     486                 :      17690 :     sal_Int32 nTmp(0);
     487         [ +  - ]:      17690 :     rIStream >> nTmp;
     488                 :      17690 :     rFract.nNumerator = nTmp;
     489         [ +  - ]:      17690 :     rIStream >> nTmp;
     490                 :      17690 :     rFract.nDenominator = nTmp;
     491                 :      17690 :     return rIStream;
     492                 :            : }
     493                 :            : 
     494                 :      18844 : SvStream& operator << ( SvStream& rOStream, const Fraction& rFract )
     495                 :            : {
     496                 :            :     //fdo#39428 SvStream no longer supports operator<<(long)
     497                 :      18844 :     rOStream << sal::static_int_cast<sal_Int32>(rFract.nNumerator);
     498                 :      18844 :     rOStream << sal::static_int_cast<sal_Int32>(rFract.nDenominator);
     499                 :      18844 :     return rOStream;
     500                 :            : }
     501                 :            : 
     502                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10