Move QLocaleData::convertDoubleToFloat to qnumeric_p.h
So others can use it too. Change-Id: I01ec3c774d9943adb903fffd17b86236d06a948c Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>bb10
parent
26f307ddb1
commit
a14bba6803
|
|
@ -51,6 +51,8 @@ QT_END_NAMESPACE
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class qfloat16;
|
||||||
|
|
||||||
namespace qnumeric_std_wrapper {
|
namespace qnumeric_std_wrapper {
|
||||||
#if defined(QT_MATH_H_DEFINES_MACROS)
|
#if defined(QT_MATH_H_DEFINES_MACROS)
|
||||||
# undef QT_MATH_H_DEFINES_MACROS
|
# undef QT_MATH_H_DEFINES_MACROS
|
||||||
|
|
@ -145,15 +147,16 @@ namespace {
|
||||||
it's out of range. If the conversion is successful, the converted value is
|
it's out of range. If the conversion is successful, the converted value is
|
||||||
stored in \a value; if it was not successful, \a value will contain the
|
stored in \a value; if it was not successful, \a value will contain the
|
||||||
minimum or maximum of T, depending on the sign of \a d. If \c T is
|
minimum or maximum of T, depending on the sign of \a d. If \c T is
|
||||||
unsigned, then \a value contains the absolute value of \a v.
|
unsigned, then \a value contains the absolute value of \a v. If \c T is \c
|
||||||
|
float, an underflow is also signalled by returning false and setting \a
|
||||||
|
value to zero.
|
||||||
|
|
||||||
This function works for v containing infinities, but not NaN. It's the
|
This function works for v containing infinities, but not NaN. It's the
|
||||||
caller's responsibility to exclude that possibility before calling it.
|
caller's responsibility to exclude that possibility before calling it.
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template <typename T> static inline std::enable_if_t<std::is_integral_v<T>, bool>
|
||||||
static inline bool convertDoubleTo(double v, T *value, bool allow_precision_upgrade = true)
|
convertDoubleTo(double v, T *value, bool allow_precision_upgrade = true)
|
||||||
{
|
{
|
||||||
static_assert(std::numeric_limits<T>::is_integer);
|
|
||||||
static_assert(std::is_integral_v<T>);
|
static_assert(std::is_integral_v<T>);
|
||||||
constexpr bool TypeIsLarger = std::numeric_limits<T>::digits > std::numeric_limits<double>::digits;
|
constexpr bool TypeIsLarger = std::numeric_limits<T>::digits > std::numeric_limits<double>::digits;
|
||||||
|
|
||||||
|
|
@ -278,6 +281,40 @@ QT_WARNING_DISABLE_FLOAT_COMPARE
|
||||||
QT_WARNING_POP
|
QT_WARNING_POP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T> static inline
|
||||||
|
std::enable_if_t<std::is_floating_point_v<T> || std::is_same_v<T, qfloat16>, bool>
|
||||||
|
convertDoubleTo(double v, T *value, bool allow_precision_upgrade = true)
|
||||||
|
{
|
||||||
|
Q_UNUSED(allow_precision_upgrade);
|
||||||
|
constexpr T Huge = std::numeric_limits<T>::infinity();
|
||||||
|
|
||||||
|
if constexpr (std::numeric_limits<double>::max_exponent <=
|
||||||
|
std::numeric_limits<T>::max_exponent) {
|
||||||
|
// no UB can happen
|
||||||
|
*value = T(v);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!qt_is_finite(v) && std::numeric_limits<T>::has_infinity) {
|
||||||
|
// infinity (or NaN)
|
||||||
|
*value = T(v);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for in-range value to ensure the conversion is not UB (see the
|
||||||
|
// comment above for Standard language).
|
||||||
|
if (std::fabs(v) > (std::numeric_limits<T>::max)()) {
|
||||||
|
*value = v < 0 ? -Huge : Huge;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*value = T(v);
|
||||||
|
if (v != 0 && *value == 0) {
|
||||||
|
// Underflow through loss of precision
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T> inline bool add_overflow(T v1, T v2, T *r) { return qAddOverflow(v1, v2, r); }
|
template <typename T> inline bool add_overflow(T v1, T v2, T *r) { return qAddOverflow(v1, v2, r); }
|
||||||
template <typename T> inline bool sub_overflow(T v1, T v2, T *r) { return qSubOverflow(v1, v2, r); }
|
template <typename T> inline bool sub_overflow(T v1, T v2, T *r) { return qSubOverflow(v1, v2, r); }
|
||||||
template <typename T> inline bool mul_overflow(T v1, T v2, T *r) { return qMulOverflow(v1, v2, r); }
|
template <typename T> inline bool mul_overflow(T v1, T v2, T *r) { return qMulOverflow(v1, v2, r); }
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,10 @@
|
||||||
|
|
||||||
#include "qlocale.h"
|
#include "qlocale.h"
|
||||||
|
|
||||||
#include <QtCore/private/qglobal_p.h>
|
|
||||||
#include <QtCore/qcalendar.h>
|
#include <QtCore/qcalendar.h>
|
||||||
#include <QtCore/qlist.h>
|
#include <QtCore/qlist.h>
|
||||||
#include <QtCore/qnumeric.h>
|
#include <QtCore/qnumeric.h>
|
||||||
|
#include <QtCore/private/qnumeric_p.h>
|
||||||
#include <QtCore/qstring.h>
|
#include <QtCore/qstring.h>
|
||||||
#include <QtCore/qvariant.h>
|
#include <QtCore/qvariant.h>
|
||||||
#include <QtCore/qvarlengtharray.h>
|
#include <QtCore/qvarlengtharray.h>
|
||||||
|
|
@ -304,23 +304,14 @@ public:
|
||||||
unsigned flags = NoFlags) const;
|
unsigned flags = NoFlags) const;
|
||||||
|
|
||||||
// this function is meant to be called with the result of stringToDouble or bytearrayToDouble
|
// this function is meant to be called with the result of stringToDouble or bytearrayToDouble
|
||||||
|
// so *ok must have been properly set (if not null)
|
||||||
[[nodiscard]] static float convertDoubleToFloat(double d, bool *ok)
|
[[nodiscard]] static float convertDoubleToFloat(double d, bool *ok)
|
||||||
{
|
{
|
||||||
if (qIsInf(d))
|
float result;
|
||||||
return float(d);
|
bool b = convertDoubleTo<float>(d, &result);
|
||||||
if (std::fabs(d) > (std::numeric_limits<float>::max)()) {
|
if (ok && *ok)
|
||||||
if (ok)
|
*ok = b;
|
||||||
*ok = false;
|
return result;
|
||||||
const float huge = std::numeric_limits<float>::infinity();
|
|
||||||
return d < 0 ? -huge : huge;
|
|
||||||
}
|
|
||||||
if (d != 0 && float(d) == 0) {
|
|
||||||
// Values that underflow double already failed. Match them:
|
|
||||||
if (ok)
|
|
||||||
*ok = false;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return float(d);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] double stringToDouble(QStringView str, bool *ok,
|
[[nodiscard]] double stringToDouble(QStringView str, bool *ok,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue