diff options
author | Eike Rathke <erack@redhat.com> | 2015-10-24 22:04:28 +0200 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2015-10-24 22:07:08 +0200 |
commit | 04967cba8e71e178915068e237a96e32a8cb3e9e (patch) | |
tree | 31349c23ec5d146108a1485f335eb0cc4084846c /sal | |
parent | 9846b6ab3d36c8b2696e8829c121016f9fa81e66 (diff) |
implement Inf and NaN handling for rtl_math_expm1() and rtl_math_log1p()
Change-Id: Ie424a6f038107ef8b574d0422efaf49b441c110f
Diffstat (limited to 'sal')
-rw-r--r-- | sal/rtl/math.cxx | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/sal/rtl/math.cxx b/sal/rtl/math.cxx index 37225f4c7b46..3ec6fe0d489d 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 |