diff options
-rw-r--r-- | configure.json | 16 | ||||
-rw-r--r-- | src/corelib/global/qconfig-bootstrapped.h | 1 | ||||
-rw-r--r-- | src/corelib/global/qnumeric.cpp | 2 | ||||
-rw-r--r-- | src/corelib/global/qnumeric.h | 7 | ||||
-rw-r--r-- | src/corelib/global/qnumeric_p.h | 3 | ||||
-rw-r--r-- | tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp | 15 | ||||
-rw-r--r-- | tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp | 2 | ||||
-rw-r--r-- | tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp | 4 |
8 files changed, 47 insertions, 3 deletions
diff --git a/configure.json b/configure.json index 5ee27fec62..70ad9440c8 100644 --- a/configure.json +++ b/configure.json @@ -484,6 +484,17 @@ ] } }, + "signaling_nan": { + "label": "Signaling NaN for doubles", + "type": "compile", + "test": { + "head": [ "#include <limits>" ], + "main": [ + "using B = std::numeric_limits<double>;", + "static_assert(B::has_signaling_NaN, \"System lacks signaling NaN\");" + ] + } + }, "sse2": { "label": "SSE2 instructions", "type": "x86Simd" @@ -1005,6 +1016,11 @@ { "type": "define", "name": "QT_REDUCE_RELOCATIONS" } ] }, + "signaling_nan": { + "label": "Signaling NaN", + "condition": "tests.signaling_nan", + "output": [ "publicFeature" ] + }, "sse2": { "label": "SSE2", "condition": "(arch.i386 || arch.x86_64) && tests.sse2", diff --git a/src/corelib/global/qconfig-bootstrapped.h b/src/corelib/global/qconfig-bootstrapped.h index 2e58dabf5f..e6ad80525a 100644 --- a/src/corelib/global/qconfig-bootstrapped.h +++ b/src/corelib/global/qconfig-bootstrapped.h @@ -109,6 +109,7 @@ # define QT_FEATURE_renameat2 -1 #endif #define QT_FEATURE_sharedmemory -1 +#define QT_FEATURE_signaling_nan -1 #define QT_FEATURE_slog2 -1 #ifdef __GLIBC_PREREQ # define QT_FEATURE_statx (__GLIBC_PREREQ(2, 28) ? 1 : -1) diff --git a/src/corelib/global/qnumeric.cpp b/src/corelib/global/qnumeric.cpp index 11440f40a4..9cb9c1283a 100644 --- a/src/corelib/global/qnumeric.cpp +++ b/src/corelib/global/qnumeric.cpp @@ -81,11 +81,13 @@ Q_CORE_EXPORT bool qIsNaN(float f) { return qt_is_nan(f); } */ Q_CORE_EXPORT bool qIsFinite(float f) { return qt_is_finite(f); } +#if QT_CONFIG(signaling_nan) /*! Returns the bit pattern of a signalling NaN as a double. \relates <QtGlobal> */ Q_CORE_EXPORT double qSNaN() { return qt_snan(); } +#endif /*! Returns the bit pattern of a quiet NaN as a double. diff --git a/src/corelib/global/qnumeric.h b/src/corelib/global/qnumeric.h index 6a0c64712f..2771eea64f 100644 --- a/src/corelib/global/qnumeric.h +++ b/src/corelib/global/qnumeric.h @@ -44,7 +44,6 @@ QT_BEGIN_NAMESPACE - Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsInf(double d); Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsNaN(double d); Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsFinite(double d); @@ -53,7 +52,9 @@ Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsInf(float f); Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsNaN(float f); Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsFinite(float f); Q_CORE_EXPORT Q_DECL_CONST_FUNCTION int qFpClassify(float val); +#if QT_CONFIG(signaling_nan) Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qSNaN(); +#endif Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qQNaN(); Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qInf(); @@ -61,7 +62,9 @@ Q_CORE_EXPORT quint32 qFloatDistance(float a, float b); Q_CORE_EXPORT quint64 qFloatDistance(double a, double b); #define Q_INFINITY (QT_PREPEND_NAMESPACE(qInf)()) -#define Q_SNAN (QT_PREPEND_NAMESPACE(qSNaN)()) +#if QT_CONFIG(signaling_nan) +# define Q_SNAN (QT_PREPEND_NAMESPACE(qSNaN)()) +#endif #define Q_QNAN (QT_PREPEND_NAMESPACE(qQNaN)()) QT_END_NAMESPACE diff --git a/src/corelib/global/qnumeric_p.h b/src/corelib/global/qnumeric_p.h index 21f9cfbef0..86e7997680 100644 --- a/src/corelib/global/qnumeric_p.h +++ b/src/corelib/global/qnumeric_p.h @@ -133,13 +133,14 @@ Q_DECL_CONSTEXPR Q_DECL_CONST_FUNCTION static inline double qt_inf() noexcept return std::numeric_limits<double>::infinity(); } -// Signaling NaN +#if QT_CONFIG(signaling_nan) Q_DECL_CONSTEXPR Q_DECL_CONST_FUNCTION static inline double qt_snan() noexcept { 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(); } +#endif // Quiet NaN Q_DECL_CONSTEXPR Q_DECL_CONST_FUNCTION static inline double qt_qnan() noexcept diff --git a/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp b/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp index 5697d21547..a6d600e125 100644 --- a/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp +++ b/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp @@ -44,6 +44,9 @@ private slots: void fuzzyCompare(); void rawNaN_data(); void rawNaN(); +#if QT_CONFIG(signaling_nan) + void distinctNaN(); +#endif void generalNaN_data(); void generalNaN(); void infinity(); @@ -139,6 +142,9 @@ void tst_QNumeric::rawNaN_data() QTest::addColumn<double>("nan"); QTest::newRow("quiet") << qQNaN(); +#if QT_CONFIG(signaling_nan) + QTest::newRow("signaling") << qSNaN(); +#endif } void tst_QNumeric::rawNaN() @@ -147,6 +153,15 @@ void tst_QNumeric::rawNaN() checkNaN(nan); } +#if QT_CONFIG(signaling_nan) +void tst_QNumeric::distinctNaN() +{ + const double qnan = qQNaN(); + const double snan = qSNaN(); + QVERIFY(memcmp(&qnan, &snan, sizeof(double)) != 0); +} +#endif + void tst_QNumeric::generalNaN_data() { QTest::addColumn<int>("most"); diff --git a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp index 6fa82ea681..c6733205e5 100644 --- a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp +++ b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp @@ -1413,10 +1413,12 @@ void tst_QCborValue::toCbor_data() // The rest of these tests are conversions whose decoding does not yield // back the same QCborValue. +#if QT_CONFIG(signaling_nan) // Signalling NaN get normalized to quiet ones QTest::newRow("Double:snan") << QCborValue(qSNaN()) << raw("\xfb\x7f\xf8\0""\0\0\0\0\0") << QCborValue::EncodingOptions(); QTest::newRow("Float:snan") << QCborValue(qSNaN()) << raw("\xfa\x7f\xc0\0\0") << QCborValue::EncodingOptions(QCborValue::UseFloat); QTest::newRow("Float16:snan") << QCborValue(qSNaN()) << raw("\xf9\x7e\0") << QCborValue::EncodingOptions(QCborValue::UseFloat16); +#endif // Floating point written as integers are read back as integers QTest::newRow("UseInteger:0") << QCborValue(0.) << raw("\x00") << QCborValue::EncodingOptions(QCborValue::UseIntegers); diff --git a/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp b/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp index 67cf9a321a..86a8965cec 100644 --- a/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp +++ b/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp @@ -88,7 +88,9 @@ private slots: void testToFillPolygons(); +#if QT_CONFIG(signaling_nan) void testNaNandInfinites(); +#endif void closing(); @@ -1228,6 +1230,7 @@ void tst_QPainterPath::testToFillPolygons() QCOMPARE(polygons.first().count(QPointF(70, 50)), 0); } +#if QT_CONFIG(signaling_nan) void tst_QPainterPath::testNaNandInfinites() { QPainterPath path1; @@ -1271,6 +1274,7 @@ void tst_QPainterPath::testNaNandInfinites() path1.lineTo(QPointF(1, 1)); QVERIFY(path1 != path2); } +#endif // signaling_nan void tst_QPainterPath::connectPathDuplicatePoint() { |