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
|
||||
|
||||
class qfloat16;
|
||||
|
||||
namespace qnumeric_std_wrapper {
|
||||
#if defined(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
|
||||
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
|
||||
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
|
||||
caller's responsibility to exclude that possibility before calling it.
|
||||
*/
|
||||
template<typename T>
|
||||
static inline bool convertDoubleTo(double v, T *value, bool allow_precision_upgrade = true)
|
||||
template <typename T> static inline std::enable_if_t<std::is_integral_v<T>, bool>
|
||||
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>);
|
||||
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
|
||||
}
|
||||
|
||||
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 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); }
|
||||
|
|
|
|||
|
|
@ -18,10 +18,10 @@
|
|||
|
||||
#include "qlocale.h"
|
||||
|
||||
#include <QtCore/private/qglobal_p.h>
|
||||
#include <QtCore/qcalendar.h>
|
||||
#include <QtCore/qlist.h>
|
||||
#include <QtCore/qnumeric.h>
|
||||
#include <QtCore/private/qnumeric_p.h>
|
||||
#include <QtCore/qstring.h>
|
||||
#include <QtCore/qvariant.h>
|
||||
#include <QtCore/qvarlengtharray.h>
|
||||
|
|
@ -304,23 +304,14 @@ public:
|
|||
unsigned flags = NoFlags) const;
|
||||
|
||||
// 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)
|
||||
{
|
||||
if (qIsInf(d))
|
||||
return float(d);
|
||||
if (std::fabs(d) > (std::numeric_limits<float>::max)()) {
|
||||
if (ok)
|
||||
*ok = false;
|
||||
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);
|
||||
float result;
|
||||
bool b = convertDoubleTo<float>(d, &result);
|
||||
if (ok && *ok)
|
||||
*ok = b;
|
||||
return result;
|
||||
}
|
||||
|
||||
[[nodiscard]] double stringToDouble(QStringView str, bool *ok,
|
||||
|
|
|
|||
Loading…
Reference in New Issue