diff options
author | Mike Kaganski <mike.kaganski@collabora.com> | 2021-06-17 22:49:30 +0200 |
---|---|---|
committer | Mike Kaganski <mike.kaganski@collabora.com> | 2021-06-18 06:24:33 +0200 |
commit | 3fc41a91ce3bd9d6756905809e261499a51d9774 (patch) | |
tree | b5af173e51b057e835129189464a97ad56d4f466 /sal/rtl/math.cxx | |
parent | a78510ab673dd0d827efeb00873d5d9137813be7 (diff) |
Use std::fesetround / std::nearbyint for half-to-even rounding
C++ floating-point environment has thread storage duration, so
std::fesetround call is thread-safe.
std::nearbyint uses half-to-even rounding with FE_TONEAREST,
as specified in ISO/IEC 9899:1999 F.3, and in Appendix to
ANSI/IEEE 854.
Change-Id: I26995842c30e2663b40af5b5314791c1328037d4
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/117307
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
Diffstat (limited to 'sal/rtl/math.cxx')
-rw-r--r-- | sal/rtl/math.cxx | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/sal/rtl/math.cxx b/sal/rtl/math.cxx index 698e158df072..7db362f35cfe 100644 --- a/sal/rtl/math.cxx +++ b/sal/rtl/math.cxx @@ -33,6 +33,8 @@ #include <algorithm> #include <cassert> +#include <cfenv> +#include <cmath> #include <float.h> #include <limits> #include <limits.h> @@ -1137,8 +1139,24 @@ double SAL_CALL rtl_math_round(double fValue, int nDecPlaces, if (fValue == 0.0) return fValue; - if ( nDecPlaces == 0 && eMode == rtl_math_RoundingMode_Corrected ) - return std::round( fValue ); + if (nDecPlaces == 0) + { + switch (eMode) + { + case rtl_math_RoundingMode_Corrected: + return std::round(fValue); + case rtl_math_RoundingMode_HalfEven: + if (const int oldMode = std::fegetround(); std::fesetround(FE_TONEAREST) == 0) + { + fValue = std::nearbyint(fValue); + std::fesetround(oldMode); + return fValue; + } + break; + default: + break; + } + } const double fOrigValue = fValue; |