diff options
author | Erik Verbruggen <erik.verbruggen@theqtcompany.com> | 2015-08-10 13:22:38 +0200 |
---|---|---|
committer | Erik Verbruggen <erik.verbruggen@theqtcompany.com> | 2015-11-19 10:56:41 +0000 |
commit | 72c68f5f220d691b475b42374b40039b99620876 (patch) | |
tree | a0ec5f34acec23c7a6740e18dd341ae8cf7588fd | |
parent | c7934f2489e2eb9a539206bab35f335b1943c5bd (diff) |
Reimplement qt_inf/qt_snan/qt_qnan using std::numeric_limits.
Qt already assumes a working IEEE-754 implementation, so we can rely
on a working std::numeric_limits<double>.
This patch also gets rid of three cases of type-punning with unions
(which is undefined behavior in C++).
Change-Id: Ic3747f49d55e372960abf2091c1d5752c1eccdff
Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r-- | src/corelib/global/qnumeric_p.h | 84 |
1 files changed, 14 insertions, 70 deletions
diff --git a/src/corelib/global/qnumeric_p.h b/src/corelib/global/qnumeric_p.h index b56cdef939..650c32d44b 100644 --- a/src/corelib/global/qnumeric_p.h +++ b/src/corelib/global/qnumeric_p.h @@ -107,85 +107,29 @@ static inline bool isfinite(float f) { return std::isfinite(f); } #endif } -#if !defined(Q_CC_MIPS) - -static const union { unsigned char c[8]; double d; } qt_be_inf_bytes = { { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 } }; -static const union { unsigned char c[8]; double d; } qt_le_inf_bytes = { { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f } }; -static inline double qt_inf() -{ - return (QSysInfo::ByteOrder == QSysInfo::BigEndian - ? qt_be_inf_bytes.d - : qt_le_inf_bytes.d); -} - -// Signaling NAN -static const union { unsigned char c[8]; double d; } qt_be_snan_bytes = { { 0x7f, 0xf8, 0, 0, 0, 0, 0, 0 } }; -static const union { unsigned char c[8]; double d; } qt_le_snan_bytes = { { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f } }; -static inline double qt_snan() +Q_DECL_CONSTEXPR static inline double qt_inf() Q_DECL_NOEXCEPT { - return (QSysInfo::ByteOrder == QSysInfo::BigEndian - ? qt_be_snan_bytes.d - : qt_le_snan_bytes.d); + Q_STATIC_ASSERT_X(std::numeric_limits<double>::has_infinity, + "platform has no definition for infinity for type double"); + return std::numeric_limits<double>::infinity(); } -// Quiet NAN -static const union { unsigned char c[8]; double d; } qt_be_qnan_bytes = { { 0xff, 0xf8, 0, 0, 0, 0, 0, 0 } }; -static const union { unsigned char c[8]; double d; } qt_le_qnan_bytes = { { 0, 0, 0, 0, 0, 0, 0xf8, 0xff } }; -static inline double qt_qnan() +// Signaling NaN +Q_DECL_CONSTEXPR static inline double qt_snan() Q_DECL_NOEXCEPT { - return (QSysInfo::ByteOrder == QSysInfo::BigEndian - ? qt_be_qnan_bytes.d - : qt_le_qnan_bytes.d); + Q_STATIC_ASSERT_X(std::numeric_limits<double>::has_signaling_NaN, + "platform has no definition for signaling NaN for type double"); + return std::numeric_limits<double>::signaling_NaN(); } -#else // Q_CC_MIPS - -static const unsigned char qt_be_inf_bytes[] = { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 }; -static const unsigned char qt_le_inf_bytes[] = { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f }; -static inline double qt_inf() +// Quiet NaN +Q_DECL_CONSTEXPR static inline double qt_qnan() Q_DECL_NOEXCEPT { - const unsigned char *bytes; - bytes = (QSysInfo::ByteOrder == QSysInfo::BigEndian - ? qt_be_inf_bytes - : qt_le_inf_bytes); - - union { unsigned char c[8]; double d; } returnValue; - memcpy(returnValue.c, bytes, sizeof(returnValue.c)); - return returnValue.d; + Q_STATIC_ASSERT_X(std::numeric_limits<double>::has_quiet_NaN, + "platform has no definition for quiet NaN for type double"); + return std::numeric_limits<double>::quiet_NaN(); } -// Signaling NAN -static const unsigned char qt_be_snan_bytes[] = { 0x7f, 0xf8, 0, 0, 0, 0, 0, 0 }; -static const unsigned char qt_le_snan_bytes[] = { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f }; -static inline double qt_snan() -{ - const unsigned char *bytes; - bytes = (QSysInfo::ByteOrder == QSysInfo::BigEndian - ? qt_be_snan_bytes - : qt_le_snan_bytes); - - union { unsigned char c[8]; double d; } returnValue; - memcpy(returnValue.c, bytes, sizeof(returnValue.c)); - return returnValue.d; -} - -// Quiet NAN -static const unsigned char qt_be_qnan_bytes[] = { 0xff, 0xf8, 0, 0, 0, 0, 0, 0 }; -static const unsigned char qt_le_qnan_bytes[] = { 0, 0, 0, 0, 0, 0, 0xf8, 0xff }; -static inline double qt_qnan() -{ - const unsigned char *bytes; - bytes = (QSysInfo::ByteOrder == QSysInfo::BigEndian - ? qt_be_qnan_bytes - : qt_le_qnan_bytes); - - union { unsigned char c[8]; double d; } returnValue; - memcpy(returnValue.c, bytes, sizeof(returnValue.c)); - return returnValue.d; -} - -#endif // Q_CC_MIPS - static inline bool qt_is_inf(double d) { return qnumeric_std_wrapper::isinf(d); |