QVariant: don't do fuzzy comparisons with NaN and infinities

There was a test that tested this, but was wrong.

[ChangeLog][QtCore][QVariant] Fixed a bug that caused wrong results for
comparisons of QVariants containing either NaN or infinite numbers.

Task-number: QTBUG-56073
Change-Id: I33dc971f005a4848bb8ffffd1475d29d00dd1b7f
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Thiago Macieira 2016-09-19 13:13:44 -07:00
parent 9369eca108
commit 14f0964344
2 changed files with 24 additions and 3 deletions

View File

@ -74,6 +74,7 @@
#include "qline.h" #include "qline.h"
#endif #endif
#include <cmath>
#include <float.h> #include <float.h>
#include <cstring> #include <cstring>
@ -3472,8 +3473,17 @@ static int numericCompare(const QVariant::Private *d1, const QVariant::Private *
Q_ASSERT(ok); Q_ASSERT(ok);
qreal r2 = qConvertToRealNumber(d2, &ok); qreal r2 = qConvertToRealNumber(d2, &ok);
Q_ASSERT(ok); Q_ASSERT(ok);
if (r1 == r2 || qFuzzyCompare(r1, r2)) if (r1 == r2)
return 0; return 0;
// only do fuzzy comparisons for finite, non-zero numbers
int c1 = std::fpclassify(r1);
int c2 = std::fpclassify(r2);
if ((c1 == FP_NORMAL || c1 == FP_SUBNORMAL) && (c2 == FP_NORMAL || c2 == FP_SUBNORMAL)) {
if (qFuzzyCompare(r1, r2))
return 0;
}
return r1 < r2 ? -1 : 1; return r1 < r2 ? -1 : 1;
} }

View File

@ -1755,6 +1755,10 @@ void tst_QVariant::compareNumbers_data() const
QTest::newRow("double5") << qVariantFromValue(0.) << qVariantFromValue(-qInf()) << +1; QTest::newRow("double5") << qVariantFromValue(0.) << qVariantFromValue(-qInf()) << +1;
QTest::newRow("double6") << qVariantFromValue(-double(qInf())) << qVariantFromValue(-qInf()) << 0; QTest::newRow("double6") << qVariantFromValue(-double(qInf())) << qVariantFromValue(-qInf()) << 0;
QTest::newRow("double7") << qVariantFromValue(qInf()) << qVariantFromValue(qInf()) << 0; QTest::newRow("double7") << qVariantFromValue(qInf()) << qVariantFromValue(qInf()) << 0;
QTest::newRow("double8") << qVariantFromValue(-qInf()) << qVariantFromValue(qInf()) << -1;
QTest::newRow("double9") << qVariantFromValue(qQNaN()) << qVariantFromValue(0.) << INT_MAX;
QTest::newRow("double10") << qVariantFromValue(0.) << qVariantFromValue(qQNaN()) << INT_MAX;
QTest::newRow("double11") << qVariantFromValue(qQNaN()) << qVariantFromValue(qQNaN()) << INT_MAX;
// mixed comparisons // mixed comparisons
// fp + fp // fp + fp
@ -1763,8 +1767,12 @@ void tst_QVariant::compareNumbers_data() const
QTest::newRow("float+double3") << qVariantFromValue(0.f) << qVariantFromValue(-1.) << +1; QTest::newRow("float+double3") << qVariantFromValue(0.f) << qVariantFromValue(-1.) << +1;
QTest::newRow("float+double4") << qVariantFromValue(-float(qInf())) << qVariantFromValue(0.) << -1; QTest::newRow("float+double4") << qVariantFromValue(-float(qInf())) << qVariantFromValue(0.) << -1;
QTest::newRow("float+double5") << qVariantFromValue(0.f) << qVariantFromValue(-qInf()) << +1; QTest::newRow("float+double5") << qVariantFromValue(0.f) << qVariantFromValue(-qInf()) << +1;
QTest::newRow("float+double6") << qVariantFromValue(-float(qInf())) << qVariantFromValue(qInf()) << 0; QTest::newRow("float+double6") << qVariantFromValue(-float(qInf())) << qVariantFromValue(-qInf()) << 0;
QTest::newRow("float+double7") << qVariantFromValue(float(qInf())) << qVariantFromValue(qInf()) << 0; QTest::newRow("float+double7") << qVariantFromValue(float(qInf())) << qVariantFromValue(qInf()) << 0;
QTest::newRow("float+double8") << qVariantFromValue(-float(qInf())) << qVariantFromValue(qInf()) << -1;
QTest::newRow("float+double9") << qVariantFromValue(qQNaN()) << qVariantFromValue(0.) << INT_MAX;
QTest::newRow("float+double10") << qVariantFromValue(0.) << qVariantFromValue(qQNaN()) << INT_MAX;
QTest::newRow("float+double11") << qVariantFromValue(qQNaN()) << qVariantFromValue(qQNaN()) << INT_MAX;
// fp + int // fp + int
QTest::newRow("float+int1") << qVariantFromValue(0.f) << qVariantFromValue(0) << 0; QTest::newRow("float+int1") << qVariantFromValue(0.f) << qVariantFromValue(0) << 0;
@ -1978,7 +1986,7 @@ void tst_QVariant::compareNumbers() const
QCOMPARE(v2, v1); QCOMPARE(v2, v1);
QVERIFY(v2 >= v1); QVERIFY(v2 >= v1);
QVERIFY(!(v2 > v1)); QVERIFY(!(v2 > v1));
} else { } else if (expected == +1) {
QVERIFY(!(v1 < v2)); QVERIFY(!(v1 < v2));
QVERIFY(!(v1 <= v2)); QVERIFY(!(v1 <= v2));
QVERIFY(!(v1 == v2)); QVERIFY(!(v1 == v2));
@ -1990,6 +1998,9 @@ void tst_QVariant::compareNumbers() const
QVERIFY(!(v2 == v1)); QVERIFY(!(v2 == v1));
QVERIFY(!(v2 >= v1)); QVERIFY(!(v2 >= v1));
QVERIFY(!(v2 > v1)); QVERIFY(!(v2 > v1));
} else {
// unorderable (NaN)
QVERIFY(!(v1 == v2));
} }
} }