diff options
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 { |