summaryrefslogtreecommitdiff
path: root/sal/rtl/math.cxx
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2021-06-17 22:49:30 +0200
committerMike Kaganski <mike.kaganski@collabora.com>2021-06-18 06:24:33 +0200
commit3fc41a91ce3bd9d6756905809e261499a51d9774 (patch)
treeb5af173e51b057e835129189464a97ad56d4f466 /sal/rtl/math.cxx
parenta78510ab673dd0d827efeb00873d5d9137813be7 (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.cxx22
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;