[Libreoffice-commits] core.git: Branch 'libreoffice-7-1' - include/sal sal/rtl
Eike Rathke (via logerrit)
logerrit at kemper.freedesktop.org
Fri Dec 18 10:01:30 UTC 2020
include/sal/mathconf.h | 14 +++++
sal/rtl/math.cxx | 135 +++++++++++++++++++++++++------------------------
2 files changed, 85 insertions(+), 64 deletions(-)
New commits:
commit ead1cdd23f5379f5cd8f69d5e73f410a67896db2
Author: Eike Rathke <erack at redhat.com>
AuthorDate: Thu Dec 17 20:44:43 2020 +0100
Commit: Eike Rathke <erack at redhat.com>
CommitDate: Fri Dec 18 11:00:57 2020 +0100
Check intermediate for not to be rounded value, tdf#138360 follow-up
This is a combination of 3 commits.
Add sal_uInt64 fields to sal_math_Double
We may need them later, and at least don't have a confusing
inf_parts or nan_parts struct name but just parts as well.
Ife0cf279c47d2815aa2a1483223397b147e9d776
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/107924
Reviewed-by: Eike Rathke <erack at redhat.com>
Tested-by: Jenkins
Replace log2() call with parts.exponent-1023, tdf#138360 follow-up
... to save some cycles as we anyway need only the integer value
of the exponent and even exactly this value for the number of
possible decimals.
I8d462f53cadde6a95d57d1342d8487fbfa001ae9
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/107928
Tested-by: Jenkins
Reviewed-by: Eike Rathke <erack at redhat.com>
Check intermediate for not to be rounded value, tdf#138360 follow-up
I98cc25267e7a10c34179bab50d19f49436e1c48c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/107929
Tested-by: Jenkins
Reviewed-by: Eike Rathke <erack at redhat.com>
Change-Id: I98cc25267e7a10c34179bab50d19f49436e1c48c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/107931
Tested-by: Jenkins
Reviewed-by: Eike Rathke <erack at redhat.com>
diff --git a/include/sal/mathconf.h b/include/sal/mathconf.h
index 687f6e3da133..11bd32c35de0 100644
--- a/include/sal/mathconf.h
+++ b/include/sal/mathconf.h
@@ -104,6 +104,13 @@ union sal_math_Double
unsigned msw :32;
unsigned lsw :32;
} w32_parts;
+ struct
+ {
+ sal_uInt64 sign : 1;
+ sal_uInt64 exponent :11;
+ sal_uInt64 fraction :52;
+ } parts;
+ sal_uInt64 intrep;
double value;
};
@@ -130,6 +137,13 @@ union sal_math_Double
unsigned lsw :32;
unsigned msw :32;
} w32_parts;
+ struct
+ {
+ sal_uInt64 fraction :52;
+ sal_uInt64 exponent :11;
+ sal_uInt64 sign : 1;
+ } parts;
+ sal_uInt64 intrep;
double value;
};
diff --git a/sal/rtl/math.cxx b/sal/rtl/math.cxx
index 46a3e925b95b..a85c8ac6e959 100644
--- a/sal/rtl/math.cxx
+++ b/sal/rtl/math.cxx
@@ -1167,9 +1167,10 @@ double SAL_CALL rtl_math_round(double fValue, int nDecPlaces,
// Determine how many decimals are representable in the precision.
// Anything greater 2^52 and 0.0 was already ruled out above.
// Theoretically 0.5, 0.25, 0.125, 0.0625, 0.03125, ...
- const double fDec = 52 - log2(fValue) + 1;
- if (fDec < nDecPlaces)
- nDecPlaces = static_cast<sal_Int32>(fDec);
+ const sal_math_Double* pd = reinterpret_cast<const sal_math_Double*>(&fValue);
+ const sal_Int32 nDec = 52 - (pd->parts.exponent - 1023);
+ if (nDec < nDecPlaces)
+ nDecPlaces = nDec;
}
/* TODO: this was without the inverse factor and determining max
@@ -1190,75 +1191,81 @@ double SAL_CALL rtl_math_round(double fValue, int nDecPlaces,
fValue *= fFac;
}
- switch ( eMode )
+ // Round only if not already in distance precision gaps of integers, where
+ // for [2^52,2^53) adding 0.5 would even yield the next representable
+ // integer.
+ if (fValue < (static_cast<sal_Int64>(1) << 52))
{
- case rtl_math_RoundingMode_Corrected :
- fValue = rtl::math::approxFloor(fValue + 0.5);
- break;
- case rtl_math_RoundingMode_Down:
- fValue = rtl::math::approxFloor(fValue);
- break;
- case rtl_math_RoundingMode_Up:
- fValue = rtl::math::approxCeil(fValue);
- break;
- case rtl_math_RoundingMode_Floor:
- fValue = bSign ? rtl::math::approxCeil(fValue)
- : rtl::math::approxFloor( fValue );
- break;
- case rtl_math_RoundingMode_Ceiling:
- fValue = bSign ? rtl::math::approxFloor(fValue)
- : rtl::math::approxCeil(fValue);
- break;
- case rtl_math_RoundingMode_HalfDown :
- {
- double f = floor(fValue);
- fValue = ((fValue - f) <= 0.5) ? f : ceil(fValue);
- }
- break;
- case rtl_math_RoundingMode_HalfUp:
+ switch ( eMode )
{
- double f = floor(fValue);
- fValue = ((fValue - f) < 0.5) ? f : ceil(fValue);
- }
- break;
- case rtl_math_RoundingMode_HalfEven:
+ case rtl_math_RoundingMode_Corrected :
+ fValue = rtl::math::approxFloor(fValue + 0.5);
+ break;
+ case rtl_math_RoundingMode_Down:
+ fValue = rtl::math::approxFloor(fValue);
+ break;
+ case rtl_math_RoundingMode_Up:
+ fValue = rtl::math::approxCeil(fValue);
+ break;
+ case rtl_math_RoundingMode_Floor:
+ fValue = bSign ? rtl::math::approxCeil(fValue)
+ : rtl::math::approxFloor( fValue );
+ break;
+ case rtl_math_RoundingMode_Ceiling:
+ fValue = bSign ? rtl::math::approxFloor(fValue)
+ : rtl::math::approxCeil(fValue);
+ break;
+ case rtl_math_RoundingMode_HalfDown :
+ {
+ double f = floor(fValue);
+ fValue = ((fValue - f) <= 0.5) ? f : ceil(fValue);
+ }
+ break;
+ case rtl_math_RoundingMode_HalfUp:
+ {
+ double f = floor(fValue);
+ fValue = ((fValue - f) < 0.5) ? f : ceil(fValue);
+ }
+ break;
+ case rtl_math_RoundingMode_HalfEven:
#if defined FLT_ROUNDS
-/*
- Use fast version. FLT_ROUNDS may be defined to a function by some compilers!
-
- DBL_EPSILON is the smallest fractional number which can be represented,
- its reciprocal is therefore the smallest number that cannot have a
- fractional part. Once you add this reciprocal to `x', its fractional part
- is stripped off. Simply subtracting the reciprocal back out returns `x'
- without its fractional component.
- Simple, clever, and elegant - thanks to Ross Cottrell, the original author,
- who placed it into public domain.
-
- volatile: prevent compiler from being too smart
-*/
- if (FLT_ROUNDS == 1)
- {
- volatile double x = fValue + 1.0 / DBL_EPSILON;
- fValue = x - 1.0 / DBL_EPSILON;
- }
- else
-#endif // FLT_ROUNDS
- {
- double f = floor(fValue);
- if ((fValue - f) != 0.5)
+ /*
+ Use fast version. FLT_ROUNDS may be defined to a function by some compilers!
+
+ DBL_EPSILON is the smallest fractional number which can be represented,
+ its reciprocal is therefore the smallest number that cannot have a
+ fractional part. Once you add this reciprocal to `x', its fractional part
+ is stripped off. Simply subtracting the reciprocal back out returns `x'
+ without its fractional component.
+ Simple, clever, and elegant - thanks to Ross Cottrell, the original author,
+ who placed it into public domain.
+
+ volatile: prevent compiler from being too smart
+ */
+ if (FLT_ROUNDS == 1)
{
- fValue = floor( fValue + 0.5 );
+ volatile double x = fValue + 1.0 / DBL_EPSILON;
+ fValue = x - 1.0 / DBL_EPSILON;
}
else
+#endif // FLT_ROUNDS
{
- double g = f / 2.0;
- fValue = (g == floor( g )) ? f : (f + 1.0);
+ double f = floor(fValue);
+ if ((fValue - f) != 0.5)
+ {
+ fValue = floor( fValue + 0.5 );
+ }
+ else
+ {
+ double g = f / 2.0;
+ fValue = (g == floor( g )) ? f : (f + 1.0);
+ }
}
- }
- break;
- default:
- OSL_ASSERT(false);
- break;
+ break;
+ default:
+ OSL_ASSERT(false);
+ break;
+ }
}
if (nDecPlaces != 0)
More information about the Libreoffice-commits
mailing list