summaryrefslogtreecommitdiff
path: root/tools/source
diff options
context:
space:
mode:
authorNoel Grandin <noel@peralex.com>2021-11-26 13:55:03 +0200
committerNoel Grandin <noel.grandin@collabora.co.uk>2021-11-29 14:28:41 +0100
commite1ca21116a05552dbabeed50b671aa02f282cb25 (patch)
tree4d02ddffc5ef5902421f28120f1f8651b44bbe56 /tools/source
parent85a2c5c71e5be5cffd9d40c1dd19bd1e69eef2bf (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> (cherry picked from commit 05766922e7e4262b98e9c3f8d83cdfdaa49d3f7a) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/125997
Diffstat (limited to 'tools/source')
-rw-r--r--tools/source/generic/fract.cxx21
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);