diff options
author | Noel Grandin <noel@peralex.com> | 2021-11-26 13:55:03 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2021-11-26 17:30:10 +0100 |
commit | 05766922e7e4262b98e9c3f8d83cdfdaa49d3f7a (patch) | |
tree | c70f1f00de111f92b3a9e204c43c5ae3749347ce | |
parent | 26643b50a29cb25f4827aebbccc72beddeac7a69 (diff) |
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.grandin@collabora.co.uk>
-rw-r--r-- | tools/source/generic/fract.cxx | 21 |
1 files changed, 15 insertions, 6 deletions
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); |