summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp')
-rw-r--r--tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp147
1 files changed, 126 insertions, 21 deletions
diff --git a/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp b/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp
index 03300c6dbe..5697d21547 100644
--- a/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp
+++ b/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
@@ -42,7 +42,12 @@ class tst_QNumeric: public QObject
private slots:
void fuzzyCompare_data();
void fuzzyCompare();
- void qNan();
+ void rawNaN_data();
+ void rawNaN();
+ void generalNaN_data();
+ void generalNaN();
+ void infinity();
+ void classifyfp();
void floatDistance_data();
void floatDistance();
void floatDistance_double_data();
@@ -52,6 +57,8 @@ private slots:
void mulOverflow_data();
void mulOverflow();
void signedOverflow();
+private:
+ void checkNaN(double nan);
};
void tst_QNumeric::fuzzyCompare_data()
@@ -91,39 +98,137 @@ void tst_QNumeric::fuzzyCompare()
# pragma GCC optimize "no-fast-math"
#endif
-void tst_QNumeric::qNan()
+void tst_QNumeric::checkNaN(double nan)
+{
+#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));
+
+ 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
- double nan = qQNaN();
- QVERIFY(!(0 > nan));
- QVERIFY(!(0 < nan));
- QVERIFY(qIsNaN(nan));
- QVERIFY(qIsNaN(nan + 1));
- QVERIFY(qIsNaN(-nan));
+ 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));
+ checkNaN(nan);
+}
- double inf = qInf();
+void tst_QNumeric::infinity()
+{
+ const double inf = qInf();
QVERIFY(inf > 0);
QVERIFY(-inf < 0);
QVERIFY(qIsInf(inf));
+ QCOMPARE(inf, inf);
+ QCOMPARE(-inf, -inf);
QVERIFY(qIsInf(-inf));
- QVERIFY(qIsInf(2*inf));
- QCOMPARE(1/inf, 0.0);
- QVERIFY(qIsNaN(0*nan));
- QVERIFY(qIsNaN(0*inf));
- QVERIFY(qFuzzyCompare(1/inf, 0.0));
+ 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()
+{
+ // NaNs already handled, see checkNaN()'s callers.
+
+ QCOMPARE(qFpClassify(qInf()), FP_INFINITE);
+ QCOMPARE(qFpClassify(-qInf()), FP_INFINITE);
+ QCOMPARE(qFpClassify(DBL_MAX * 2.0), FP_INFINITE);
+ QCOMPARE(qFpClassify(FLT_MAX * 2.f), FP_INFINITE);
+ QCOMPARE(qFpClassify(DBL_MAX * -2.0), FP_INFINITE);
+ QCOMPARE(qFpClassify(FLT_MAX * -2.f), FP_INFINITE);
+
+ QCOMPARE(qFpClassify(1.0), FP_NORMAL);
+ QCOMPARE(qFpClassify(DBL_MAX), FP_NORMAL);
+ QCOMPARE(qFpClassify(-DBL_MAX), FP_NORMAL);
+ QCOMPARE(qFpClassify(DBL_MIN), FP_NORMAL);
+ QCOMPARE(qFpClassify(-DBL_MIN), FP_NORMAL);
+ QCOMPARE(qFpClassify(DBL_MIN / 2.0), FP_SUBNORMAL);
+ QCOMPARE(qFpClassify(DBL_MIN / -2.0), FP_SUBNORMAL);
+
+ QCOMPARE(qFpClassify(1.f), FP_NORMAL);
+ QCOMPARE(qFpClassify(FLT_MAX), FP_NORMAL);
+ QCOMPARE(qFpClassify(-FLT_MAX), FP_NORMAL);
+ QCOMPARE(qFpClassify(FLT_MIN), FP_NORMAL);
+ QCOMPARE(qFpClassify(-FLT_MIN), FP_NORMAL);
+ QCOMPARE(qFpClassify(FLT_MIN / 2.f), FP_SUBNORMAL);
+ QCOMPARE(qFpClassify(FLT_MIN / -2.f), FP_SUBNORMAL);
}
void tst_QNumeric::floatDistance_data()
@@ -461,13 +566,13 @@ template <typename Int> static void mulOverflow_template()
QCOMPARE(mul_overflow(Int(max / 2), Int(3), &r), true);
QCOMPARE(mul_overflow(mid1, Int(mid2 + 1), &r), true);
QCOMPARE(mul_overflow(Int(max / 2 + 2), Int(2), &r), true);
+ QCOMPARE(mul_overflow(Int(max - max / 2), Int(2), &r), true);
QCOMPARE(mul_overflow(Int(1ULL << (std::numeric_limits<Int>::digits - 1)), Int(2), &r), true);
if (min) {
QCOMPARE(mul_overflow(min, Int(2), &r), true);
QCOMPARE(mul_overflow(Int(min / 2), Int(3), &r), true);
QCOMPARE(mul_overflow(Int(min / 2 - 1), Int(2), &r), true);
- QCOMPARE(mul_overflow(Int(min + min/2), Int(2), &r), true);
}
#endif
}