diff options
author | Eike Rathke <erack@redhat.com> | 2016-10-01 12:11:19 +0200 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2016-10-01 22:55:57 +0000 |
commit | 2135eae2a97c17d89cb47a2074830fd2d7b2226f (patch) | |
tree | 6f91d5cdc9ffc0653275b020529848756305b71b /sal | |
parent | ec3aabe66bde2c8bdea2c3692ac1c4981c8910a3 (diff) |
let approxEqual() not scale too early for large representable integer values
And since this is now too much code for inline move implementation to math.cxx
Which again made it necessary to give libreofficekit lokdocview.cxx its own
implementation that doesn't even claim to build against sal ...
Change-Id: I0f80be9d9172ee20693b9babde715206f2c3d8c1
Reviewed-on: https://gerrit.libreoffice.org/29428
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins <ci@libreoffice.org>
Diffstat (limited to 'sal')
-rw-r--r-- | sal/rtl/math.cxx | 39 | ||||
-rw-r--r-- | sal/util/sal.map | 1 |
2 files changed, 40 insertions, 0 deletions
diff --git a/sal/rtl/math.cxx b/sal/rtl/math.cxx index b8a1cd2b2962..1df123bb095c 100644 --- a/sal/rtl/math.cxx +++ b/sal/rtl/math.cxx @@ -149,6 +149,27 @@ struct UStringTraits } }; +/** If value (passed as absolute value) is an integer representable as double, + which we handle explicitly at some places. + */ +bool isRepresentableInteger(double fAbsValue) +{ + const sal_Int64 kMaxInt = (static_cast<sal_Int64>(1) << 53) - 1; + if (fAbsValue <= static_cast<double>(kMaxInt)) + { + sal_Int64 nInt = static_cast<sal_Int64>(fAbsValue); + // Check the integer range again because double comparison may yield + // true within the precision range. + // XXX loplugin:fpcomparison complains about floating-point comparison + // for static_cast<double>(nInt) == fAbsValue, though we actually want + // this here. + double fInt; + return (nInt <= kMaxInt && + (!((fInt = static_cast<double>(nInt)) < fAbsValue) && !(fInt > fAbsValue))); + } + return false; +} + // Solaris C++ 5.2 compiler has problems when "StringT ** pResult" is // "typename T::String ** pResult" instead: template< typename T, typename StringT > @@ -1064,6 +1085,24 @@ double SAL_CALL rtl_math_approxValue( double fValue ) SAL_THROW_EXTERN_C() return bSign ? -fValue : fValue; } +bool SAL_CALL rtl_math_approxEqual(double a, double b) SAL_THROW_EXTERN_C() +{ + static const double e48 = 1.0 / (16777216.0 * 16777216.0); + static const double e44 = e48 * 16.0; + // XXX loplugin:fpcomparison complains about floating-point comparison for + // a==b, though we actually want this here. + if (!(a<b) && !(a>b)) + return true; + if (a == 0.0 || b == 0.0) + return false; + const double d = fabs(a - b); + if (d > ((a = fabs(a)) * e44) || d > ((b = fabs(b)) * e44)) + return false; + if (isRepresentableInteger(d) && isRepresentableInteger(a) && isRepresentableInteger(b)) + return false; // special case for representable integers. + return (d < a * e48 && d < b * e48); +} + double SAL_CALL rtl_math_expm1( double fValue ) SAL_THROW_EXTERN_C() { return expm1(fValue); diff --git a/sal/util/sal.map b/sal/util/sal.map index d9995e1e4cae..d50752ce31ae 100644 --- a/sal/util/sal.map +++ b/sal/util/sal.map @@ -704,6 +704,7 @@ LIBO_UDK_5.3 { # symbols available in >= LibO 5.3 rtl_uString_newReplaceFirstAsciiLUtf16L; rtl_uString_newReplaceFirstUtf16LAsciiL; rtl_uString_newReplaceFirstUtf16LUtf16L; + rtl_math_approxEqual; } LIBO_UDK_5.2; PRIVATE_1.0 { |