Add qFpClassify() to mirror std::fpclassify()
The rules of std don't permit us to add an overload for fpclassify(qfloat16), so we need our own equivalent that we *can* overload. Deploy it in the few places we use fpclassify(). Extended qnumeric's testing to cover qFpClassify(). Change-Id: Ie5a0a5cc24599d1571404c573d33c682b0d305a5 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Paul Wicking <paul.wicking@qt.io>
This commit is contained in:
parent
368eb2ecec
commit
84aea6c091
@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of the QtCore module of the Qt Toolkit.
|
** This file is part of the QtCore module of the Qt Toolkit.
|
||||||
@ -46,6 +46,7 @@ QT_BEGIN_NAMESPACE
|
|||||||
/*!
|
/*!
|
||||||
Returns \c true if the double \a {d} is equivalent to infinity.
|
Returns \c true if the double \a {d} is equivalent to infinity.
|
||||||
\relates <QtGlobal>
|
\relates <QtGlobal>
|
||||||
|
\sa qInf()
|
||||||
*/
|
*/
|
||||||
Q_CORE_EXPORT bool qIsInf(double d) { return qt_is_inf(d); }
|
Q_CORE_EXPORT bool qIsInf(double d) { return qt_is_inf(d); }
|
||||||
|
|
||||||
@ -64,6 +65,7 @@ Q_CORE_EXPORT bool qIsFinite(double d) { return qt_is_finite(d); }
|
|||||||
/*!
|
/*!
|
||||||
Returns \c true if the float \a {f} is equivalent to infinity.
|
Returns \c true if the float \a {f} is equivalent to infinity.
|
||||||
\relates <QtGlobal>
|
\relates <QtGlobal>
|
||||||
|
\sa qInf()
|
||||||
*/
|
*/
|
||||||
Q_CORE_EXPORT bool qIsInf(float f) { return qt_is_inf(f); }
|
Q_CORE_EXPORT bool qIsInf(float f) { return qt_is_inf(f); }
|
||||||
|
|
||||||
@ -88,15 +90,36 @@ Q_CORE_EXPORT double qSNaN() { return qt_snan(); }
|
|||||||
/*!
|
/*!
|
||||||
Returns the bit pattern of a quiet NaN as a double.
|
Returns the bit pattern of a quiet NaN as a double.
|
||||||
\relates <QtGlobal>
|
\relates <QtGlobal>
|
||||||
|
\sa qIsNaN()
|
||||||
*/
|
*/
|
||||||
Q_CORE_EXPORT double qQNaN() { return qt_qnan(); }
|
Q_CORE_EXPORT double qQNaN() { return qt_qnan(); }
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Returns the bit pattern for an infinite number as a double.
|
Returns the bit pattern for an infinite number as a double.
|
||||||
\relates <QtGlobal>
|
\relates <QtGlobal>
|
||||||
|
\sa qIsInf()
|
||||||
*/
|
*/
|
||||||
Q_CORE_EXPORT double qInf() { return qt_inf(); }
|
Q_CORE_EXPORT double qInf() { return qt_inf(); }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\relates <QtGlobal>
|
||||||
|
Classifies a floating-point value.
|
||||||
|
|
||||||
|
The return values are defined in \c{<cmath>}: returns one of the following,
|
||||||
|
determined by the floating-point class of \a val:
|
||||||
|
\list
|
||||||
|
\li FP_NAN not a number
|
||||||
|
\li FP_INFINITE infinities (positive or negative)
|
||||||
|
\li FP_NORMAL finite with a full mantissa
|
||||||
|
\li FP_SUBNORMAL finite with a reduced mantissa
|
||||||
|
\endlist
|
||||||
|
*/
|
||||||
|
Q_CORE_EXPORT int qFpClassify(double val) { return qt_fpclassify(val); }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\overload
|
||||||
|
*/
|
||||||
|
Q_CORE_EXPORT int qFpClassify(float val) { return qt_fpclassify(val); }
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of the QtCore module of the Qt Toolkit.
|
** This file is part of the QtCore module of the Qt Toolkit.
|
||||||
@ -48,9 +48,11 @@ QT_BEGIN_NAMESPACE
|
|||||||
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsInf(double d);
|
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsInf(double d);
|
||||||
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsNaN(double d);
|
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsNaN(double d);
|
||||||
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsFinite(double d);
|
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsFinite(double d);
|
||||||
|
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION int qFpClassify(double val);
|
||||||
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsInf(float f);
|
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsInf(float f);
|
||||||
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsNaN(float f);
|
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsNaN(float f);
|
||||||
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsFinite(float f);
|
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsFinite(float f);
|
||||||
|
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION int qFpClassify(float val);
|
||||||
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qSNaN();
|
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qSNaN();
|
||||||
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qQNaN();
|
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qQNaN();
|
||||||
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qInf();
|
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qInf();
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
** Copyright (C) 2018 Intel Corporation.
|
** Copyright (C) 2018 Intel Corporation.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
@ -85,9 +85,11 @@ namespace qnumeric_std_wrapper {
|
|||||||
Q_DECL_CONST_FUNCTION static inline bool math_h_isnan(double d) { using namespace std; return isnan(d); }
|
Q_DECL_CONST_FUNCTION static inline bool math_h_isnan(double d) { using namespace std; return isnan(d); }
|
||||||
Q_DECL_CONST_FUNCTION static inline bool math_h_isinf(double d) { using namespace std; return isinf(d); }
|
Q_DECL_CONST_FUNCTION static inline bool math_h_isinf(double d) { using namespace std; return isinf(d); }
|
||||||
Q_DECL_CONST_FUNCTION static inline bool math_h_isfinite(double d) { using namespace std; return isfinite(d); }
|
Q_DECL_CONST_FUNCTION static inline bool math_h_isfinite(double d) { using namespace std; return isfinite(d); }
|
||||||
|
Q_DECL_CONST_FUNCTION static inline int math_h_fpclassify(double d) { using namespace std; return fpclassify(d); }
|
||||||
Q_DECL_CONST_FUNCTION static inline bool math_h_isnan(float f) { using namespace std; return isnan(f); }
|
Q_DECL_CONST_FUNCTION static inline bool math_h_isnan(float f) { using namespace std; return isnan(f); }
|
||||||
Q_DECL_CONST_FUNCTION static inline bool math_h_isinf(float f) { using namespace std; return isinf(f); }
|
Q_DECL_CONST_FUNCTION static inline bool math_h_isinf(float f) { using namespace std; return isinf(f); }
|
||||||
Q_DECL_CONST_FUNCTION static inline bool math_h_isfinite(float f) { using namespace std; return isfinite(f); }
|
Q_DECL_CONST_FUNCTION static inline bool math_h_isfinite(float f) { using namespace std; return isfinite(f); }
|
||||||
|
Q_DECL_CONST_FUNCTION static inline int math_h_fpclassify(float f) { using namespace std; return fpclassify(f); }
|
||||||
}
|
}
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
// These macros from math.h conflict with the real functions in the std namespace.
|
// These macros from math.h conflict with the real functions in the std namespace.
|
||||||
@ -95,6 +97,7 @@ QT_END_NAMESPACE
|
|||||||
# undef isnan
|
# undef isnan
|
||||||
# undef isinf
|
# undef isinf
|
||||||
# undef isfinite
|
# undef isfinite
|
||||||
|
# undef fpclassify
|
||||||
# endif // defined(isnan)
|
# endif // defined(isnan)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -106,16 +109,20 @@ namespace qnumeric_std_wrapper {
|
|||||||
Q_DECL_CONST_FUNCTION static inline bool isnan(double d) { return math_h_isnan(d); }
|
Q_DECL_CONST_FUNCTION static inline bool isnan(double d) { return math_h_isnan(d); }
|
||||||
Q_DECL_CONST_FUNCTION static inline bool isinf(double d) { return math_h_isinf(d); }
|
Q_DECL_CONST_FUNCTION static inline bool isinf(double d) { return math_h_isinf(d); }
|
||||||
Q_DECL_CONST_FUNCTION static inline bool isfinite(double d) { return math_h_isfinite(d); }
|
Q_DECL_CONST_FUNCTION static inline bool isfinite(double d) { return math_h_isfinite(d); }
|
||||||
|
Q_DECL_CONST_FUNCTION static inline int fpclassify(double d) { return math_h_fpclassify(d); }
|
||||||
Q_DECL_CONST_FUNCTION static inline bool isnan(float f) { return math_h_isnan(f); }
|
Q_DECL_CONST_FUNCTION static inline bool isnan(float f) { return math_h_isnan(f); }
|
||||||
Q_DECL_CONST_FUNCTION static inline bool isinf(float f) { return math_h_isinf(f); }
|
Q_DECL_CONST_FUNCTION static inline bool isinf(float f) { return math_h_isinf(f); }
|
||||||
Q_DECL_CONST_FUNCTION static inline bool isfinite(float f) { return math_h_isfinite(f); }
|
Q_DECL_CONST_FUNCTION static inline bool isfinite(float f) { return math_h_isfinite(f); }
|
||||||
|
Q_DECL_CONST_FUNCTION static inline int fpclassify(float f) { return math_h_fpclassify(f); }
|
||||||
#else
|
#else
|
||||||
Q_DECL_CONST_FUNCTION static inline bool isnan(double d) { return std::isnan(d); }
|
Q_DECL_CONST_FUNCTION static inline bool isnan(double d) { return std::isnan(d); }
|
||||||
Q_DECL_CONST_FUNCTION static inline bool isinf(double d) { return std::isinf(d); }
|
Q_DECL_CONST_FUNCTION static inline bool isinf(double d) { return std::isinf(d); }
|
||||||
Q_DECL_CONST_FUNCTION static inline bool isfinite(double d) { return std::isfinite(d); }
|
Q_DECL_CONST_FUNCTION static inline bool isfinite(double d) { return std::isfinite(d); }
|
||||||
|
Q_DECL_CONST_FUNCTION static inline int fpclassify(double d) { return std::fpclassify(d); }
|
||||||
Q_DECL_CONST_FUNCTION static inline bool isnan(float f) { return std::isnan(f); }
|
Q_DECL_CONST_FUNCTION static inline bool isnan(float f) { return std::isnan(f); }
|
||||||
Q_DECL_CONST_FUNCTION static inline bool isinf(float f) { return std::isinf(f); }
|
Q_DECL_CONST_FUNCTION static inline bool isinf(float f) { return std::isinf(f); }
|
||||||
Q_DECL_CONST_FUNCTION static inline bool isfinite(float f) { return std::isfinite(f); }
|
Q_DECL_CONST_FUNCTION static inline bool isfinite(float f) { return std::isfinite(f); }
|
||||||
|
Q_DECL_CONST_FUNCTION static inline int fpclassify(float f) { return std::fpclassify(f); }
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,6 +164,11 @@ Q_DECL_CONST_FUNCTION static inline bool qt_is_finite(double d)
|
|||||||
return qnumeric_std_wrapper::isfinite(d);
|
return qnumeric_std_wrapper::isfinite(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Q_DECL_CONST_FUNCTION static inline int qt_fpclassify(double d)
|
||||||
|
{
|
||||||
|
return qnumeric_std_wrapper::fpclassify(d);
|
||||||
|
}
|
||||||
|
|
||||||
Q_DECL_CONST_FUNCTION static inline bool qt_is_inf(float f)
|
Q_DECL_CONST_FUNCTION static inline bool qt_is_inf(float f)
|
||||||
{
|
{
|
||||||
return qnumeric_std_wrapper::isinf(f);
|
return qnumeric_std_wrapper::isinf(f);
|
||||||
@ -172,6 +184,11 @@ Q_DECL_CONST_FUNCTION static inline bool qt_is_finite(float f)
|
|||||||
return qnumeric_std_wrapper::isfinite(f);
|
return qnumeric_std_wrapper::isfinite(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Q_DECL_CONST_FUNCTION static inline int qt_fpclassify(float f)
|
||||||
|
{
|
||||||
|
return qnumeric_std_wrapper::fpclassify(f);
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef Q_CLANG_QDOC
|
#ifndef Q_CLANG_QDOC
|
||||||
namespace {
|
namespace {
|
||||||
/*!
|
/*!
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
** Copyright (C) 2018 Intel Corporation.
|
** Copyright (C) 2018 Intel Corporation.
|
||||||
** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
|
** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
@ -4002,8 +4002,8 @@ static int numericCompare(const QVariant::Private *d1, const QVariant::Private *
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// only do fuzzy comparisons for finite, non-zero numbers
|
// only do fuzzy comparisons for finite, non-zero numbers
|
||||||
int c1 = std::fpclassify(r1);
|
int c1 = qFpClassify(r1);
|
||||||
int c2 = std::fpclassify(r2);
|
int c2 = qFpClassify(r2);
|
||||||
if ((c1 == FP_NORMAL || c1 == FP_SUBNORMAL) && (c2 == FP_NORMAL || c2 == FP_SUBNORMAL)) {
|
if ((c1 == FP_NORMAL || c1 == FP_SUBNORMAL) && (c2 == FP_NORMAL || c2 == FP_SUBNORMAL)) {
|
||||||
if (qFuzzyCompare(r1, r2))
|
if (qFuzzyCompare(r1, r2))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
** Copyright (C) 2016 Intel Corporation.
|
** Copyright (C) 2016 Intel Corporation.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
@ -2522,12 +2522,12 @@ bool QTest::compare_helper(bool success, const char *failureMsg,
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
static bool floatingCompare(const T &t1, const T &t2)
|
static bool floatingCompare(const T &t1, const T &t2)
|
||||||
{
|
{
|
||||||
switch (std::fpclassify(t1))
|
switch (qFpClassify(t1))
|
||||||
{
|
{
|
||||||
case FP_INFINITE:
|
case FP_INFINITE:
|
||||||
return (t1 < 0) == (t2 < 0) && std::fpclassify(t2) == FP_INFINITE;
|
return (t1 < 0) == (t2 < 0) && qFpClassify(t2) == FP_INFINITE;
|
||||||
case FP_NAN:
|
case FP_NAN:
|
||||||
return std::fpclassify(t2) == FP_NAN;
|
return qFpClassify(t2) == FP_NAN;
|
||||||
default:
|
default:
|
||||||
return qFuzzyCompare(t1, t2);
|
return qFuzzyCompare(t1, t2);
|
||||||
}
|
}
|
||||||
@ -2631,7 +2631,7 @@ static void massageExponent(char *text)
|
|||||||
template <> Q_TESTLIB_EXPORT char *QTest::toString<TYPE>(const TYPE &t) \
|
template <> Q_TESTLIB_EXPORT char *QTest::toString<TYPE>(const TYPE &t) \
|
||||||
{ \
|
{ \
|
||||||
char *msg = new char[128]; \
|
char *msg = new char[128]; \
|
||||||
switch (std::fpclassify(t)) { \
|
switch (qFpClassify(t)) { \
|
||||||
case FP_INFINITE: \
|
case FP_INFINITE: \
|
||||||
qstrncpy(msg, (t < 0 ? "-inf" : "inf"), 128); \
|
qstrncpy(msg, (t < 0 ? "-inf" : "inf"), 128); \
|
||||||
break; \
|
break; \
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
** Copyright (C) 2016 Intel Corporation.
|
** Copyright (C) 2016 Intel Corporation.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
@ -43,6 +43,7 @@ private slots:
|
|||||||
void fuzzyCompare_data();
|
void fuzzyCompare_data();
|
||||||
void fuzzyCompare();
|
void fuzzyCompare();
|
||||||
void qNanInf();
|
void qNanInf();
|
||||||
|
void classifyfp();
|
||||||
void floatDistance_data();
|
void floatDistance_data();
|
||||||
void floatDistance();
|
void floatDistance();
|
||||||
void floatDistance_double_data();
|
void floatDistance_double_data();
|
||||||
@ -123,6 +124,7 @@ void tst_QNumeric::qNanInf()
|
|||||||
QVERIFY(qIsNaN(-nan));
|
QVERIFY(qIsNaN(-nan));
|
||||||
QVERIFY(!(nan == nan));
|
QVERIFY(!(nan == nan));
|
||||||
QVERIFY(qIsNaN(0.0 * nan));
|
QVERIFY(qIsNaN(0.0 * nan));
|
||||||
|
QCOMPARE(qFpClassify(nan), FP_NAN);
|
||||||
QCOMPARE(nan, nan);
|
QCOMPARE(nan, nan);
|
||||||
QCOMPARE(nan, -nan);
|
QCOMPARE(nan, -nan);
|
||||||
QCOMPARE(nan, qQNaN());
|
QCOMPARE(nan, qQNaN());
|
||||||
@ -143,6 +145,34 @@ void tst_QNumeric::qNanInf()
|
|||||||
QVERIFY(qIsNaN(0.0 * inf));
|
QVERIFY(qIsNaN(0.0 * inf));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QNumeric::classifyfp()
|
||||||
|
{
|
||||||
|
QCOMPARE(qFpClassify(qQNaN()), FP_NAN);
|
||||||
|
|
||||||
|
QCOMPARE(qFpClassify(qInf()), FP_INFINITE);
|
||||||
|
QCOMPARE(qFpClassify(-qInf()), FP_INFINITE);
|
||||||
|
QCOMPARE(qFpClassify(DBL_MAX * 2.0), FP_INFINITE);
|
||||||
|
QCOMPARE(qFpClassify(FLT_MAX * 2.f), FP_INFINITE);
|
||||||
|
QCOMPARE(qFpClassify(DBL_MAX * -2.0), FP_INFINITE);
|
||||||
|
QCOMPARE(qFpClassify(FLT_MAX * -2.f), FP_INFINITE);
|
||||||
|
|
||||||
|
QCOMPARE(qFpClassify(1.0), FP_NORMAL);
|
||||||
|
QCOMPARE(qFpClassify(DBL_MAX), FP_NORMAL);
|
||||||
|
QCOMPARE(qFpClassify(-DBL_MAX), FP_NORMAL);
|
||||||
|
QCOMPARE(qFpClassify(DBL_MIN), FP_NORMAL);
|
||||||
|
QCOMPARE(qFpClassify(-DBL_MIN), FP_NORMAL);
|
||||||
|
QCOMPARE(qFpClassify(DBL_MIN / 2.0), FP_SUBNORMAL);
|
||||||
|
QCOMPARE(qFpClassify(DBL_MIN / -2.0), FP_SUBNORMAL);
|
||||||
|
|
||||||
|
QCOMPARE(qFpClassify(1.f), FP_NORMAL);
|
||||||
|
QCOMPARE(qFpClassify(FLT_MAX), FP_NORMAL);
|
||||||
|
QCOMPARE(qFpClassify(-FLT_MAX), FP_NORMAL);
|
||||||
|
QCOMPARE(qFpClassify(FLT_MIN), FP_NORMAL);
|
||||||
|
QCOMPARE(qFpClassify(-FLT_MIN), FP_NORMAL);
|
||||||
|
QCOMPARE(qFpClassify(FLT_MIN / 2.f), FP_SUBNORMAL);
|
||||||
|
QCOMPARE(qFpClassify(FLT_MIN / -2.f), FP_SUBNORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
void tst_QNumeric::floatDistance_data()
|
void tst_QNumeric::floatDistance_data()
|
||||||
{
|
{
|
||||||
QTest::addColumn<float>("val1");
|
QTest::addColumn<float>("val1");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user