diff options
author | Jan Arve Saether <jan-arve.saether@digia.com> | 2013-07-31 15:43:09 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-27 07:57:23 +0200 |
commit | e37001aad7f6e4bbad250addba033f1eaf97d566 (patch) | |
tree | e83a70da7f50edd967128f84df18287e805e30a9 /tests/auto/corelib/global | |
parent | 88999e9ea037ee79557d0c012ad9fdfc72fb5ece (diff) | |
download | qtbase-e37001aad7f6e4bbad250addba033f1eaf97d566.tar.gz |
Say hello to qFloatDistance()
This function is useful if a floating point comparison requires a
certain precision. The return value can be considered as the precision.
For instance, if you want to compare two 32-bit floating point values
and all you need is a 24-bit precision, you can use this function like
this:
if (qFloatDistance(a,b) < (1 << 7)) { // The last 7 bits are not
// significant
// precise enough
}
Task-number: QTBUG-32632
Change-Id: I020a58d2f9f9452ac3c510b4bb560dc806f0d93c
Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'tests/auto/corelib/global')
-rw-r--r-- | tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp b/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp index 20f99e9191..36e01a0ccd 100644 --- a/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp +++ b/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp @@ -44,6 +44,7 @@ #include <QtGlobal> #include <math.h> +#include <float.h> class tst_QNumeric: public QObject { @@ -53,6 +54,10 @@ private slots: void fuzzyCompare_data(); void fuzzyCompare(); void qNan(); + void floatDistance_data(); + void floatDistance(); + void floatDistance_double_data(); + void floatDistance_double(); }; void tst_QNumeric::fuzzyCompare_data() @@ -121,5 +126,93 @@ void tst_QNumeric::qNan() QVERIFY(qFuzzyCompare(1/inf, 0.0)); } +void tst_QNumeric::floatDistance_data() +{ + QTest::addColumn<float>("val1"); + QTest::addColumn<float>("val2"); + QTest::addColumn<quint32>("expectedDistance"); + + // exponent: 8 bits + // mantissa: 23 bits + const quint32 number_of_denormals = (1 << 23) - 1; // Set to 0 if denormals are not included + + quint32 _0_to_1 = quint32((1 << 23) * 126 + 1 + number_of_denormals); // We need +1 to include the 0 + quint32 _1_to_2 = quint32(1 << 23); + + // We don't need +1 because FLT_MAX has all bits set in the mantissa. (Thus mantissa + // have not wrapped back to 0, which would be the case for 1 in _0_to_1 + quint32 _0_to_FLT_MAX = quint32((1 << 23) * 254) + number_of_denormals; + + quint32 _0_to_FLT_MIN = 1 + number_of_denormals; + QTest::newRow("[0,FLT_MIN]") << 0.F << FLT_MIN << _0_to_FLT_MIN; + QTest::newRow("[0,FLT_MAX]") << 0.F << FLT_MAX << _0_to_FLT_MAX; + QTest::newRow("[1,1.5]") << 1.0F << 1.5F << quint32(1 << 22); + QTest::newRow("[0,1]") << 0.F << 1.0F << _0_to_1; + QTest::newRow("[0.5,1]") << 0.5F << 1.0F << quint32(1 << 23); + QTest::newRow("[1,2]") << 1.F << 2.0F << _1_to_2; + QTest::newRow("[-1,+1]") << -1.F << +1.0F << 2 * _0_to_1; + QTest::newRow("[-1,0]") << -1.F << 0.0F << _0_to_1; + QTest::newRow("[-1,FLT_MAX]") << -1.F << FLT_MAX << _0_to_1 + _0_to_FLT_MAX; + QTest::newRow("[-2,-1") << -2.F << -1.F << _1_to_2; + QTest::newRow("[-1,-2") << -1.F << -2.F << _1_to_2; + QTest::newRow("[FLT_MIN,FLT_MAX]") << FLT_MIN << FLT_MAX << _0_to_FLT_MAX - _0_to_FLT_MIN; + QTest::newRow("[-FLT_MAX,FLT_MAX]") << -FLT_MAX << FLT_MAX << (2*_0_to_FLT_MAX); + float denormal = FLT_MIN; + denormal/=2.0F; + QTest::newRow("denormal") << 0.F << denormal << _0_to_FLT_MIN/2; +} + +void tst_QNumeric::floatDistance() +{ + QFETCH(float, val1); + QFETCH(float, val2); + QFETCH(quint32, expectedDistance); + QCOMPARE(qFloatDistance(val1, val2), expectedDistance); +} + +void tst_QNumeric::floatDistance_double_data() +{ + QTest::addColumn<double>("val1"); + QTest::addColumn<double>("val2"); + QTest::addColumn<quint64>("expectedDistance"); + + // exponent: 11 bits + // mantissa: 52 bits + const quint64 number_of_denormals = (Q_UINT64_C(1) << 52) - 1; // Set to 0 if denormals are not included + + quint64 _0_to_1 = (Q_UINT64_C(1) << 52) * ((1 << (11-1)) - 2) + 1 + number_of_denormals; // We need +1 to include the 0 + quint64 _1_to_2 = Q_UINT64_C(1) << 52; + + // We don't need +1 because DBL_MAX has all bits set in the mantissa. (Thus mantissa + // have not wrapped back to 0, which would be the case for 1 in _0_to_1 + quint64 _0_to_DBL_MAX = quint64((Q_UINT64_C(1) << 52) * ((1 << 11) - 2)) + number_of_denormals; + + quint64 _0_to_DBL_MIN = 1 + number_of_denormals; + QTest::newRow("[0,DBL_MIN]") << 0.0 << DBL_MIN << _0_to_DBL_MIN; + QTest::newRow("[0,DBL_MAX]") << 0.0 << DBL_MAX << _0_to_DBL_MAX; + QTest::newRow("[1,1.5]") << 1.0 << 1.5 << (Q_UINT64_C(1) << 51); + QTest::newRow("[0,1]") << 0.0 << 1.0 << _0_to_1; + QTest::newRow("[0.5,1]") << 0.5 << 1.0 << (Q_UINT64_C(1) << 52); + QTest::newRow("[1,2]") << 1.0 << 2.0 << _1_to_2; + QTest::newRow("[-1,+1]") << -1.0 << +1.0 << 2 * _0_to_1; + QTest::newRow("[-1,0]") << -1.0 << 0.0 << _0_to_1; + QTest::newRow("[-1,DBL_MAX]") << -1.0 << DBL_MAX << _0_to_1 + _0_to_DBL_MAX; + QTest::newRow("[-2,-1") << -2.0 << -1.0 << _1_to_2; + QTest::newRow("[-1,-2") << -1.0 << -2.0 << _1_to_2; + QTest::newRow("[DBL_MIN,DBL_MAX]") << DBL_MIN << DBL_MAX << _0_to_DBL_MAX - _0_to_DBL_MIN; + QTest::newRow("[-DBL_MAX,DBL_MAX]") << -DBL_MAX << DBL_MAX << (2*_0_to_DBL_MAX); + double denormal = DBL_MIN; + denormal/=2.0; + QTest::newRow("denormal") << 0.0 << denormal << _0_to_DBL_MIN/2; +} + +void tst_QNumeric::floatDistance_double() +{ + QFETCH(double, val1); + QFETCH(double, val2); + QFETCH(quint64, expectedDistance); + QCOMPARE(qFloatDistance(val1, val2), expectedDistance); +} + QTEST_APPLESS_MAIN(tst_QNumeric) #include "tst_qnumeric.moc" |