QVariant: always compare floating point with double precision

When Qt is configured with `-qreal float`, then we should still compare
QVariants containing floating point values with the full precision of
the stored type, and not cast to qreal (ie. float).

Cast all floating point types up to double, which is the highest-
precision floating point type we support in Qt. This might have a small
performance impact when compiling with `-qreal float`, if the FPU does
not perform well with double-precision floating point values.

We don't test any `-qreal float` configurations in CI, so not adding
a unit test for this.

Fixes: QTBUG-114991
Change-Id: I198ec2c39913b501ef2fe99ae3048b160baa1fd8
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
(cherry picked from commit 1fe60cbcc3c476f5f4bc4bce49d4e73d99c49d3d)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Volker Hilsheimer 2023-07-04 18:47:26 +02:00 committed by Qt Cherry-pick Bot
parent 4ba4723d57
commit f00f557ee6

View File

@ -173,20 +173,20 @@ static std::optional<qlonglong> qConvertToNumber(const QVariant::Private *d, boo
return std::nullopt;
}
static std::optional<qreal> qConvertToRealNumber(const QVariant::Private *d)
static std::optional<double> qConvertToRealNumber(const QVariant::Private *d)
{
bool ok;
switch (d->typeInterface()->typeId) {
case QMetaType::QString:
if (double r = d->get<QString>().toDouble(&ok); ok)
return qreal(r);
return r;
return std::nullopt;
case QMetaType::Double:
return qreal(d->get<double>());
return d->get<double>();
case QMetaType::Float:
return qreal(d->get<float>());
return double(d->get<float>());
case QMetaType::Float16:
return qreal(d->get<qfloat16>());
return double(d->get<qfloat16>());
case QMetaType::ULongLong:
case QMetaType::UInt:
case QMetaType::UChar:
@ -194,7 +194,7 @@ static std::optional<qreal> qConvertToRealNumber(const QVariant::Private *d)
case QMetaType::Char32:
case QMetaType::UShort:
case QMetaType::ULong:
return qreal(qMetaTypeUNumber(d));
return double(qMetaTypeUNumber(d));
#ifndef QT_BOOTSTRAPPED
case QMetaType::QCborValue:
return d->get<QCborValue>().toDouble();
@ -204,7 +204,7 @@ static std::optional<qreal> qConvertToRealNumber(const QVariant::Private *d)
default:
// includes enum conversion as well as invalid types
if (std::optional<qlonglong> l = qConvertToNumber(d))
return qreal(*l);
return double(*l);
return std::nullopt;
}
}
@ -2372,15 +2372,15 @@ static QPartialOrdering numericCompare(const QVariant::Private *d1, const QVaria
if (promotedType != QMetaType::QReal)
return integralCompare(promotedType, d1, d2);
// qreal comparisons
std::optional<qreal> r1 = qConvertToRealNumber(d1);
std::optional<qreal> r2 = qConvertToRealNumber(d2);
// floating point comparison
const auto r1 = qConvertToRealNumber(d1);
const auto r2 = qConvertToRealNumber(d2);
if (!r1 || !r2)
return QPartialOrdering::Unordered;
if (*r1 == *r2)
return QPartialOrdering::Equivalent;
return spaceShip<qreal>(*r1, *r2);
return spaceShip(*r1, *r2);
}
#ifndef QT_BOOTSTRAPPED