implement Inf and NaN handling for rtl_math_expm1() and rtl_math_log1p()
Change-Id: Ie424a6f038107ef8b574d0422efaf49b441c110f
diff --git a/sal/rtl/math.cxx b/sal/rtl/math.cxx
index 37225f4..3ec6fe0 100644
--- a/sal/rtl/math.cxx
+++ b/sal/rtl/math.cxx
@@ -1096,6 +1096,24 @@ double SAL_CALL rtl_math_approxValue( double fValue ) SAL_THROW_EXTERN_C()
double SAL_CALL rtl_math_expm1( double fValue ) SAL_THROW_EXTERN_C()
{
// See http://en.cppreference.com/w/cpp/numeric/math/expm1
if (fValue == 0.0)
return fValue;
if (!::rtl::math::isFinite(fValue))
{
if (::rtl::math::isInf(fValue))
{
if (::rtl::math::isSignBitSet(fValue))
return -1.0;
else
return fValue;
}
// It is a NaN.
return fValue;
}
double fe = exp( fValue );
if (fe == 1.0)
return fValue;
@@ -1106,6 +1124,31 @@ double SAL_CALL rtl_math_expm1( double fValue ) SAL_THROW_EXTERN_C()
double SAL_CALL rtl_math_log1p( double fValue ) SAL_THROW_EXTERN_C()
{
// See http://en.cppreference.com/w/cpp/numeric/math/log1p
if (fValue == 0.0)
return fValue;
if (fValue == -1.0)
{
rtl::math::setInf( &fValue, true);
return fValue;
}
if (fValue < -1.0) // includes -Inf
{
rtl::math::setNan( &fValue);
return fValue;
}
if (!::rtl::math::isFinite(fValue))
{
if (::rtl::math::isInf(fValue))
return fValue;
// It is a NaN.
return fValue;
}
// Use volatile because a compiler may be too smart "optimizing" the
// condition such that in certain cases the else path was called even if
// (fp==1.0) was true, where the term (fp-1.0) then resulted in 0.0 and