qfloat16: use new comparison helper macros

This replaces all the other helper macros which were used to
generate the relational operators before, and also gains support for
operator<=>() in C++20 mode.

Change-Id: I40cec3cb5a5c42523787414d610e00afe6fc86f8
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
This commit is contained in:
Ivan Solovev 2023-06-02 11:36:12 +02:00
parent 706dafe347
commit e1eec6476a
2 changed files with 129 additions and 32 deletions

View File

@ -5,6 +5,7 @@
#ifndef QFLOAT16_H
#define QFLOAT16_H
#include <QtCore/qcompare.h>
#include <QtCore/qglobal.h>
#include <QtCore/qhashfunctions.h>
#include <QtCore/qmath.h>
@ -167,41 +168,32 @@ private:
QT_WARNING_PUSH
QT_WARNING_DISABLE_FLOAT_COMPARE
friend inline bool operator>(qfloat16 a, qfloat16 b) noexcept { return static_cast<NearestFloat>(a) > static_cast<NearestFloat>(b); }
friend inline bool operator<(qfloat16 a, qfloat16 b) noexcept { return static_cast<NearestFloat>(a) < static_cast<NearestFloat>(b); }
friend inline bool operator>=(qfloat16 a, qfloat16 b) noexcept { return static_cast<NearestFloat>(a) >= static_cast<NearestFloat>(b); }
friend inline bool operator<=(qfloat16 a, qfloat16 b) noexcept { return static_cast<NearestFloat>(a) <= static_cast<NearestFloat>(b); }
friend inline bool operator==(qfloat16 a, qfloat16 b) noexcept { return static_cast<NearestFloat>(a) == static_cast<NearestFloat>(b); }
friend inline bool operator!=(qfloat16 a, qfloat16 b) noexcept { return static_cast<NearestFloat>(a) != static_cast<NearestFloat>(b); }
friend bool comparesEqual(const qfloat16 &lhs, const qfloat16 &rhs) noexcept
{ return static_cast<NearestFloat>(lhs) == static_cast<NearestFloat>(rhs); }
friend Qt::partial_ordering compareThreeWay(const qfloat16 &lhs, const qfloat16 &rhs) noexcept
{ return Qt::compareThreeWay(static_cast<NearestFloat>(lhs), static_cast<NearestFloat>(rhs)); }
Q_DECLARE_PARTIALLY_ORDERED(qfloat16)
#define QF16_MAKE_BOOL_OP_FP(FP, OP) \
friend inline bool operator OP(qfloat16 lhs, FP rhs) noexcept { return static_cast<FP>(lhs) OP rhs; } \
friend inline bool operator OP(FP lhs, qfloat16 rhs) noexcept { return lhs OP static_cast<FP>(rhs); }
#define QF16_MAKE_BOOL_OP(FP) \
QF16_MAKE_BOOL_OP_FP(FP, <) \
QF16_MAKE_BOOL_OP_FP(FP, >) \
QF16_MAKE_BOOL_OP_FP(FP, >=) \
QF16_MAKE_BOOL_OP_FP(FP, <=) \
QF16_MAKE_BOOL_OP_FP(FP, ==) \
QF16_MAKE_BOOL_OP_FP(FP, !=)
#define QF16_MAKE_ORDER_OP_FP(FP) \
friend bool comparesEqual(const qfloat16 &lhs, FP rhs) noexcept \
{ return static_cast<FP>(lhs) == rhs; } \
friend Qt::partial_ordering compareThreeWay(const qfloat16 &lhs, FP rhs) noexcept \
{ return Qt::compareThreeWay(static_cast<FP>(lhs), rhs); } \
Q_DECLARE_PARTIALLY_ORDERED(qfloat16, FP)
QF16_MAKE_BOOL_OP(long double)
QF16_MAKE_BOOL_OP(double)
QF16_MAKE_BOOL_OP(float)
#undef QF16_MAKE_BOOL_OP
#undef QF16_MAKE_BOOL_OP_FP
QF16_MAKE_ORDER_OP_FP(long double)
QF16_MAKE_ORDER_OP_FP(double)
QF16_MAKE_ORDER_OP_FP(float)
#if QFLOAT16_IS_NATIVE
QF16_MAKE_ORDER_OP_FP(qfloat16::NativeType)
#endif
#undef QF16_MAKE_ORDER_OP_FP
#define QF16_MAKE_BOOL_OP_INT(OP) \
friend inline bool operator OP(qfloat16 a, int b) noexcept { return static_cast<NearestFloat>(a) OP static_cast<NearestFloat>(b); } \
friend inline bool operator OP(int a, qfloat16 b) noexcept { return static_cast<NearestFloat>(a) OP static_cast<NearestFloat>(b); }
QF16_MAKE_BOOL_OP_INT(>)
QF16_MAKE_BOOL_OP_INT(<)
QF16_MAKE_BOOL_OP_INT(>=)
QF16_MAKE_BOOL_OP_INT(<=)
QF16_MAKE_BOOL_OP_INT(==)
QF16_MAKE_BOOL_OP_INT(!=)
#undef QF16_MAKE_BOOL_OP_INT
friend bool comparesEqual(const qfloat16 &lhs, int rhs) noexcept
{ return static_cast<NearestFloat>(lhs) == static_cast<NearestFloat>(rhs); }
friend Qt::partial_ordering compareThreeWay(const qfloat16 &lhs, int rhs) noexcept
{ return Qt::compareThreeWay(static_cast<NearestFloat>(lhs), static_cast<NearestFloat>(rhs)); }
Q_DECLARE_PARTIALLY_ORDERED(qfloat16, int)
QT_WARNING_POP

