20#include "QtCore/private/qglobal_p.h"
21#include "QtCore/qnumeric.h"
22#include "QtCore/qsimd.h"
27#include <QtCore/q26numeric.h>
30# define __has_extension(X) 0
33#if !defined(Q_CC_MSVC) && defined(Q_OS_QNX)
36# define QT_MATH_H_DEFINES_MACROS
64#if defined(QT_MATH_H_DEFINES_MACROS)
65# undef QT_MATH_H_DEFINES_MACROS
88 static_assert(
std::numeric_limits<
double>::has_infinity,
89 "platform has no definition for infinity for type double");
90 return std::numeric_limits<
double>::infinity();
93#if QT_CONFIG(signaling_nan)
94constexpr Q_DECL_CONST_FUNCTION
static inline double qt_snan()
noexcept
96 static_assert(std::numeric_limits<
double>::has_signaling_NaN,
97 "platform has no definition for signaling NaN for type double");
98 return std::numeric_limits<
double>::signaling_NaN();
105 static_assert(
std::numeric_limits<
double>::has_quiet_NaN,
106 "platform has no definition for quiet NaN for type double");
107 return std::numeric_limits<
double>::quiet_NaN();
112 return qnumeric_std_wrapper::isinf(d);
117 return qnumeric_std_wrapper::isnan(d);
122 return qnumeric_std_wrapper::isfinite(d);
127 return qnumeric_std_wrapper::fpclassify(d);
132 return qnumeric_std_wrapper::isinf(f);
137 return qnumeric_std_wrapper::isnan(f);
142 return qnumeric_std_wrapper::isfinite(f);
147 return qnumeric_std_wrapper::fpclassify(f);
153
154
155
156
157
158
159
160
161
162
163
164template <
typename T>
static inline std::enable_if_t<std::is_integral_v<T>,
bool>
165convertDoubleTo(
double v, T *value,
bool allow_precision_upgrade =
true)
167 static_assert(
std::is_integral_v<T>);
168 constexpr bool TypeIsLarger =
std::numeric_limits<T>::digits >
std::numeric_limits<
double>::digits;
170 if constexpr (TypeIsLarger) {
171 using S = std::make_signed_t<T>;
172 constexpr S max_mantissa = S(1) <<
std::numeric_limits<
double>::digits;
176 if (!allow_precision_upgrade && !(v <=
double(max_mantissa) && v >=
double(-max_mantissa - 1)))
180 constexpr T Tmin = (
std::numeric_limits<T>::min)();
181 constexpr T Tmax = (
std::numeric_limits<T>::max)();
193#if defined(Q_PROCESSOR_X86_64) && defined(__SSE2__
)
202 if (std::numeric_limits<T>::is_signed) {
203 __m128d mv = _mm_set_sd(v);
207 *value = T(_mm_cvtt_roundsd_i64(mv, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC));
209 *value = _mm_cvtt_roundsd_i32(mv, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
211 *value =
sizeof(T) > 4 ? T(_mm_cvttsd_si64(mv)) : _mm_cvttsd_si32(mv);
216 if (*value == Tmin && !_mm_ucomieq_sd(mv, _mm_set_sd(Tmin))) {
225 __m128d mi = _mm_setzero_pd();
226 mi =
sizeof(T) > 4 ? _mm_cvtsi64_sd(mv, *value) : _mm_cvtsi32_sd(mv, *value);
227 return _mm_ucomieq_sd(mv, mi);
231 if (!std::numeric_limits<T>::is_signed) {
241 __m128d mv = _mm_set_sd(v);
245 *value = T(_mm_cvtt_roundsd_u64(mv, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC));
247 *value = _mm_cvtt_roundsd_u32(mv, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
249 if (*value == Tmax) {
252 if (TypeIsLarger || _mm_ucomieq_sd(mv, _mm_set_sd(
double(Tmax))))
257 __m128d mi = _mm_setzero_pd();
258 mi =
sizeof(T) > 4 ? _mm_cvtu64_sd(mv, *value) : _mm_cvtu32_sd(mv, *value);
259 return _mm_ucomieq_sd(mv, mi);
265 if (
std::numeric_limits<T>::is_signed) {
266 supremum = -1.0 * Tmin;
271 using ST =
typename std::make_signed<T>::type;
272 supremum = -2.0 * (
std::numeric_limits<ST>::min)();
284QT_WARNING_DISABLE_FLOAT_COMPARE
291template <
typename T>
static
292std::enable_if_t<std::is_floating_point_v<T> || std::is_same_v<T, qfloat16>,
bool>
293convertDoubleTo(
double v, T *value,
bool allow_precision_upgrade =
true)
295 Q_UNUSED(allow_precision_upgrade);
296 constexpr T Huge =
std::numeric_limits<T>::infinity();
298 if constexpr (
std::numeric_limits<
double>::max_exponent <=
299 std::numeric_limits<T>::max_exponent) {
305#if defined(__SSE2__
) && (defined(Q_CC_GNU) || __has_extension(gnu_asm))
312 unsigned csr = _MM_MASK_MASK;
313 auto sse_check_result = [&](
auto result) {
314 if ((csr & (_MM_EXCEPT_UNDERFLOW | _MM_EXCEPT_OVERFLOW)) == 0)
316 if (csr & _MM_EXCEPT_OVERFLOW)
331 if constexpr (
std::is_same_v<T,
float>) {
333 asm (
"vldmxcsr %[csr]\n\t"
334 "vcvtsd2ss %[in], %[in], %[out]\n\t"
336 : [csr]
"+m" (csr), [out]
"=v" (*value) : [in]
"v" (v));
338 asm (
"ldmxcsr %[csr]\n\t"
339 "cvtsd2ss %[in], %[out]\n\t"
341 : [csr]
"+m" (csr), [out]
"=v" (*value) : [in]
"v" (v));
343 return sse_check_result(*value);
346# if defined(__F16C__) || defined(__AVX512FP16__)
347 if constexpr (
sizeof(T) == 2 && std::numeric_limits<T>::max_exponent == 16) {
349 auto doConvert = [&](
auto *out) {
350 asm (
"vldmxcsr %[csr]\n\t"
351# ifdef __AVX512FP16__
353 "vcvtsd2sh %[in], %[in], %[out]\n\t"
355 "vcvtsd2ss %[in], %[in], %[out]\n\t"
356 "vcvtps2ph %[rc], %[out], %[out]\n\t"
359 : [csr]
"+m" (csr), [out]
"=v" (*out)
360 : [in]
"v" (v), [rc]
"i" (_MM_FROUND_CUR_DIRECTION)
362 return sse_check_result(out);
365 if constexpr (std::is_same_v<T, qfloat16> && !std::is_void_v<
typename T::NativeType>) {
366 typename T::NativeType tmp;
367 bool b = doConvert(&tmp);
373 return doConvert(value);
380 if (!qt_is_finite(v) && std::numeric_limits<T>::has_infinity) {
388 if (
std::fabs(v) >
double{(
std::numeric_limits<T>::max)()}) {
389 *value = v < 0 ? -Huge : Huge;
394 if (v != 0 && *value == 0) {
401template <
typename T>
inline bool add_overflow(T v1, T v2, T *r) {
return qAddOverflow(v1, v2, r); }
402template <
typename T>
inline bool sub_overflow(T v1, T v2, T *r) {
return qSubOverflow(v1, v2, r); }
403template <
typename T>
inline bool mul_overflow(T v1, T v2, T *r) {
return qMulOverflow(v1, v2, r); }
405template <
typename T, T V2>
bool add_overflow(T v1, std::integral_constant<T, V2>, T *r)
407 return qAddOverflow<T, V2>(v1, std::integral_constant<T, V2>{}, r);
410template <
auto V2,
typename T>
bool add_overflow(T v1, T *r)
412 return qAddOverflow<V2, T>(v1, r);
415template <
typename T, T V2>
bool sub_overflow(T v1, std::integral_constant<T, V2>, T *r)
417 return qSubOverflow<T, V2>(v1, std::integral_constant<T, V2>{}, r);
420template <
auto V2,
typename T>
bool sub_overflow(T v1, T *r)
422 return qSubOverflow<V2, T>(v1, r);
425template <
typename T, T V2>
bool mul_overflow(T v1, std::integral_constant<T, V2>, T *r)
427 return qMulOverflow<T, V2>(v1, std::integral_constant<T, V2>{}, r);
430template <
auto V2,
typename T>
bool mul_overflow(T v1, T *r)
432 return qMulOverflow<V2, T>(v1, r);
437template <
typename To,
typename From>
440 return q26::saturate_cast<To>(x);
\keyword 16-bit Floating Point Support\inmodule QtCore \inheaderfile QFloat16
Combined button and popup list for selecting options.
constexpr const T & min(const T &a, const T &b)
constexpr bool HasLargerInt
constexpr int qSaturateRound(FP value)
constexpr std::enable_if_t<(std::is_unsigned_v< T >||std::is_signed_v< T >), bool > qMulOverflowGeneric(T v1, T v2, T *r)
constexpr auto qUnsignedAbs(T t)
constexpr std::enable_if_t< std::is_unsigned_v< T >, bool > qAddOverflowGeneric(T v1, T v2, T *r)
constexpr std::enable_if_t< std::is_same_v< T, decltype(+T{})>, bool > qMulOverflowWideMultiplication(T v1, T v2, T *r)
constexpr bool fuzzyCompare(const T &lhs, const S &rhs) noexcept
constexpr Result qCheckedFPConversionToInteger(FP value)
static Q_DECL_CONST_FUNCTION bool isinf(double d)
static Q_DECL_CONST_FUNCTION bool isnan(float f)
static Q_DECL_CONST_FUNCTION bool isinf(float f)
static Q_DECL_CONST_FUNCTION int fpclassify(float f)
static Q_DECL_CONST_FUNCTION int fpclassify(double d)
static Q_DECL_CONST_FUNCTION bool isfinite(double d)
static Q_DECL_CONST_FUNCTION bool isnan(double d)
static Q_DECL_CONST_FUNCTION bool isfinite(float f)
static quint64 d2i(double d)
Q_CORE_EXPORT int qFpClassify(float val)
Q_CORE_EXPORT int qFpClassify(double val)
static quint32 f2i(float f)
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsFinite(float f)
constexpr T qAbs(const T &t)
constexpr std::enable_if< std::is_integral< T >::value, bool >::type qIsFinite(T)
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsFinite(double d)
constexpr bool qSubOverflow(T v1, T *r)
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qInf()
constexpr bool qMulOverflow(T v1, T *r)
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsNaN(float f)
constexpr bool qFuzzyIsNull(double d) noexcept
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsInf(double d)
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsInf(float f)
constexpr bool qFuzzyCompare(float p1, float p2) noexcept
constexpr bool qSubOverflow(T v1, std::integral_constant< T, V2 >, T *r)
constexpr bool qAddOverflow(T v1, T *r)
constexpr std::enable_if< std::is_integral< T >::value, bool >::type qIsNaN(T)
constexpr std::enable_if_t< std::is_unsigned_v< T >||std::is_signed_v< T >, bool > qMulOverflow(T v1, T v2, T *r)
constexpr qint64 qRound64(double d)
constexpr int qRound(float f)
constexpr int qRound(double d)
constexpr bool qIsNull(float f) noexcept
constexpr bool qFuzzyIsNull(float f) noexcept
constexpr std::enable_if_t< std::is_unsigned_v< T >, bool > qSubOverflow(T v1, T v2, T *r)
constexpr bool qFuzzyCompare(double p1, double p2) noexcept
constexpr qint64 qRound64(float f)
constexpr bool qMulOverflow(T v1, std::integral_constant< T, V2 >, T *r)
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qQNaN()
constexpr std::enable_if_t< std::is_unsigned_v< T >, bool > qAddOverflow(T v1, T v2, T *r)
constexpr bool qAddOverflow(T v1, std::integral_constant< T, V2 >, T *r)
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsNaN(double d)
QT_WARNING_PUSH QT_WARNING_DISABLE_FLOAT_COMPARE constexpr bool qIsNull(double d) noexcept
static constexpr auto qt_saturate(From x)
static Q_DECL_CONST_FUNCTION bool qt_is_nan(double d)
#define __has_extension(X)
static Q_DECL_CONST_FUNCTION int qt_fpclassify(float f)
constexpr static Q_DECL_CONST_FUNCTION double qt_qnan() noexcept
constexpr static Q_DECL_CONST_FUNCTION double qt_inf() noexcept
static Q_DECL_CONST_FUNCTION int qt_fpclassify(double d)
static Q_DECL_CONST_FUNCTION bool qt_is_inf(double d)
static Q_DECL_CONST_FUNCTION bool qt_is_finite(double d)
static Q_DECL_CONST_FUNCTION bool qt_is_finite(float f)
static Q_DECL_CONST_FUNCTION bool qt_is_nan(float f)
static Q_DECL_CONST_FUNCTION bool qt_is_inf(float f)