From 469c071d6989193e23d8c67ccdd515eb76abada4 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 17 Mar 2025 11:35:09 -0700 Subject: [PATCH] QVariant/QMetaType: fix conversions to/from qfloat16 Needed to make some conversions explicit, since you can't assign to a qfloat16 from double. [ChangeLog][QtCore][QVariant] Implemented converting of qfloat16 to and from the other numeric types, text conversions to and from QString and QByteArray, and conversions to and from QJsonValue and QCborValue. This should make qfloat16 behave the same as float and double. Also flip the order of arguments in one of the addComparePairs(): left side is actual, right side is expected. I noticed on the copy & paste to do the qfloat16 above it. Pick-to: 6.8 Task-number: QTBUG-134756 Change-Id: I6a6c469d21746a07c18efffd6b3b961c73c0e2f2 Reviewed-by: Marc Mutz (cherry picked from commit a4daf4939644ea3a087a8c03b1ec962e2e4defa8) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/kernel/qmetatype.cpp | 22 +++++++++-- src/corelib/kernel/qvariant.cpp | 1 + .../corelib/kernel/qvariant/tst_qvariant.cpp | 38 ++++++++++++++++++- 3 files changed, 55 insertions(+), 6 deletions(-) diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index 132791fa390..66dec2979c4 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -1004,6 +1004,7 @@ static constexpr struct : QMetaTypeModuleHelper using LongLong = qlonglong; using ULong = unsigned long; using ULongLong = qulonglong; + using Float16 = qfloat16; using Float = float; using Double = double; using Bool = bool; @@ -1028,7 +1029,7 @@ static constexpr struct : QMetaTypeModuleHelper if constexpr(std::is_integral_v) \ result = source.toInteger(); \ else \ - result = source.toDouble(); \ + result = To(source.toDouble()); \ } \ return true; \ ); \ @@ -1043,7 +1044,7 @@ static constexpr struct : QMetaTypeModuleHelper if constexpr(std::is_integral_v) \ result = source.toInteger(); \ else \ - result = source.toDouble(); \ + result = To(source.toDouble()); \ } \ return true; \ ) @@ -1064,6 +1065,7 @@ static constexpr struct : QMetaTypeModuleHelper QMETATYPE_CONVERTER_ASSIGN(To, ULong); \ QMETATYPE_CONVERTER_ASSIGN(To, LongLong); \ QMETATYPE_CONVERTER_ASSIGN(To, ULongLong); \ + QMETATYPE_CONVERTER(To, Float16, result = qRound64(source); return true;); \ QMETATYPE_CONVERTER(To, Float, result = qRound64(source); return true;); \ QMETATYPE_CONVERTER(To, Double, result = qRound64(source); return true;); \ QMETATYPE_CONVERTER(To, QChar, result = source.unicode(); return true;); \ @@ -1102,16 +1104,17 @@ static constexpr struct : QMetaTypeModuleHelper QMETATYPE_CONVERTER_ASSIGN(To, ULong); \ QMETATYPE_CONVERTER_ASSIGN(To, LongLong); \ QMETATYPE_CONVERTER_ASSIGN(To, ULongLong); \ + QMETATYPE_CONVERTER_ASSIGN(To, Float16); \ QMETATYPE_CONVERTER_ASSIGN(To, Float); \ QMETATYPE_CONVERTER_ASSIGN(To, Double); \ QMETATYPE_CONVERTER(To, QString, \ bool ok = false; \ - result = source.toDouble(&ok); \ + result = To(source.toDouble(&ok)); \ return ok; \ ); \ QMETATYPE_CONVERTER(To, QByteArray, \ bool ok = false; \ - result = source.toDouble(&ok); \ + result = To(source.toDouble(&ok)); \ return ok; \ ); \ CONVERT_CBOR_AND_JSON(To) @@ -1131,6 +1134,7 @@ static constexpr struct : QMetaTypeModuleHelper INTEGRAL_CONVERTER(ULong); INTEGRAL_CONVERTER(LongLong); INTEGRAL_CONVERTER(ULongLong); + FLOAT_CONVERTER(Float16); FLOAT_CONVERTER(Float); FLOAT_CONVERTER(Double); @@ -1182,6 +1186,10 @@ static constexpr struct : QMetaTypeModuleHelper QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, ULong); QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, UInt); QMETATYPE_CONVERTER_ASSIGN_NUMBER(QString, ULongLong); + QMETATYPE_CONVERTER(QString, Float16, + result = QString::number(source, 'g', QLocale::FloatingPointShortest); + return true; + ); QMETATYPE_CONVERTER(QString, Float, result = QString::number(source, 'g', QLocale::FloatingPointShortest); return true; @@ -1250,6 +1258,10 @@ static constexpr struct : QMetaTypeModuleHelper QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, ULong); QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, UInt); QMETATYPE_CONVERTER_ASSIGN_NUMBER(QByteArray, ULongLong); + QMETATYPE_CONVERTER(QByteArray, Float16, + result = QByteArray::number(source, 'g', QLocale::FloatingPointShortest); + return true; + ); QMETATYPE_CONVERTER(QByteArray, Float, result = QByteArray::number(source, 'g', QLocale::FloatingPointShortest); return true; @@ -1393,6 +1405,7 @@ static constexpr struct : QMetaTypeModuleHelper QMETATYPE_CONVERTER_ASSIGN(QCborValue, Short); QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QCborValue, Double); QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QCborValue, Float); + QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QCborValue, Float16); QMETATYPE_CONVERTER(QCborValue, QStringList, result = QCborArray::fromStringList(source); return true; @@ -1583,6 +1596,7 @@ static constexpr struct : QMetaTypeModuleHelper QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, UInt); QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Double); QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Float); + QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Float16); QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, ULong); QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, Long); QMETATYPE_CONVERTER_ASSIGN_DOUBLE(QJsonValue, LongLong); diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 3cf9058a59d..2c69870c7b4 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -2210,6 +2210,7 @@ static bool qIsNumericType(uint tp) Q_UINT64_C(1) << QMetaType::QString | Q_UINT64_C(1) << QMetaType::Bool | Q_UINT64_C(1) << QMetaType::Double | + Q_UINT64_C(1) << QMetaType::Float16 | Q_UINT64_C(1) << QMetaType::Float | Q_UINT64_C(1) << QMetaType::Char | Q_UINT64_C(1) << QMetaType::Char16 | diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp index 0967bdb9470..62f6c30b60a 100644 --- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp +++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp @@ -260,6 +260,9 @@ private slots: void toFloat_data(); void toFloat(); + void toFloat16_data(); + void toFloat16(); + void toPointF_data(); void toPointF(); @@ -893,6 +896,7 @@ template static void addNumberConversions() addNumber(0x8000'0000UL); addNumber(-0x1'0000'0000LL); addNumber(0x1'0000'000'0000ULL); + addNumber(qfloat16(-3.1415927f)); addNumber(-3.1415927f); addNumber(-3.1415927); @@ -1145,8 +1149,10 @@ void tst_QVariant::toBool_data() QTest::newRow( "uint1" ) << QVariant( 123u ) << true; QTest::newRow( "double0" ) << QVariant( 0.0 ) << false; QTest::newRow( "float0" ) << QVariant( 0.0f ) << false; + QTest::newRow( "float16_0" ) << QVariant::fromValue( qfloat16() ) << false; QTest::newRow( "double1" ) << QVariant( 3.1415927 ) << true; QTest::newRow( "float1" ) << QVariant( 3.1415927f ) << true; + QTest::newRow( "float16_1" ) << QVariant::fromValue( qfloat16(3.1415927f) ) << true; QTest::newRow( "string0" ) << QVariant( QString("3") ) << true; QTest::newRow( "string1" ) << QVariant( QString("true") ) << true; QTest::newRow( "string2" ) << QVariant( QString("0") ) << false; @@ -1238,6 +1244,16 @@ void tst_QVariant::toFloat() checkNumberConversions(&QVariant::toFloat); } +void tst_QVariant::toFloat16_data() +{ + addNumberConversions(); +} + +void tst_QVariant::toFloat16() +{ + checkNumberConversions(nullptr); +} + void tst_QVariant::toSChar_data() { addNumberConversions(); @@ -3020,6 +3036,7 @@ void tst_QVariant::compareNumerics_data() const addCompareToInvalid(ulong(0)); addCompareToInvalid(qint64(0)); addCompareToInvalid(quint64(0)); + addCompareToInvalid(qfloat16(0.f)); addCompareToInvalid(0.f); addCompareToInvalid(0.0); addCompareToInvalid(QCborSimpleType{}); @@ -3060,7 +3077,7 @@ QT_WARNING_POP T one = T(zero + 1); T min = std::numeric_limits::min(); T max = std::numeric_limits::max(); - T mid = max / 2 + 1; + T mid = T(max / 2 + 1); if (min != zero) addList(std::array{zero, one, min, mid, max}); else @@ -3079,6 +3096,7 @@ QT_WARNING_POP addSingleType(quint32(0)); addSingleType(qint64(0)); addSingleType(quint64(0)); + addSingleType(qfloat16(0.f)); addSingleType(0.f); addSingleType(0.0); addList(std::array{ EnumTest_Enum0{}, EnumTest_Enum0_value, EnumTest_Enum0_negValue }); @@ -3138,6 +3156,22 @@ QT_WARNING_POP // addComparePair(LLONG_MIN, LLONG_MAX); // already added by addSingleType() // floating point + addComparePair(qfloat16(0.f), 0); + addComparePair(qfloat16(0.f), 0U); + addComparePair(qfloat16(0.f), Q_INT64_C(0)); + addComparePair(qfloat16(0.f), Q_UINT64_C(0)); + addComparePair(qfloat16(0.f), 0.f); + addComparePair(qfloat16(0.f), 1.f); + addComparePair(qfloat16(0.f), 0.); + addComparePair(qfloat16(0.f), 1.); + addComparePair(qfloat16(1 << 11), 1 << 11); + addComparePair(qfloat16(1 << 11) - 1, (1 << 11) - 1); + addComparePair(-qfloat16(1 << 11), 1 << 11); + addComparePair(-qfloat16(1 << 11) + 1, -(1 << 11) + 1); + addComparePair(std::numeric_limits::infinity(), qInf()); + addComparePair(std::numeric_limits::infinity(), -qInf()); + addComparePair(std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()); + addComparePair(0.f, 0); addComparePair(0.f, 0U); addComparePair(0.f, Q_INT64_C(0)); @@ -3150,7 +3184,7 @@ QT_WARNING_POP addComparePair(-float(1 << 24) + 1, -(1 << 24) + 1); addComparePair(HUGE_VALF, qInf()); addComparePair(HUGE_VALF, -qInf()); - addComparePair(qQNaN(), std::numeric_limits::quiet_NaN()); + addComparePair(std::numeric_limits::quiet_NaN(), qQNaN()); if (sizeof(qreal) == sizeof(double)) { addComparePair(std::numeric_limits::min(), std::numeric_limits::min()); addComparePair(std::numeric_limits::min(), std::numeric_limits::max());