View File

@ -7,6 +7,8 @@
#include <QMetaType>
#include <QTextStream>
#include <private/qcomparisontesthelper_p.h>
#include <math.h>
//#define DO_FULL_TEST
@ -18,6 +20,9 @@ class tst_qfloat16: public QObject
Q_OBJECT
private slots:
void compareCompiles();
void ordering_data();
void ordering();
void fuzzyCompare_data();
void fuzzyCompare();
void fuzzyIsNull_data();
@ -47,6 +52,106 @@ private slots:
void textStream();
};
void tst_qfloat16::compareCompiles()
{
QTestPrivate::testAllComparisonOperatorsCompile<qfloat16>();
QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, float>();
QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, double>();
QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, long double>();
#if QFLOAT16_IS_NATIVE
QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, qfloat16::NativeType>();
#endif
QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, int>();
}
void tst_qfloat16::ordering_data()
{
QTest::addColumn<float>("left");
QTest::addColumn<float>("right");
auto row = [](float left, float right) {
QTest::addRow("%f_vs_%f", left, right) << left << right;
};
row(0.0f, 0.0f);
row(0.000001f, 0.0f);
row(0.0f, 0.000001f);
row(-1.000001f, 1.000001f);
const float nan = std::numeric_limits<float>::quiet_NaN();
const float inf = std::numeric_limits<float>::infinity();
row(nan, nan);
row(nan, inf);
row(inf, nan);
row(-inf, nan);
row(nan, -inf);
row(-inf, inf);
row(inf, -inf);
row(-inf, 0.0f);
row(0.0f, inf);
row(0.0f, nan);
row(nan, 0.0f);
row(2.0f, 314.159f);
row(-314.159f, 2.0f);
row(-2.0f, 314.159f);
row(nan, 314.159f);
row(-314.159f, inf);
row(-inf, 314.159f);
row(2.0f, -inf);
row(-2.0f, nan);
row(-inf, -2.0f);
// testing with values outside qfloat16 range
row(0.0f, 13e5f);
// generateRow(inf, 13e5f); // fails qfloat16 vs qfloat16 and qfloat16 vs int (QTBUG-118193)
row(0.0f, -13e5f);
// generateRow(-inf, -13e5f); // fails qfloat16 vs qfloat16 and qfloat16 vs int (QTBUG-118193)
}
void tst_qfloat16::ordering()
{
QFETCH(float, left);
QFETCH(float, right);
const auto expectedOrder = Qt::compareThreeWay(left, right);
const auto lhs = qfloat16(left);
#define POSTCHECK(msg) \
if (QTest::currentTestFailed()) { qDebug(msg); return; }
#define CHECK_FP(RHS) \
do { \
QTestPrivate::testAllComparisonOperators(lhs, static_cast<RHS>(right), expectedOrder); \
POSTCHECK("qfloat16 vs " #RHS " comparison failed") \
} while (false) \
/* END */
CHECK_FP(qfloat16);
CHECK_FP(float);
CHECK_FP(double);
CHECK_FP(long double);
#undef CHECK_FP
#define CHECK_INT(RHS) \
do { \
const auto rhs = static_cast<RHS>(right); \
const auto expectedRes = Qt::compareThreeWay(left, rhs); \
QTestPrivate::testAllComparisonOperators(lhs, rhs, expectedRes); \
POSTCHECK("qfloat16 vs " #RHS " comparison failed") \
} while (false) \
/* END */
if (qIsFinite(right)) {
CHECK_INT(int);
// These fail because of QTBUG-117637. Will be fixed in a follow-up patch.
// CHECK_INT(qint8);
// CHECK_INT(qint16);
// CHECK_INT(qint64);
}
#undef CHECK_INT
#undef POSTCHECK
}
void tst_qfloat16::fuzzyCompare_data()
{
QTest::addColumn<qfloat16>("val1");