summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/global
diff options
context:
space:
mode:
authorEdward Welbourne <edward.welbourne@qt.io>2019-09-18 11:32:50 +0200
committerEdward Welbourne <edward.welbourne@qt.io>2019-09-23 14:57:48 +0200
commit35aec918c15d50893dd4e403e400f37e6a2d7c6f (patch)
treed31b448586d308acb7174740661e9313a758dbc0 /tests/auto/corelib/global
parent2dfeea921b8ac9fef92db8fab7b518f3f5994512 (diff)
Rearrange tst_QNumeric's tests for infinity and (quiet) NaN
Separate quiet NaN from infinity and expand the nan-with-payload test to a general test that bits outside the exponent don't break qIsNan(). Generally test more thoroughly and systematically. Tests for signalling NaN shall follow. Change-Id: Ib35dabacc8ebcc9a0761df38f6f419f0398d0e20 Reviewed-by: Erik Verbruggen <erik.verbruggen@me.com>
Diffstat (limited to 'tests/auto/corelib/global')
-rw-r--r--tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp110
1 files changed, 84 insertions, 26 deletions
diff --git a/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp b/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp
index 0a84b1fdd8..5697d21547 100644
--- a/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp
+++ b/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp
@@ -42,7 +42,11 @@ class tst_QNumeric: public QObject
private slots:
void fuzzyCompare_data();
void fuzzyCompare();
- void qNanInf();
+ void rawNaN_data();
+ void rawNaN();
+ void generalNaN_data();
+ void generalNaN();
+ void infinity();
void classifyfp();
void floatDistance_data();
void floatDistance();
@@ -53,6 +57,8 @@ private slots:
void mulOverflow_data();
void mulOverflow();
void signedOverflow();
+private:
+ void checkNaN(double nan);
};
void tst_QNumeric::fuzzyCompare_data()
@@ -92,44 +98,89 @@ void tst_QNumeric::fuzzyCompare()
# pragma GCC optimize "no-fast-math"
#endif
-void tst_QNumeric::qNanInf()
+void tst_QNumeric::checkNaN(double nan)
{
-#if defined __FAST_MATH__ && (__GNUC__ * 100 + __GNUC_MINOR__ < 404)
- QSKIP("Non-conformant fast math mode is enabled, cannot run test");
-#endif
- double nan = qQNaN();
+#define CHECKNAN(value) \
+ do { \
+ const double v = (value); \
+ QCOMPARE(qFpClassify(v), FP_NAN); \
+ QVERIFY(qIsNaN(v)); \
+ QVERIFY(!qIsFinite(v)); \
+ QVERIFY(!qIsInf(v)); \
+ } while (0)
+
QVERIFY(!(0 > nan));
QVERIFY(!(0 < nan));
QVERIFY(!(0 == nan));
QVERIFY(!(nan == nan));
- QVERIFY(qIsNaN(nan));
- QVERIFY(qIsNaN(nan + 1));
- QVERIFY(qIsNaN(-nan));
- QVERIFY(qIsNaN(1.0 / nan));
- QVERIFY(qIsNaN(0.0 / nan));
- QVERIFY(qIsNaN(0.0 * nan));
+
+ CHECKNAN(nan);
+ CHECKNAN(nan + 1);
+ CHECKNAN(nan - 1);
+ CHECKNAN(-nan);
+ CHECKNAN(nan * 2.0);
+ CHECKNAN(nan / 2.0);
+ CHECKNAN(1.0 / nan);
+ CHECKNAN(0.0 / nan);
+ CHECKNAN(0.0 * nan);
+
+ // When any NaN is expected, any NaN will do:
QCOMPARE(nan, nan);
QCOMPARE(nan, -nan);
+ QCOMPARE(nan, qQNaN());
+#undef CHECKNAN
+}
+
+void tst_QNumeric::rawNaN_data()
+{
+#if defined __FAST_MATH__ && (__GNUC__ * 100 + __GNUC_MINOR__ < 404)
+ QSKIP("Non-conformant fast math mode is enabled, cannot run test");
+#endif
+ QTest::addColumn<double>("nan");
+
+ QTest::newRow("quiet") << qQNaN();
+}
+void tst_QNumeric::rawNaN()
+{
+ QFETCH(double, nan);
+ checkNaN(nan);
+}
+
+void tst_QNumeric::generalNaN_data()
+{
+ QTest::addColumn<int>("most");
+ QTest::addColumn<int>("next");
+ QTest::addColumn<int>("least");
+ // Every value with every bit of the exponent set is a NaN.
+ // Sign and mantissa can be anything without interfering with that.
+ // The 0x7f bits of most and the 0xf0 bits of next are the exponent.
+
+ QTest::newRow("lowload") << 0x7f << 0xf0 << 1;
+ QTest::newRow("sign-lowload") << 0xff << 0xf0 << 1;
+ QTest::newRow("highload") << 0x7f << 0xf1 << 0;
+ QTest::newRow("sign-highload") << 0xff << 0xf1 << 0;
+}
+
+void tst_QNumeric::generalNaN()
+{
+ QFETCH(int, most);
+ QFETCH(int, next);
+ QFETCH(int, least);
+ double nan;
Q_STATIC_ASSERT(sizeof(double) == 8);
#ifdef Q_LITTLE_ENDIAN
- const uchar bytes[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f };
+ const uchar bytes[] = { uchar(least), 0, 0, 0, 0, 0, uchar(next), uchar(most) };
#else
- const uchar bytes[] = { 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
+ const uchar bytes[] = { uchar(most), uchar(next), 0, 0, 0, 0, 0, uchar(least) };
#endif
memcpy(&nan, bytes, 8);
- QVERIFY(!qIsFinite(nan));
- QVERIFY(!qIsInf(nan));
- QVERIFY(qIsNaN(nan));
- QVERIFY(qIsNaN(-nan));
- QVERIFY(!(nan == nan));
- QVERIFY(qIsNaN(0.0 * nan));
- QCOMPARE(qFpClassify(nan), FP_NAN);
- QCOMPARE(nan, nan);
- QCOMPARE(nan, -nan);
- QCOMPARE(nan, qQNaN());
+ checkNaN(nan);
+}
- double inf = qInf();
+void tst_QNumeric::infinity()
+{
+ const double inf = qInf();
QVERIFY(inf > 0);
QVERIFY(-inf < 0);
QVERIFY(qIsInf(inf));
@@ -138,16 +189,23 @@ void tst_QNumeric::qNanInf()
QVERIFY(qIsInf(-inf));
QVERIFY(qIsInf(inf + 1));
QVERIFY(qIsInf(inf - 1));
+ QVERIFY(qIsInf(-inf - 1));
+ QVERIFY(qIsInf(-inf + 1));
QVERIFY(qIsInf(inf * 2.0));
+ QVERIFY(qIsInf(-inf * 2.0));
QVERIFY(qIsInf(inf / 2.0));
+ QVERIFY(qIsInf(-inf / 2.0));
QVERIFY(qFuzzyCompare(1.0 / inf, 0.0));
QCOMPARE(1.0 / inf, 0.0);
+ QVERIFY(qFuzzyCompare(1.0 / -inf, 0.0));
+ QCOMPARE(1.0 / -inf, 0.0);
QVERIFY(qIsNaN(0.0 * inf));
+ QVERIFY(qIsNaN(0.0 * -inf));
}
void tst_QNumeric::classifyfp()
{
- QCOMPARE(qFpClassify(qQNaN()), FP_NAN);
+ // NaNs already handled, see checkNaN()'s callers.
QCOMPARE(qFpClassify(qInf()), FP_INFINITE);
QCOMPARE(qFpClassify(-qInf()), FP_INFINITE);