25#include <osl/diagnose.h> 
   31#include <boost/rational.hpp> 
   41static boost::rational<sal_Int32> 
toRational(sal_Int32 n, sal_Int32 d)
 
   47    if (
d < -std::numeric_limits<sal_Int32>::max())
 
   49    return boost::rational<sal_Int32>(
n, 
d);
 
   54    return nNum < std::numeric_limits<sal_Int32>::min()
 
   55            || nNum > std::numeric_limits<sal_Int32>::max();
 
   63        if (
const auto gcd = std::gcd(nNum, nDen); gcd > 1)
 
   69                    "tools.fraction", 
"values outside of range we can represent, doing reduction, which will reduce precision");
 
   81        SAL_WARN( 
"tools.fraction", 
"'Fraction(" << nNum << 
",0)' invalid fraction created" );
 
   84    else if ((nDen == -1 && nNum == std::numeric_limits<sal_Int32>::min()) ||
 
   85            (nNum == -1 && nDen == std::numeric_limits<sal_Int32>::min()))
 
   88        SAL_WARN(
"tools.fraction", 
"'Fraction(" << nNum << 
"," << nDen << 
")' invalid fraction created");
 
   97    : 
Fraction(sal_Int64(nNum), sal_Int64(nDen))
 
  108    catch (
const boost::bad_rational&)
 
  111        SAL_WARN( 
"tools.fraction", 
"'Fraction(" << dVal << 
")' invalid fraction created" );
 
  115Fraction::operator double()
 const 
  119        SAL_WARN( 
"tools.fraction", 
"'double()' on invalid fraction" );
 
  123    return boost::rational_cast<double>(
toRational(mnNumerator, mnDenominator));
 
  137        SAL_WARN( 
"tools.fraction", 
"'operator +=' with invalid fraction" );
 
  156        SAL_WARN( 
"tools.fraction", 
"'operator -=' with invalid fraction" );
 
  170    bool checked_multiply_by(boost::rational<sal_Int32>& i, 
const boost::rational<sal_Int32>& r)
 
  173        sal_Int32 num = r.numerator();
 
  174        sal_Int32 den = r.denominator();
 
  186        sal_Int32 gcd1 = std::gcd(
i.numerator(), den);
 
  187        sal_Int32 gcd2 = std::gcd(num, 
i.denominator());
 
  210        SAL_WARN( 
"tools.fraction", 
"'operator *=' with invalid fraction" );
 
  216    bool bFail = checked_multiply_by(
a, b);
 
  235        SAL_WARN( 
"tools.fraction", 
"'operator /=' with invalid fraction" );
 
  269        SAL_WARN( 
"tools.fraction", 
"'ReduceInaccurate' on invalid fraction" );
 
  286        SAL_WARN( 
"tools.fraction", 
"'GetNumerator()' on invalid fraction" );
 
  296        SAL_WARN( 
"tools.fraction", 
"'GetDenominator()' on invalid fraction" );
 
  302Fraction::operator sal_Int32()
 const 
  306        SAL_WARN( 
"tools.fraction", 
"'operator sal_Int32()' on invalid fraction" );
 
  309    return boost::rational_cast<sal_Int32>(
toRational(mnNumerator, mnDenominator));
 
  342    return !(rVal1 == rVal2);
 
  347    return !(rVal1 > rVal2);
 
  352    return !(rVal1 < rVal2);
 
  359        SAL_WARN( 
"tools.fraction", 
"'operator ==' with an invalid fraction" );
 
  370        SAL_WARN( 
"tools.fraction", 
"'operator <' with an invalid fraction" );
 
  381        SAL_WARN( 
"tools.fraction", 
"'operator >' with an invalid fraction" );
 
  395    if ( dVal > std::numeric_limits<sal_Int32>::max() ||
 
  396         dVal < std::numeric_limits<sal_Int32>::min() ||
 
  398        throw boost::bad_rational();
 
  400    const sal_Int32 nMAX = std::numeric_limits<sal_Int32>::max() / 10;
 
  402    while ( 
std::abs( dVal ) < nMAX && nDen < nMAX ) {
 
  406    return boost::rational<sal_Int32>( sal_Int32(dVal), nDen );
 
  418    _BitScanReverse(&r, nNum);
 
  421    return 32 - __builtin_clz(nNum);
 
  449    sal_Int32 nMul = rRational.numerator();
 
  450    if (nMul == std::numeric_limits<sal_Int32>::min())
 
  455    const bool bNeg = nMul < 0;
 
  458    sal_Int32 nDiv = rRational.denominator();
 
  460    DBG_ASSERT(nSignificantBits<65, 
"More than 64 bit of significance is overkill!");
 
  463    const int nMulBitsToLose = std::max( ( 
impl_NumberOfBits( nMul ) - 
int( nSignificantBits ) ), 0 );
 
  464    const int nDivBitsToLose = std::max( ( 
impl_NumberOfBits( nDiv ) - 
int( nSignificantBits ) ), 0 );
 
  466    const int nToLose = std::min( nMulBitsToLose, nDivBitsToLose );
 
  472    if ( !nMul || !nDiv ) {
 
  474        OSL_FAIL( 
"Oops, we reduced too much..." );
 
  478    rRational.assign( bNeg ? -nMul : nMul, nDiv );
 
  492    if( nD1 == 0 || nD2 == 0 ) 
 
  494        SAL_WARN(
"tools.fraction", 
"Invalid parameter for ImplMakeFraction");
 
  500    if ( nN1 < 0 ) { 
i = -
i; nN1 = -nN1; }
 
  501    if ( nN2 < 0 ) { 
i = -
i; nN2 = -nN2; }
 
  502    if ( nD1 < 0 ) { 
i = -
i; nD1 = -nD1; }
 
  503    if ( nD2 < 0 ) { 
i = -
i; nD2 = -nD2; }
 
  506    assert( nN1 >= std::numeric_limits<sal_Int32>::min() );
 
  507    assert( nN1 <= std::numeric_limits<sal_Int32>::max( ));
 
  508    assert( nD1 >= std::numeric_limits<sal_Int32>::min() );
 
  509    assert( nD1 <= std::numeric_limits<sal_Int32>::max( ));
 
  510    assert( nN2 >= std::numeric_limits<sal_Int32>::min() );
 
  511    assert( nN2 <= std::numeric_limits<sal_Int32>::max( ));
 
  512    assert( nD2 >= std::numeric_limits<sal_Int32>::min() );
 
  513    assert( nD2 <= std::numeric_limits<sal_Int32>::max( ));
 
  516    boost::rational<sal_Int32> b = 
toRational(nN2, nD2);
 
  517    bool bFail = checked_multiply_by(
a, b);
 
  531        bFail = checked_multiply_by(
a, b);
 
  534    return Fraction(
a.numerator(), 
a.denominator());
 
sal_Int32 GetNumerator() const
 
static Fraction MakeFraction(tools::Long nN1, tools::Long nN2, tools::Long nD1, tools::Long nD2)
Multiply the two fractions represented here and reduce inaccuracy to 32-bits, used by vcl.
 
void ReduceInaccurate(unsigned nSignificantBits)
 
Fraction & operator+=(const Fraction &rfrFrac)
 
Fraction & operator*=(const Fraction &rfrFrac)
 
sal_Int32 mnNumerator
these two fields form a boost::rational, but I didn't want to put more boost headers into the global ...
 
sal_Int32 GetDenominator() const
 
size_t GetHashValue() const
 
Fraction & operator/=(const Fraction &rfrFrac)
 
Fraction & operator-=(const Fraction &rfrFrac)
 
#define DBG_ASSERT(sCon, aError)
 
Degree100 abs(Degree100 x)
 
static int impl_NumberOfBits(sal_uInt32 nNum)
Find the number of bits required to represent this number, using the CLZ intrinsic.
 
Fraction operator-(const Fraction &rVal1, const Fraction &rVal2)
 
static boost::rational< sal_Int32 > rational_FromDouble(double dVal)
 
Fraction operator/(const Fraction &rVal1, const Fraction &rVal2)
 
bool operator>(const Fraction &rVal1, const Fraction &rVal2)
 
bool operator<(const Fraction &rVal1, const Fraction &rVal2)
 
Fraction operator+(const Fraction &rVal1, const Fraction &rVal2)
 
Fraction operator*(const Fraction &rVal1, const Fraction &rVal2)
 
bool operator==(const Fraction &rVal1, const Fraction &rVal2)
 
static boost::rational< sal_Int32 > toRational(sal_Int32 n, sal_Int32 d)
 
bool operator>=(const Fraction &rVal1, const Fraction &rVal2)
 
bool operator!=(const Fraction &rVal1, const Fraction &rVal2)
 
bool operator<=(const Fraction &rVal1, const Fraction &rVal2)
 
static constexpr bool isOutOfRange(sal_Int64 nNum)
 
static void rational_ReduceInaccurate(boost::rational< sal_Int32 > &rRational, unsigned nSignificantBits)
 
#define SAL_WARN_IF(condition, area, stream)
 
#define SAL_WARN(area, stream)
 
std::enable_if_t<(sizeof(N)==4)> hash_combine(N &nSeed, T const *pValue, size_t nCount)
 
std::enable_if< std::is_signed< T >::value, bool >::type checked_multiply(T a, T b, T &result)