qfloat16: extend comparison with integral types
qfloat16 implemented comparison with int, but not with other integral types. As a result, comparing qfloat16 vs qint64 or short was ambiguous, because the compiler had (at least) two options: * qint64 -> int * qint64 -> float Fix it by explicitly introducing comparison operators for other integral types. Use the new compare helper macros for that, and implement helper methods as templates restricted on integral types. Note that we have to manually extend the std::is_integral type trait because libstdc++ only treats __{u}int128_t types as integral when compiling in -std=gnu++XX mode, and we compile Qt in -std=c++XX mode. Fixes: QTBUG-117637 Change-Id: Id0c074af1e9ccc2c2492eb2cc4ee62a4a7131b07 Reviewed-by: Marc Mutz <marc.mutz@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
parent
e1eec6476a
commit
0d85d0a72f
@ -14,6 +14,7 @@
|
||||
|
||||
#include <limits>
|
||||
#include <string.h>
|
||||
#include <type_traits>
|
||||
|
||||
#if defined(QT_COMPILER_SUPPORTS_F16C) && defined(__AVX2__) && !defined(__F16C__)
|
||||
// All processors that support AVX2 do support F16C too, so we could enable the
|
||||
@ -51,6 +52,19 @@ class qfloat16
|
||||
constexpr inline explicit Wrap(int value) : b16(quint16(value)) {}
|
||||
};
|
||||
|
||||
#ifdef QT_SUPPORTS_INT128
|
||||
template <typename T>
|
||||
using IsIntegral = std::disjunction<std::is_integral<T>,
|
||||
std::is_same<std::remove_const_t<T>, qint128>,
|
||||
std::is_same<std::remove_const_t<T>, quint128>>;
|
||||
#else
|
||||
template <typename T>
|
||||
using IsIntegral = std::is_integral<T>;
|
||||
#endif
|
||||
template <typename T>
|
||||
using if_type_is_integral = std::enable_if_t<IsIntegral<std::remove_reference_t<T>>::value,
|
||||
bool>;
|
||||
|
||||
public:
|
||||
using NativeType = QtPrivate::NativeFloat16Type;
|
||||
|
||||
@ -189,11 +203,27 @@ QT_WARNING_DISABLE_FLOAT_COMPARE
|
||||
#endif
|
||||
#undef QF16_MAKE_ORDER_OP_FP
|
||||
|
||||
friend bool comparesEqual(const qfloat16 &lhs, int rhs) noexcept
|
||||
template <typename T, if_type_is_integral<T> = true>
|
||||
friend bool comparesEqual(const qfloat16 &lhs, T rhs) noexcept
|
||||
{ return static_cast<NearestFloat>(lhs) == static_cast<NearestFloat>(rhs); }
|
||||
friend Qt::partial_ordering compareThreeWay(const qfloat16 &lhs, int rhs) noexcept
|
||||
template <typename T, if_type_is_integral<T> = true>
|
||||
friend Qt::partial_ordering compareThreeWay(const qfloat16 &lhs, T rhs) noexcept
|
||||
{ return Qt::compareThreeWay(static_cast<NearestFloat>(lhs), static_cast<NearestFloat>(rhs)); }
|
||||
Q_DECLARE_PARTIALLY_ORDERED(qfloat16, int)
|
||||
|
||||
Q_DECLARE_PARTIALLY_ORDERED(qfloat16, qint8)
|
||||
Q_DECLARE_PARTIALLY_ORDERED(qfloat16, quint8)
|
||||
Q_DECLARE_PARTIALLY_ORDERED(qfloat16, qint16)
|
||||
Q_DECLARE_PARTIALLY_ORDERED(qfloat16, quint16)
|
||||
Q_DECLARE_PARTIALLY_ORDERED(qfloat16, qint32)
|
||||
Q_DECLARE_PARTIALLY_ORDERED(qfloat16, quint32)
|
||||
Q_DECLARE_PARTIALLY_ORDERED(qfloat16, long)
|
||||
Q_DECLARE_PARTIALLY_ORDERED(qfloat16, unsigned long)
|
||||
Q_DECLARE_PARTIALLY_ORDERED(qfloat16, qint64)
|
||||
Q_DECLARE_PARTIALLY_ORDERED(qfloat16, quint64)
|
||||
#ifdef QT_SUPPORTS_INT128
|
||||
Q_DECLARE_PARTIALLY_ORDERED(qfloat16, qint128)
|
||||
Q_DECLARE_PARTIALLY_ORDERED(qfloat16, quint128)
|
||||
#endif
|
||||
|
||||
QT_WARNING_POP
|
||||
|
||||
|
@ -62,6 +62,22 @@ void tst_qfloat16::compareCompiles()
|
||||
QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, qfloat16::NativeType>();
|
||||
#endif
|
||||
QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, int>();
|
||||
QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, qint8>();
|
||||
QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, quint8>();
|
||||
QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, qint16>();
|
||||
QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, quint16>();
|
||||
QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, char16_t>();
|
||||
QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, long>();
|
||||
QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, unsigned long>();
|
||||
QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, wchar_t>();
|
||||
QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, qint32>();
|
||||
QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, quint32>();
|
||||
QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, qint64>();
|
||||
QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, quint64>();
|
||||
#ifdef QT_SUPPORTS_INT128
|
||||
QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, qint128>();
|
||||
QTestPrivate::testAllComparisonOperatorsCompile<qfloat16, quint128>();
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_qfloat16::ordering_data()
|
||||
@ -142,10 +158,25 @@ void tst_qfloat16::ordering()
|
||||
|
||||
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);
|
||||
CHECK_INT(qint8);
|
||||
CHECK_INT(signed char);
|
||||
CHECK_INT(qint16);
|
||||
CHECK_INT(qint32);
|
||||
CHECK_INT(qint64);
|
||||
#if QT_SUPPORTS_INT128
|
||||
CHECK_INT(qint128);
|
||||
#endif
|
||||
if (right >= 0) {
|
||||
CHECK_INT(unsigned int);
|
||||
CHECK_INT(quint8);
|
||||
CHECK_INT(unsigned char);
|
||||
CHECK_INT(quint16);
|
||||
CHECK_INT(quint32);
|
||||
CHECK_INT(quint64);
|
||||
#if QT_SUPPORTS_INT128
|
||||
CHECK_INT(quint128);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#undef CHECK_INT
|
||||
|
Loading…
x
Reference in New Issue
Block a user