From e1eec6476a322488b491d34eb516e9a1f7fc43a2 Mon Sep 17 00:00:00 2001 From: Ivan Solovev Date: Fri, 2 Jun 2023 11:36:12 +0200 Subject: [PATCH] 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 Reviewed-by: Marc Mutz --- src/corelib/global/qfloat16.h | 56 ++++------ .../corelib/global/qfloat16/tst_qfloat16.cpp | 105 ++++++++++++++++++ 2 files changed, 129 insertions(+), 32 deletions(-) diff --git a/src/corelib/global/qfloat16.h b/src/corelib/global/qfloat16.h index f342428a334..f9625a72b9e 100644 --- a/src/corelib/global/qfloat16.h +++ b/src/corelib/global/qfloat16.h @@ -5,6 +5,7 @@ #ifndef QFLOAT16_H #define QFLOAT16_H +#include #include #include #include @@ -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(a) > static_cast(b); } - friend inline bool operator<(qfloat16 a, qfloat16 b) noexcept { return static_cast(a) < static_cast(b); } - friend inline bool operator>=(qfloat16 a, qfloat16 b) noexcept { return static_cast(a) >= static_cast(b); } - friend inline bool operator<=(qfloat16 a, qfloat16 b) noexcept { return static_cast(a) <= static_cast(b); } - friend inline bool operator==(qfloat16 a, qfloat16 b) noexcept { return static_cast(a) == static_cast(b); } - friend inline bool operator!=(qfloat16 a, qfloat16 b) noexcept { return static_cast(a) != static_cast(b); } + friend bool comparesEqual(const qfloat16 &lhs, const qfloat16 &rhs) noexcept + { return static_cast(lhs) == static_cast(rhs); } + friend Qt::partial_ordering compareThreeWay(const qfloat16 &lhs, const qfloat16 &rhs) noexcept + { return Qt::compareThreeWay(static_cast(lhs), static_cast(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(lhs) OP rhs; } \ - friend inline bool operator OP(FP lhs, qfloat16 rhs) noexcept { return lhs OP static_cast(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(lhs) == rhs; } \ + friend Qt::partial_ordering compareThreeWay(const qfloat16 &lhs, FP rhs) noexcept \ + { return Qt::compareThreeWay(static_cast(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(a) OP static_cast(b); } \ - friend inline bool operator OP(int a, qfloat16 b) noexcept { return static_cast(a) OP static_cast(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(lhs) == static_cast(rhs); } + friend Qt::partial_ordering compareThreeWay(const qfloat16 &lhs, int rhs) noexcept + { return Qt::compareThreeWay(static_cast(lhs), static_cast(rhs)); } + Q_DECLARE_PARTIALLY_ORDERED(qfloat16, int) QT_WARNING_POP diff --git a/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp b/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp index 7260c2900d4..e93d5d1838d 100644 --- a/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp +++ b/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp @@ -7,6 +7,8 @@ #include #include +#include + #include //#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(); + QTestPrivate::testAllComparisonOperatorsCompile(); + QTestPrivate::testAllComparisonOperatorsCompile(); + QTestPrivate::testAllComparisonOperatorsCompile(); +#if QFLOAT16_IS_NATIVE + QTestPrivate::testAllComparisonOperatorsCompile(); +#endif + QTestPrivate::testAllComparisonOperatorsCompile(); +} + +void tst_qfloat16::ordering_data() +{ + QTest::addColumn("left"); + QTest::addColumn("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::quiet_NaN(); + const float inf = std::numeric_limits::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(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(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("val1");