summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/global
diff options
context:
space:
mode:
authorEdward Welbourne <edward.welbourne@qt.io>2019-09-17 18:19:59 +0200
committerEdward Welbourne <edward.welbourne@qt.io>2019-10-03 11:09:47 +0200
commitb4efdd376996f98375146d154c1dc7737c0edc38 (patch)
treed4b7a3bacb65b2046db402b5e84bb3c50c8ade2a /tests/auto/corelib/global
parent2e068c7f2aca6a40bcf1e4c5bc85c26f478fe786 (diff)
Reorganise the qfloat16 auto-test
Its limits() test was rather large and had some overlap with an older qNan() test, that needed some clean-up (it combined qfloat16 values with double and float values in ways that caused qfloat16 to be promoted to another type, so we weren't testing qfloat16). Renamed the qNan() test to qNaN(), separated out the parts of it that actually tested infinity. Moved various parts of limits() to these and rationalised the result. Split out a properties() test from limits() for the properties of the qfloat16 type that are supplied by its numeric_limits. Split out a data-driven finite() test to cover some repeated code that was in limits() and extended it to test more values. Added more tests of isNormal(). Fixed my earlier UK-ish spelling of "optimise", in the process, and identify the processor rather than the virtualization as the context where the compiler errs. Change-Id: I8133da6fb7995ee20e5802c6357d611c8c0cba73 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'tests/auto/corelib/global')
-rw-r--r--tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp186
1 files changed, 102 insertions, 84 deletions
diff --git a/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp b/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp
index 5c7737085e..01a1789188 100644
--- a/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp
+++ b/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp
@@ -41,7 +41,8 @@ private slots:
void fuzzyCompare();
void ltgt_data();
void ltgt();
- void qNan();
+ void qNaN();
+ void infinity();
void float_cast();
void float_cast_data();
void promotionTests();
@@ -49,6 +50,9 @@ private slots:
void arithOps();
void floatToFloat16();
void floatFromFloat16();
+ void finite_data();
+ void finite();
+ void properties();
void limits();
};
@@ -154,38 +158,66 @@ void tst_qfloat16::ltgt()
# pragma GCC optimize "no-fast-math"
#endif
-void tst_qfloat16::qNan()
+void tst_qfloat16::qNaN()
{
#if defined __FAST_MATH__ && (__GNUC__ * 100 + __GNUC_MINOR__ < 404)
QSKIP("Non-conformant fast math mode is enabled, cannot run test");
#endif
- qfloat16 nan = qQNaN();
- QVERIFY(!(0. > nan));
- QVERIFY(!(0. < nan));
+ using Bounds = std::numeric_limits<qfloat16>;
+ const qfloat16 nan = Bounds::quiet_NaN();
+ const qfloat16 zero(0), one(1);
+ QVERIFY(!(zero > nan));
+ QVERIFY(!(zero < nan));
+ QVERIFY(!(zero == nan));
QVERIFY(!qIsInf(nan));
QVERIFY(qIsNaN(nan));
- QVERIFY(qIsNaN(nan + 1.f));
+ QVERIFY(qIsNaN(nan + one));
QVERIFY(qIsNaN(-nan));
- qfloat16 inf = qInf();
- QVERIFY(inf > qfloat16(0));
- QVERIFY(-inf < qfloat16(0));
- QVERIFY(!qIsNaN(inf));
- QVERIFY(qIsInf(inf));
- QVERIFY(qIsInf(-inf));
- QVERIFY(qIsInf(2.f*inf));
- QVERIFY(qIsInf(inf*2.f));
- // QTBUG-75812: QEMU/arm64 compiler over-optimizes, so flakily fails 1/inf == 0 :-(
- if (qfloat16(9.785e-4f) == qfloat16(9.794e-4f))
- QCOMPARE(qfloat16(1.f) / inf, qfloat16(0.f));
#ifdef Q_CC_INTEL
QEXPECT_FAIL("", "ICC optimizes zero * anything to zero", Continue);
#endif
- QVERIFY(qIsNaN(nan*0.f));
+ QVERIFY(qIsNaN(nan * zero));
#ifdef Q_CC_INTEL
QEXPECT_FAIL("", "ICC optimizes zero * anything to zero", Continue);
#endif
- QVERIFY(qIsNaN(inf*0.f));
- QVERIFY(qFuzzyCompare(qfloat16(1.f/inf), qfloat16(0.0)));
+ QVERIFY(qIsNaN(Bounds::infinity() * zero));
+
+ QVERIFY(!nan.isNormal());
+ QVERIFY(!qIsFinite(nan));
+ QVERIFY(!(nan == nan));
+ QCOMPARE(nan, nan); // Despite the preceding
+ QCOMPARE(qFpClassify(nan), FP_NAN);
+}
+
+void tst_qfloat16::infinity()
+{
+ const qfloat16 huge = std::numeric_limits<qfloat16>::infinity();
+ const qfloat16 zero(0), one(1), two(2);
+ QVERIFY(huge > -huge);
+ QVERIFY(huge > zero);
+ QVERIFY(-huge < zero);
+ QCOMPARE(huge, huge);
+ QCOMPARE(-huge, -huge);
+
+ // QTBUG-75812 - see overOptimized in the limits() test.
+ if (qfloat16(9.785e-4f) == qfloat16(9.794e-4f)) {
+ QCOMPARE(one / huge, zero);
+ QVERIFY(qFuzzyCompare(one / huge, zero)); // (same thing)
+ }
+
+ QVERIFY(qIsInf(huge));
+ QVERIFY(qIsInf(-huge));
+ QVERIFY(qIsInf(two * huge));
+ QVERIFY(qIsInf(huge * two));
+
+ QVERIFY(!huge.isNormal());
+ QVERIFY(!(-huge).isNormal());
+ QVERIFY(!qIsNaN(huge));
+ QVERIFY(!qIsNaN(-huge));
+ QVERIFY(!qIsFinite(huge));
+ QVERIFY(!qIsFinite(-huge));
+ QCOMPARE(qFpClassify(huge), FP_INFINITE);
+ QCOMPARE(qFpClassify(-huge), FP_INFINITE);
}
void tst_qfloat16::float_cast_data()
@@ -366,10 +398,40 @@ static qfloat16 powf16(qfloat16 base, int raise)
return answer;
}
-void tst_qfloat16::limits()
+void tst_qfloat16::finite_data()
+{
+ using Bounds = std::numeric_limits<qfloat16>;
+ QTest::addColumn<qfloat16>("value");
+ QTest::addColumn<int>("mode");
+
+ QTest::newRow("zero") << qfloat16(0) << FP_ZERO;
+ QTest::newRow("one") << qfloat16(1) << FP_NORMAL;
+ QTest::newRow("-one") << qfloat16(-1) << FP_NORMAL;
+ QTest::newRow("ten") << qfloat16(10) << FP_NORMAL;
+ QTest::newRow("-ten") << qfloat16(-10) << FP_NORMAL;
+ QTest::newRow("max") << Bounds::max() << FP_NORMAL;
+ QTest::newRow("lowest") << Bounds::lowest() << FP_NORMAL;
+ QTest::newRow("min") << Bounds::min() << FP_NORMAL;
+ QTest::newRow("-min") << -Bounds::min() << FP_NORMAL;
+ QTest::newRow("denorm_min") << Bounds::denorm_min() << FP_SUBNORMAL;
+ QTest::newRow("-denorm_min") << -Bounds::denorm_min() << FP_SUBNORMAL;
+}
+
+void tst_qfloat16::finite()
+{
+ QFETCH(qfloat16, value);
+ QFETCH(int, mode);
+ QCOMPARE(value.isNormal(), mode != FP_SUBNORMAL);
+ QCOMPARE(value, value); // Fuzzy
+ QVERIFY(value == value); // Exact
+ QVERIFY(qIsFinite(value));
+ QVERIFY(!qIsInf(value));
+ QVERIFY(!qIsNaN(value));
+ QCOMPARE(qFpClassify(value), mode);
+}
+
+void tst_qfloat16::properties()
{
- // *NOT* using QCOMPARE() on finite qfloat16 values, since that uses fuzzy
- // comparison, and we need exact here.
using Bounds = std::numeric_limits<qfloat16>;
QVERIFY(Bounds::is_specialized);
QVERIFY(Bounds::is_signed);
@@ -386,21 +448,16 @@ void tst_qfloat16::limits()
QCOMPARE(Bounds::round_style, std::round_to_nearest);
QCOMPARE(Bounds::radix, 2);
// Untested: has_denorm_loss
+}
+
+void tst_qfloat16::limits() // See also: qNaN() and infinity()
+{
+ // *NOT* using QCOMPARE() on finite qfloat16 values, since that uses fuzzy
+ // comparison, and we need exact here.
+ using Bounds = std::numeric_limits<qfloat16>;
- // A few common values:
+ // A few useful values:
const qfloat16 zero(0), one(1), ten(10);
- QVERIFY(qIsFinite(zero));
- QVERIFY(!qIsInf(zero));
- QVERIFY(!qIsNaN(zero));
- QCOMPARE(qFpClassify(zero), FP_ZERO);
- QVERIFY(qIsFinite(one));
- QVERIFY(!qIsInf(one));
- QCOMPARE(qFpClassify(one), FP_NORMAL);
- QVERIFY(!qIsNaN(one));
- QVERIFY(qIsFinite(ten));
- QVERIFY(!qIsInf(ten));
- QVERIFY(!qIsNaN(ten));
- QCOMPARE(qFpClassify(ten), FP_NORMAL);
// digits in the mantissa, including the implicit 1 before the binary dot at its left:
QVERIFY(qfloat16(1 << (Bounds::digits - 1)) + one > qfloat16(1 << (Bounds::digits - 1)));
@@ -436,12 +493,12 @@ void tst_qfloat16::limits()
// How many digits are significant ? (Casts avoid linker errors ...)
QCOMPARE(int(Bounds::digits10), 3); // 9.79e-4 has enough sigificant digits:
qfloat16 below(9.785e-4f), above(9.794e-4f);
-#if 0 // Sadly, the QEMU x-compile for arm64 "optimises" comparisons:
- const bool overOptimised = false;
+#if 0 // Sadly, the QEMU x-compile for arm64 "optimizes" comparisons:
+ const bool overOptimized = false;
#else
- const bool overOptimised = (below != above);
- if (overOptimised)
- QEXPECT_FAIL("", "Over-optimised on QEMU", Continue);
+ const bool overOptimized = (below != above);
+ if (overOptimized)
+ QEXPECT_FAIL("", "Over-optimized on ARM", Continue);
#endif // (but it did, so should, pass everywhere else, confirming digits10 is indeed 3).
QVERIFY(below == above);
QCOMPARE(int(Bounds::max_digits10), 5); // we need 5 to distinguish these two:
@@ -450,62 +507,23 @@ void tst_qfloat16::limits()
// Actual limiting values of the type:
const qfloat16 rose(one + Bounds::epsilon());
QVERIFY(rose > one);
- if (overOptimised)
- QEXPECT_FAIL("", "Over-optimised on QEMU", Continue);
+ if (overOptimized)
+ QEXPECT_FAIL("", "Over-optimized on ARM", Continue);
QVERIFY(one + Bounds::epsilon() / rose == one);
- QVERIFY(qIsInf(Bounds::infinity()));
- QVERIFY(!qIsNaN(Bounds::infinity()));
- QVERIFY(!qIsFinite(Bounds::infinity()));
- QCOMPARE(Bounds::infinity(), Bounds::infinity());
- QCOMPARE(qFpClassify(Bounds::infinity()), FP_INFINITE);
-
- QVERIFY(Bounds::infinity() > -Bounds::infinity());
- QVERIFY(Bounds::infinity() > zero);
- QVERIFY(qIsInf(-Bounds::infinity()));
- QVERIFY(!qIsNaN(-Bounds::infinity()));
- QVERIFY(!qIsFinite(-Bounds::infinity()));
- QCOMPARE(-Bounds::infinity(), -Bounds::infinity());
- QCOMPARE(qFpClassify(-Bounds::infinity()), FP_INFINITE);
-
- QVERIFY(-Bounds::infinity() < zero);
- QVERIFY(qIsNaN(Bounds::quiet_NaN()));
- QVERIFY(!qIsInf(Bounds::quiet_NaN()));
- QVERIFY(!qIsFinite(Bounds::quiet_NaN()));
- QVERIFY(!(Bounds::quiet_NaN() == Bounds::quiet_NaN()));
- QCOMPARE(Bounds::quiet_NaN(), Bounds::quiet_NaN());
- QCOMPARE(qFpClassify(Bounds::quiet_NaN()), FP_NAN);
QVERIFY(Bounds::max() > zero);
- QVERIFY(qIsFinite(Bounds::max()));
- QVERIFY(!qIsInf(Bounds::max()));
- QVERIFY(!qIsNaN(Bounds::max()));
QVERIFY(qIsInf(Bounds::max() * rose));
- QCOMPARE(qFpClassify(Bounds::max()), FP_NORMAL);
QVERIFY(Bounds::lowest() < zero);
- QVERIFY(qIsFinite(Bounds::lowest()));
- QVERIFY(!qIsInf(Bounds::lowest()));
- QVERIFY(!qIsNaN(Bounds::lowest()));
QVERIFY(qIsInf(Bounds::lowest() * rose));
- QCOMPARE(qFpClassify(Bounds::lowest()), FP_NORMAL);
QVERIFY(Bounds::min() > zero);
- QVERIFY(Bounds::min().isNormal());
QVERIFY(!(Bounds::min() / rose).isNormal());
- QVERIFY(qIsFinite(Bounds::min()));
- QVERIFY(!qIsInf(Bounds::min()));
- QVERIFY(!qIsNaN(Bounds::min()));
- QCOMPARE(qFpClassify(Bounds::min()), FP_NORMAL);
QVERIFY(Bounds::denorm_min() > zero);
- QVERIFY(!Bounds::denorm_min().isNormal());
- QVERIFY(qIsFinite(Bounds::denorm_min()));
- QVERIFY(!qIsInf(Bounds::denorm_min()));
- QVERIFY(!qIsNaN(Bounds::denorm_min()));
- if (overOptimised)
- QEXPECT_FAIL("", "Over-optimised on QEMU", Continue);
+ if (overOptimized)
+ QEXPECT_FAIL("", "Over-optimized on ARM", Continue);
QCOMPARE(Bounds::denorm_min() / rose, zero);
- QCOMPARE(qFpClassify(Bounds::denorm_min()), FP_SUBNORMAL);
}
QTEST_APPLESS_MAIN(tst_qfloat16)