summaryrefslogtreecommitdiff
path: root/sal
diff options
context:
space:
mode:
Diffstat (limited to 'sal')
-rw-r--r--sal/rtl/math.cxx39
-rw-r--r--sal/util/sal.map1
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 {