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)

Reply via email to