tools/source/generic/fract.cxx |   21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

New commits:
commit 05766922e7e4262b98e9c3f8d83cdfdaa49d3f7a
Author:     Noel Grandin <n...@peralex.com>
AuthorDate: Fri Nov 26 13:55:03 2021 +0200
Commit:     Noel Grandin <noel.gran...@collabora.co.uk>
CommitDate: Fri Nov 26 17:30:10 2021 +0100

    speed up Fraction::operator*= a little
    
    for my test spreadsheet this reduced the time spent
    in Fraction by 30%
    
    Change-Id: Ib14a93284dbd6c6ea2349c1754979135463ca61b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/125878
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>

diff --git a/tools/source/generic/fract.cxx b/tools/source/generic/fract.cxx
index 1b3c95a6cdda..93a92fb3a12a 100644
--- a/tools/source/generic/fract.cxx
+++ b/tools/source/generic/fract.cxx
@@ -35,8 +35,8 @@
 #endif
 
 static boost::rational<sal_Int32> rational_FromDouble(double dVal);
-
 static void rational_ReduceInaccurate(boost::rational<sal_Int32>& rRational, 
unsigned nSignificantBits);
+static int impl_NumberOfBits( sal_uInt32 nNum );
 
 static boost::rational<sal_Int32> toRational(sal_Int32 n, sal_Int32 d)
 {
@@ -163,15 +163,24 @@ Fraction& Fraction::operator -= ( const Fraction& rVal )
 
 namespace
 {
-    template<typename T> bool checked_multiply_by(boost::rational<T>& i, const 
boost::rational<T>& r)
+    bool checked_multiply_by(boost::rational<sal_Int32>& i, const 
boost::rational<sal_Int32>& r)
     {
         // Protect against self-modification
-        T num = r.numerator();
-        T den = r.denominator();
+        sal_Int32 num = r.numerator();
+        sal_Int32 den = r.denominator();
+
+        // Fast-path if the number of bits in input is < the number of bits in 
the output, overflow cannot happen
+        // This is considerably faster than repeated std::gcd() operations
+        if ((impl_NumberOfBits(std::abs(i.numerator())) + 
impl_NumberOfBits(std::abs(r.numerator()))) < 32 &&
+            (impl_NumberOfBits(std::abs(i.denominator())) + 
impl_NumberOfBits(std::abs(r.denominator()))) < 32)
+        {
+            i *= r;
+            return false;
+        }
 
         // Avoid overflow and preserve normalization
-        T gcd1 = std::gcd(i.numerator(), den);
-        T gcd2 = std::gcd(num, i.denominator());
+        sal_Int32 gcd1 = std::gcd(i.numerator(), den);
+        sal_Int32 gcd2 = std::gcd(num, i.denominator());
 
         bool fail = false;
         fail |= o3tl::checked_multiply(i.numerator() / gcd1, num / gcd2, num);

Reply via email to