include/tools/fract.hxx | 3 +++ tools/source/generic/fract.cxx | 40 ++++++++++++++++++++++++++++++++++++++++ vcl/source/outdev/map.cxx | 32 +------------------------------- 3 files changed, 44 insertions(+), 31 deletions(-)
New commits: commit 551e5943d4bec10c31077f38ccf5d8149c05265c Author: Noel Grandin <noel.gran...@collabora.co.uk> AuthorDate: Thu Oct 27 08:48:25 2022 +0200 Commit: Noel Grandin <noel.gran...@collabora.co.uk> CommitDate: Thu Oct 27 10:58:04 2022 +0200 tdf#123419 optimise ImplMakeFraction which is very hot here. Push it down into Fraction, where we can skip the construction of boost::rational intermediate values Change-Id: I7e5f18456a252a159d3a50e9297168e5ba9e1588 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/141894 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> diff --git a/include/tools/fract.hxx b/include/tools/fract.hxx index c844f8eed619..e1305ca8a8fd 100644 --- a/include/tools/fract.hxx +++ b/include/tools/fract.hxx @@ -72,6 +72,9 @@ public: void ReduceInaccurate( unsigned nSignificantBits ); + /// Multiply the two fractions represented here and reduce inaccuracy to 32-bits, used by vcl + static Fraction MakeFraction(tools::Long nN1, tools::Long nN2, tools::Long nD1, tools::Long nD2); + // Compute value usable as hash. size_t GetHashValue() const; diff --git a/tools/source/generic/fract.cxx b/tools/source/generic/fract.cxx index 7f2ffba1003d..b6ae743764df 100644 --- a/tools/source/generic/fract.cxx +++ b/tools/source/generic/fract.cxx @@ -483,4 +483,44 @@ size_t Fraction::GetHashValue() const return hash; } +Fraction Fraction::MakeFraction( tools::Long nN1, tools::Long nN2, tools::Long nD1, tools::Long nD2 ) +{ + if( nD1 == 0 || nD2 == 0 ) //under these bad circumstances the following while loop will be endless + { + SAL_WARN("tools.fraction", "Invalid parameter for ImplMakeFraction"); + return Fraction( 1, 1 ); + } + + tools::Long i = 1; + + if ( nN1 < 0 ) { i = -i; nN1 = -nN1; } + if ( nN2 < 0 ) { i = -i; nN2 = -nN2; } + if ( nD1 < 0 ) { i = -i; nD1 = -nD1; } + if ( nD2 < 0 ) { i = -i; nD2 = -nD2; } + // all positive; i sign + + boost::rational<sal_Int32> a = toRational(i*nN1, nD1); + boost::rational<sal_Int32> b = toRational(nN2, nD2); + bool bFail = checked_multiply_by(a, b); + + + while ( bFail ) { + if ( nN1 > nN2 ) + nN1 = (nN1 + 1) / 2; + else + nN2 = (nN2 + 1) / 2; + if ( nD1 > nD2 ) + nD1 = (nD1 + 1) / 2; + else + nD2 = (nD2 + 1) / 2; + + a = toRational(i*nN1, nD1); + b = toRational(nN2, nD2); + bFail = checked_multiply_by(a, b); + } + + rational_ReduceInaccurate(a, /*nSignificantBits*/32); + return Fraction(a.numerator(), a.denominator()); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/outdev/map.cxx b/vcl/source/outdev/map.cxx index 2c3801bf9e84..02221c345862 100644 --- a/vcl/source/outdev/map.cxx +++ b/vcl/source/outdev/map.cxx @@ -44,37 +44,7 @@ ctor fraction once); we could also do this with BigInts static Fraction ImplMakeFraction( tools::Long nN1, tools::Long nN2, tools::Long nD1, tools::Long nD2 ) { - if( nD1 == 0 || nD2 == 0 ) //under these bad circumstances the following while loop will be endless - { - SAL_WARN("vcl.gdi", "Invalid parameter for ImplMakeFraction"); - return Fraction( 1, 1 ); - } - - tools::Long i = 1; - - if ( nN1 < 0 ) { i = -i; nN1 = -nN1; } - if ( nN2 < 0 ) { i = -i; nN2 = -nN2; } - if ( nD1 < 0 ) { i = -i; nD1 = -nD1; } - if ( nD2 < 0 ) { i = -i; nD2 = -nD2; } - // all positive; i sign - - Fraction aF = Fraction( i*nN1, nD1 ) * Fraction( nN2, nD2 ); - - while ( !aF.IsValid() ) { - if ( nN1 > nN2 ) - nN1 = (nN1 + 1) / 2; - else - nN2 = (nN2 + 1) / 2; - if ( nD1 > nD2 ) - nD1 = (nD1 + 1) / 2; - else - nD2 = (nD2 + 1) / 2; - - aF = Fraction( i*nN1, nD1 ) * Fraction( nN2, nD2 ); - } - - aF.ReduceInaccurate(32); - return aF; + return Fraction::MakeFraction(nN1, nN2, nD1, nD2); } static auto setMapRes(ImplMapRes& rMapRes, const o3tl::Length eUnit)