19#include "QtCore/private/qglobal_p.h"
20#include "QtCore/qnumeric.h"
21#include "QtCore/qsimd.h"
26#ifndef __has_extension
27# define __has_extension(X) 0
30#if !defined(Q_CC_MSVC) && defined(Q_OS_QNX)
33# define QT_MATH_H_DEFINES_MACROS
61#if defined(QT_MATH_H_DEFINES_MACROS)
62# undef QT_MATH_H_DEFINES_MACROS
85 static_assert(std::numeric_limits<double>::has_infinity,
86 "platform has no definition for infinity for type double");
87 return std::numeric_limits<double>::infinity();
90#if QT_CONFIG(signaling_nan)
93 static_assert(std::numeric_limits<double>::has_signaling_NaN,
94 "platform has no definition for signaling NaN for type double");
95 return std::numeric_limits<double>::signaling_NaN();
102 static_assert(std::numeric_limits<double>::has_quiet_NaN,
103 "platform has no definition for quiet NaN for type double");
104 return std::numeric_limits<double>::quiet_NaN();
161template <
typename T>
static inline std::enable_if_t<std::is_integral_v<T>,
bool>
162convertDoubleTo(
double v, T *
value,
bool allow_precision_upgrade =
true)
164 static_assert(std::is_integral_v<T>);
165 constexpr bool TypeIsLarger = std::numeric_limits<T>::digits > std::numeric_limits<double>::digits;
167 if constexpr (TypeIsLarger) {
168 using S = std::make_signed_t<T>;
169 constexpr S max_mantissa =
S(1) << std::numeric_limits<double>::digits;
173 if (!allow_precision_upgrade && !(
v <=
double(max_mantissa) &&
v >=
double(-max_mantissa - 1)))
177 constexpr T Tmin = (std::numeric_limits<T>::min)();
178 constexpr T Tmax = (std::numeric_limits<T>::max)();
190#if defined(Q_PROCESSOR_X86_64) && defined(__SSE2__)
199 if (std::numeric_limits<T>::is_signed) {
200 __m128d mv = _mm_set_sd(
v);
204 *
value = T(_mm_cvtt_roundsd_i64(mv, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC));
206 *
value = _mm_cvtt_roundsd_i32(mv, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
208 *
value =
sizeof(T) > 4 ? T(_mm_cvttsd_si64(mv)) : _mm_cvttsd_si32(mv);
213 if (*
value == Tmin && !_mm_ucomieq_sd(mv, _mm_set_sd(Tmin))) {
222 __m128d mi = _mm_setzero_pd();
223 mi =
sizeof(T) > 4 ? _mm_cvtsi64_sd(mv, *
value) : _mm_cvtsi32_sd(mv, *
value);
224 return _mm_ucomieq_sd(mv, mi);
228 if (!std::numeric_limits<T>::is_signed) {
238 __m128d mv = _mm_set_sd(
v);
242 *
value = T(_mm_cvtt_roundsd_u64(mv, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC));
244 *
value = _mm_cvtt_roundsd_u32(mv, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
246 if (*
value == Tmax) {
249 if (TypeIsLarger || _mm_ucomieq_sd(mv, _mm_set_sd(Tmax)))
254 __m128d mi = _mm_setzero_pd();
255 mi =
sizeof(T) > 4 ? _mm_cvtu64_sd(mv, *
value) : _mm_cvtu32_sd(mv, *
value);
256 return _mm_ucomieq_sd(mv, mi);
262 if (std::numeric_limits<T>::is_signed) {
263 supremum = -1.0 * Tmin;
268 using ST =
typename std::make_signed<T>::type;
269 supremum = -2.0 * (std::numeric_limits<ST>::min)();
288template <
typename T>
static
289std::enable_if_t<std::is_floating_point_v<T> || std::is_same_v<T, qfloat16>,
bool>
290convertDoubleTo(
double v, T *
value,
bool allow_precision_upgrade =
true)
293 constexpr T Huge = std::numeric_limits<T>::infinity();
295 if constexpr (std::numeric_limits<double>::max_exponent <=
296 std::numeric_limits<T>::max_exponent) {
302#if defined(__SSE2__) && (defined(Q_CC_GNU) || __has_extension(gnu_asm))
309 unsigned csr = _MM_MASK_MASK;
310 auto sse_check_result = [&](
auto result) {
311 if ((csr & (_MM_EXCEPT_UNDERFLOW | _MM_EXCEPT_OVERFLOW)) == 0)
313 if (csr & _MM_EXCEPT_OVERFLOW)
328 if constexpr (std::is_same_v<T, float>) {
330 asm (
"vldmxcsr %[csr]\n\t"
331 "vcvtsd2ss %[in], %[in], %[out]\n\t"
333 : [csr]
"+m" (csr), [
out]
"=v" (*
value) : [
in]
"v" (
v));
335 asm (
"ldmxcsr %[csr]\n\t"
336 "cvtsd2ss %[in], %[out]\n\t"
338 : [csr]
"+m" (csr), [
out]
"=v" (*
value) : [
in]
"v" (
v));
340 return sse_check_result(*
value);
343# if defined(__F16C__) || defined(__AVX512FP16__)
344 if constexpr (
sizeof(T) == 2 && std::numeric_limits<T>::max_exponent == 16) {
346 auto doConvert = [&](
auto *
out) {
347 asm (
"vldmxcsr %[csr]\n\t"
348# ifdef __AVX512FP16__
350 "vcvtsd2sh %[in], %[in], %[out]\n\t"
352 "vcvtsd2ss %[in], %[in], %[out]\n\t"
353 "vcvtps2ph %[rc], %[out], %[out]\n\t"
356 : [csr]
"+m" (csr), [
out]
"=v" (*
out)
357 : [
in]
"v" (
v), [rc]
"i" (_MM_FROUND_CUR_DIRECTION)
359 return sse_check_result(
out);
362 if constexpr (std::is_same_v<T, qfloat16> && !std::is_void_v<typename T::NativeType>) {
363 typename T::NativeType tmp;
364 bool b = doConvert(&tmp);
370 return doConvert(
value);
377 if (!
qt_is_finite(
v) && std::numeric_limits<T>::has_infinity) {
385 if (std::fabs(
v) > (std::numeric_limits<T>::max)()) {
386 *
value =
v < 0 ? -Huge : Huge;
391 if (
v != 0 && *
value == 0) {
402template <
typename T, T V2>
bool add_overflow(T
v1, std::integral_constant<T, V2>, T *
r)
404 return qAddOverflow<T, V2>(
v1, std::integral_constant<T, V2>{},
r);
407template <auto V2,
typename T>
bool add_overflow(T
v1, T *
r)
409 return qAddOverflow<V2, T>(
v1,
r);
412template <
typename T, T V2>
bool sub_overflow(T
v1, std::integral_constant<T, V2>, T *
r)
414 return qSubOverflow<T, V2>(
v1, std::integral_constant<T, V2>{},
r);
417template <auto V2,
typename T>
bool sub_overflow(T
v1, T *
r)
419 return qSubOverflow<V2, T>(
v1,
r);
422template <
typename T, T V2>
bool mul_overflow(T
v1, std::integral_constant<T, V2>, T *
r)
424 return qMulOverflow<T, V2>(
v1, std::integral_constant<T, V2>{},
r);
427template <auto V2,
typename T>
bool mul_overflow(T
v1, T *
r)
429 return qMulOverflow<V2, T>(
v1,
r);
441template <
typename To,
typename From>
444 static_assert(std::is_integral_v<To>);
445 static_assert(std::is_integral_v<From>);
448 constexpr auto Lo = (std::numeric_limits<To>::min)();
449 constexpr auto Hi = (std::numeric_limits<To>::max)();
451 if constexpr (std::is_signed_v<From> == std::is_signed_v<To>) {
457 if constexpr (std::is_signed_v<From>) {
463 using FromU = std::make_unsigned_t<From>;
464 using ToU = std::make_unsigned_t<To>;
465 return FromU(
x) > ToU(Hi) ? Hi : To(
x);
\keyword 16-bit Floating Point Support\inmodule QtCore \inheaderfile QFloat16
Combined button and popup list for selecting options.
static Q_DECL_CONST_FUNCTION bool isinf(double d)
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)
#define Q_DECL_CONST_FUNCTION
#define QT_WARNING_DISABLE_FLOAT_COMPARE
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
std::enable_if_t< std::is_unsigned_v< T >, bool > qAddOverflow(T v1, T v2, T *r)
std::enable_if_t< std::is_unsigned_v< T >, bool > qSubOverflow(T v1, T v2, T *r)
std::enable_if_t< std::is_unsigned_v< T >||std::is_signed_v< T >, bool > qMulOverflow(T v1, T v2, T *r)
static constexpr auto qt_saturate(From x)
static Q_DECL_CONST_FUNCTION bool qt_is_nan(double d)
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)
GLint GLfloat GLfloat GLfloat v2
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
QTextStream out(stdout)
[7]