Implement qFpClassify(qfloat16)
This extends support for qfloat16 sufficiently for the things testlib needs in order to treat it as a first-class citizen. Extended tests for qfloat to check qFpClassify() on it. Change-Id: I906292afaf51cd9c94ba384ff5aaa855edd56da1 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
2eb849ed51
commit
934000c11a
@ -1,5 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Copyright (C) 2016 by Southwest Research Institute (R)
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
@ -39,6 +40,7 @@
|
||||
|
||||
#include "qfloat16.h"
|
||||
#include "private/qsimd_p.h"
|
||||
#include <cmath> // for fpclassify()'s return values
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
@ -91,6 +93,17 @@ QT_BEGIN_NAMESPACE
|
||||
\sa qIsFinite
|
||||
*/
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Implements qFpClassify() for qfloat16.
|
||||
*/
|
||||
|
||||
int qfloat16::fpClassify() const noexcept
|
||||
{
|
||||
return isInf() ? FP_INFINITE : isNaN() ? FP_NAN
|
||||
: !b16 ? FP_ZERO : isNormal() ? FP_NORMAL : FP_SUBNORMAL;
|
||||
}
|
||||
|
||||
/*! \fn int qRound(qfloat16 value)
|
||||
\relates <QFloat16>
|
||||
|
||||
|
@ -83,6 +83,7 @@ public:
|
||||
bool isInf() const noexcept { return ((b16 >> 8) & 0x7e) == 0x7c; }
|
||||
bool isNaN() const noexcept { return ((b16 >> 8) & 0x7e) == 0x7e; }
|
||||
bool isFinite() const noexcept { return ((b16 >> 8) & 0x7c) != 0x7c; }
|
||||
Q_CORE_EXPORT int fpClassify() const noexcept;
|
||||
// Support for std::numeric_limits<qfloat16>
|
||||
static constexpr qfloat16 _limit_epsilon() noexcept { return qfloat16(Wrap(0x1400)); }
|
||||
static constexpr qfloat16 _limit_min() noexcept { return qfloat16(Wrap(0x400)); }
|
||||
@ -117,6 +118,7 @@ Q_CORE_EXPORT void qFloatFromFloat16(float *, const qfloat16 *, qsizetype length
|
||||
Q_REQUIRED_RESULT inline bool qIsInf(qfloat16 f) noexcept { return f.isInf(); }
|
||||
Q_REQUIRED_RESULT inline bool qIsNaN(qfloat16 f) noexcept { return f.isNaN(); }
|
||||
Q_REQUIRED_RESULT inline bool qIsFinite(qfloat16 f) noexcept { return f.isFinite(); }
|
||||
Q_REQUIRED_RESULT inline int qFpClassify(qfloat16 f) noexcept { return f.fpClassify(); }
|
||||
// Q_REQUIRED_RESULT quint32 qFloatDistance(qfloat16 a, qfloat16 b);
|
||||
|
||||
// The remainder of these utility functions complement qglobal.h
|
||||
|
@ -390,12 +390,15 @@ void tst_qfloat16::limits()
|
||||
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)));
|
||||
@ -409,7 +412,9 @@ void tst_qfloat16::limits()
|
||||
QVERIFY(qIsInf(bit * two));
|
||||
bit = powf16(two, Bounds::min_exponent - 1);
|
||||
QVERIFY(bit.isNormal());
|
||||
QCOMPARE(qFpClassify(bit), FP_NORMAL);
|
||||
QVERIFY(!(bit / two).isNormal());
|
||||
QCOMPARE(qFpClassify(bit / two), FP_SUBNORMAL);
|
||||
QVERIFY(bit / two > zero);
|
||||
|
||||
// Base ten (with no matching off-by-one idiocy):
|
||||
@ -424,6 +429,7 @@ void tst_qfloat16::limits()
|
||||
QVERIFY(high10 > zero);
|
||||
QVERIFY(qIsFinite(high10));
|
||||
QVERIFY(!qIsFinite(high10 * ten));
|
||||
QCOMPARE(qFpClassify(high10), FP_NORMAL);
|
||||
|
||||
// How many digits are significant ? (Casts avoid linker errors ...)
|
||||
QCOMPARE(int(Bounds::digits10), 3); // 9.79e-4 has enough sigificant digits:
|
||||
@ -449,34 +455,46 @@ void tst_qfloat16::limits()
|
||||
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()));
|
||||
@ -485,6 +503,7 @@ void tst_qfloat16::limits()
|
||||
if (overOptimised)
|
||||
QEXPECT_FAIL("", "Over-optimised on QEMU", Continue);
|
||||
QCOMPARE(Bounds::denorm_min() / rose, zero);
|
||||
QCOMPARE(qFpClassify(Bounds::denorm_min()), FP_SUBNORMAL);
|
||||
}
|
||||
|
||||
QTEST_APPLESS_MAIN(tst_qfloat16)
|
||||
|
Loading…
Reference in New Issue
Block a user