File indexing completed on 2025-09-17 09:09:16
0001
0002
0003
0004
0005 #ifndef QFLOAT16_H
0006 #define QFLOAT16_H
0007
0008 #include <QtCore/qcompare.h>
0009 #include <QtCore/qglobal.h>
0010 #include <QtCore/qhashfunctions.h>
0011 #include <QtCore/qmath.h>
0012 #include <QtCore/qnamespace.h>
0013 #include <QtCore/qtconfigmacros.h>
0014 #include <QtCore/qtformat_impl.h>
0015 #include <QtCore/qtypes.h>
0016
0017 #include <limits>
0018 #include <string.h>
0019 #include <type_traits>
0020
0021 #if defined(QT_COMPILER_SUPPORTS_F16C) && defined(__AVX2__) && !defined(__F16C__)
0022
0023
0024
0025
0026 # if defined(Q_CC_MSVC) && !defined(Q_CC_CLANG)
0027 # define __F16C__ 1
0028 # endif
0029 #endif
0030
0031 #if defined(QT_COMPILER_SUPPORTS_F16C) && defined(__F16C__)
0032 #include <immintrin.h>
0033 #endif
0034
0035 QT_BEGIN_NAMESPACE
0036
0037 #if 0
0038 #pragma qt_class(QFloat16)
0039 #pragma qt_no_master_include
0040 #endif
0041
0042 #ifndef QT_NO_DATASTREAM
0043 class QDataStream;
0044 #endif
0045 class QTextStream;
0046
0047 class qfloat16
0048 {
0049 struct Wrap
0050 {
0051
0052
0053 quint16 b16;
0054 constexpr inline explicit Wrap(int value) : b16(quint16(value)) {}
0055 };
0056
0057 template <typename T>
0058 using if_type_is_integral = std::enable_if_t<std::is_integral_v<std::remove_reference_t<T>>, bool>;
0059
0060 public:
0061 using NativeType = QtPrivate::NativeFloat16Type;
0062
0063 static constexpr bool IsNative = QFLOAT16_IS_NATIVE;
0064 using NearestFloat = std::conditional_t<IsNative, NativeType, float>;
0065
0066 constexpr inline qfloat16() noexcept : b16(0) {}
0067 explicit qfloat16(Qt::Initialization) noexcept { }
0068
0069 #if QFLOAT16_IS_NATIVE
0070 constexpr inline qfloat16(NativeType f) : nf(f) {}
0071 constexpr operator NativeType() const noexcept { return nf; }
0072 #else
0073 inline qfloat16(float f) noexcept;
0074 inline operator float() const noexcept;
0075 #endif
0076 template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T> && !std::is_same_v<T, NearestFloat>>>
0077 constexpr explicit qfloat16(T value) noexcept : qfloat16(NearestFloat(value)) {}
0078
0079
0080 bool isInf() const noexcept { return (b16 & 0x7fff) == 0x7c00; }
0081 bool isNaN() const noexcept { return (b16 & 0x7fff) > 0x7c00; }
0082 bool isFinite() const noexcept { return (b16 & 0x7fff) < 0x7c00; }
0083 Q_CORE_EXPORT int fpClassify() const noexcept;
0084
0085 qfloat16 copySign(qfloat16 sign) const noexcept
0086 { return qfloat16(Wrap((sign.b16 & 0x8000) | (b16 & 0x7fff))); }
0087
0088
0089 #ifdef __STDCPP_FLOAT16_T__
0090 private:
0091 using Bounds = std::numeric_limits<NativeType>;
0092 public:
0093 static constexpr qfloat16 _limit_epsilon() noexcept { return Bounds::epsilon(); }
0094 static constexpr qfloat16 _limit_min() noexcept { return Bounds::min(); }
0095 static constexpr qfloat16 _limit_denorm_min() noexcept { return Bounds::denorm_min(); }
0096 static constexpr qfloat16 _limit_max() noexcept { return Bounds::max(); }
0097 static constexpr qfloat16 _limit_lowest() noexcept { return Bounds::lowest(); }
0098 static constexpr qfloat16 _limit_infinity() noexcept { return Bounds::infinity(); }
0099 static constexpr qfloat16 _limit_quiet_NaN() noexcept { return Bounds::quiet_NaN(); }
0100 #if QT_CONFIG(signaling_nan)
0101 static constexpr qfloat16 _limit_signaling_NaN() noexcept { return Bounds::signaling_NaN(); }
0102 #endif
0103 #else
0104 static constexpr qfloat16 _limit_epsilon() noexcept { return qfloat16(Wrap(0x1400)); }
0105 static constexpr qfloat16 _limit_min() noexcept { return qfloat16(Wrap(0x400)); }
0106 static constexpr qfloat16 _limit_denorm_min() noexcept { return qfloat16(Wrap(1)); }
0107 static constexpr qfloat16 _limit_max() noexcept { return qfloat16(Wrap(0x7bff)); }
0108 static constexpr qfloat16 _limit_lowest() noexcept { return qfloat16(Wrap(0xfbff)); }
0109 static constexpr qfloat16 _limit_infinity() noexcept { return qfloat16(Wrap(0x7c00)); }
0110 static constexpr qfloat16 _limit_quiet_NaN() noexcept { return qfloat16(Wrap(0x7e00)); }
0111 #if QT_CONFIG(signaling_nan)
0112 static constexpr qfloat16 _limit_signaling_NaN() noexcept { return qfloat16(Wrap(0x7d00)); }
0113 #endif
0114 #endif
0115 inline constexpr bool isNormal() const noexcept
0116 { return (b16 & 0x7c00) && (b16 & 0x7c00) != 0x7c00; }
0117 private:
0118
0119
0120
0121
0122
0123
0124 union {
0125 quint16 b16;
0126 #if QFLOAT16_IS_NATIVE
0127 NativeType nf;
0128 #endif
0129 };
0130 constexpr inline explicit qfloat16(Wrap nibble) noexcept :
0131 #if QFLOAT16_IS_NATIVE && defined(__cpp_lib_bit_cast)
0132 nf(std::bit_cast<NativeType>(nibble.b16))
0133 #else
0134 b16(nibble.b16)
0135 #endif
0136 {}
0137
0138 Q_CORE_EXPORT static const quint32 mantissatable[];
0139 Q_CORE_EXPORT static const quint32 exponenttable[];
0140 Q_CORE_EXPORT static const quint32 offsettable[];
0141 Q_CORE_EXPORT static const quint16 basetable[];
0142 Q_CORE_EXPORT static const quint16 shifttable[];
0143 Q_CORE_EXPORT static const quint32 roundtable[];
0144
0145 friend bool qIsNull(qfloat16 f) noexcept;
0146
0147 friend inline qfloat16 operator-(qfloat16 a) noexcept
0148 {
0149 qfloat16 f;
0150 f.b16 = a.b16 ^ quint16(0x8000);
0151 return f;
0152 }
0153
0154 friend inline qfloat16 operator+(qfloat16 a, qfloat16 b) noexcept { return qfloat16(static_cast<NearestFloat>(a) + static_cast<NearestFloat>(b)); }
0155 friend inline qfloat16 operator-(qfloat16 a, qfloat16 b) noexcept { return qfloat16(static_cast<NearestFloat>(a) - static_cast<NearestFloat>(b)); }
0156 friend inline qfloat16 operator*(qfloat16 a, qfloat16 b) noexcept { return qfloat16(static_cast<NearestFloat>(a) * static_cast<NearestFloat>(b)); }
0157 friend inline qfloat16 operator/(qfloat16 a, qfloat16 b) noexcept { return qfloat16(static_cast<NearestFloat>(a) / static_cast<NearestFloat>(b)); }
0158
0159 friend size_t qHash(qfloat16 key, size_t seed = 0) noexcept
0160 { return qHash(float(key), seed); }
0161
0162 QT_WARNING_PUSH
0163 QT_WARNING_DISABLE_GCC("-Wfloat-conversion")
0164
0165 #define QF16_MAKE_ARITH_OP_FP(FP, OP) \
0166 friend inline FP operator OP(qfloat16 lhs, FP rhs) noexcept { return static_cast<FP>(lhs) OP rhs; } \
0167 friend inline FP operator OP(FP lhs, qfloat16 rhs) noexcept { return lhs OP static_cast<FP>(rhs); }
0168 #define QF16_MAKE_ARITH_OP_EQ_FP(FP, OP_EQ, OP) \
0169 friend inline qfloat16& operator OP_EQ(qfloat16& lhs, FP rhs) noexcept \
0170 { lhs = qfloat16(NearestFloat(static_cast<FP>(lhs) OP rhs)); return lhs; }
0171 #define QF16_MAKE_ARITH_OP(FP) \
0172 QF16_MAKE_ARITH_OP_FP(FP, +) \
0173 QF16_MAKE_ARITH_OP_FP(FP, -) \
0174 QF16_MAKE_ARITH_OP_FP(FP, *) \
0175 QF16_MAKE_ARITH_OP_FP(FP, /) \
0176 QF16_MAKE_ARITH_OP_EQ_FP(FP, +=, +) \
0177 QF16_MAKE_ARITH_OP_EQ_FP(FP, -=, -) \
0178 QF16_MAKE_ARITH_OP_EQ_FP(FP, *=, *) \
0179 QF16_MAKE_ARITH_OP_EQ_FP(FP, /=, /)
0180
0181 QF16_MAKE_ARITH_OP(long double)
0182 QF16_MAKE_ARITH_OP(double)
0183 QF16_MAKE_ARITH_OP(float)
0184 #if QFLOAT16_IS_NATIVE
0185 QF16_MAKE_ARITH_OP(NativeType)
0186 #endif
0187 #undef QF16_MAKE_ARITH_OP
0188 #undef QF16_MAKE_ARITH_OP_FP
0189
0190 #define QF16_MAKE_ARITH_OP_INT(OP) \
0191 friend inline double operator OP(qfloat16 lhs, int rhs) noexcept { return static_cast<double>(lhs) OP rhs; } \
0192 friend inline double operator OP(int lhs, qfloat16 rhs) noexcept { return lhs OP static_cast<double>(rhs); }
0193
0194 QF16_MAKE_ARITH_OP_INT(+)
0195 QF16_MAKE_ARITH_OP_INT(-)
0196 QF16_MAKE_ARITH_OP_INT(*)
0197 QF16_MAKE_ARITH_OP_INT(/)
0198 #undef QF16_MAKE_ARITH_OP_INT
0199
0200 QT_WARNING_DISABLE_FLOAT_COMPARE
0201
0202 #if QFLOAT16_IS_NATIVE
0203 # define QF16_CONSTEXPR constexpr
0204 # define QF16_PARTIALLY_ORDERED Q_DECLARE_PARTIALLY_ORDERED_LITERAL_TYPE
0205 #else
0206 # define QF16_CONSTEXPR
0207 # define QF16_PARTIALLY_ORDERED Q_DECLARE_PARTIALLY_ORDERED
0208 #endif
0209
0210 friend QF16_CONSTEXPR bool comparesEqual(const qfloat16 &lhs, const qfloat16 &rhs) noexcept
0211 { return static_cast<NearestFloat>(lhs) == static_cast<NearestFloat>(rhs); }
0212 friend QF16_CONSTEXPR
0213 Qt::partial_ordering compareThreeWay(const qfloat16 &lhs, const qfloat16 &rhs) noexcept
0214 { return Qt::compareThreeWay(static_cast<NearestFloat>(lhs), static_cast<NearestFloat>(rhs)); }
0215 QF16_PARTIALLY_ORDERED(qfloat16)
0216
0217 #define QF16_MAKE_ORDER_OP_FP(FP) \
0218 friend QF16_CONSTEXPR bool comparesEqual(const qfloat16 &lhs, FP rhs) noexcept \
0219 { return static_cast<FP>(lhs) == rhs; } \
0220 friend QF16_CONSTEXPR \
0221 Qt::partial_ordering compareThreeWay(const qfloat16 &lhs, FP rhs) noexcept \
0222 { return Qt::compareThreeWay(static_cast<FP>(lhs), rhs); } \
0223 QF16_PARTIALLY_ORDERED(qfloat16, FP)
0224
0225 QF16_MAKE_ORDER_OP_FP(long double)
0226 QF16_MAKE_ORDER_OP_FP(double)
0227 QF16_MAKE_ORDER_OP_FP(float)
0228 #if QFLOAT16_IS_NATIVE
0229 QF16_MAKE_ORDER_OP_FP(qfloat16::NativeType)
0230 #endif
0231 #undef QF16_MAKE_ORDER_OP_FP
0232
0233 template <typename T, if_type_is_integral<T> = true>
0234 friend QF16_CONSTEXPR bool comparesEqual(const qfloat16 &lhs, T rhs) noexcept
0235 { return static_cast<NearestFloat>(lhs) == static_cast<NearestFloat>(rhs); }
0236 template <typename T, if_type_is_integral<T> = true>
0237 friend QF16_CONSTEXPR Qt::partial_ordering compareThreeWay(const qfloat16 &lhs, T rhs) noexcept
0238 { return Qt::compareThreeWay(static_cast<NearestFloat>(lhs), static_cast<NearestFloat>(rhs)); }
0239
0240 QF16_PARTIALLY_ORDERED(qfloat16, qint8)
0241 QF16_PARTIALLY_ORDERED(qfloat16, quint8)
0242 QF16_PARTIALLY_ORDERED(qfloat16, qint16)
0243 QF16_PARTIALLY_ORDERED(qfloat16, quint16)
0244 QF16_PARTIALLY_ORDERED(qfloat16, qint32)
0245 QF16_PARTIALLY_ORDERED(qfloat16, quint32)
0246 QF16_PARTIALLY_ORDERED(qfloat16, long)
0247 QF16_PARTIALLY_ORDERED(qfloat16, unsigned long)
0248 QF16_PARTIALLY_ORDERED(qfloat16, qint64)
0249 QF16_PARTIALLY_ORDERED(qfloat16, quint64)
0250 #ifdef QT_SUPPORTS_INT128
0251 QF16_PARTIALLY_ORDERED(qfloat16, qint128)
0252 QF16_PARTIALLY_ORDERED(qfloat16, quint128)
0253 #endif
0254
0255 #undef QF16_PARTIALLY_ORDERED
0256 #undef QF16_CONSTEXPR
0257
0258 QT_WARNING_POP
0259
0260 #ifndef QT_NO_DATASTREAM
0261 friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &ds, qfloat16 f);
0262 friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &ds, qfloat16 &f);
0263 #endif
0264 friend Q_CORE_EXPORT QTextStream &operator<<(QTextStream &ts, qfloat16 f);
0265 friend Q_CORE_EXPORT QTextStream &operator>>(QTextStream &ts, qfloat16 &f);
0266 };
0267
0268 Q_DECLARE_TYPEINFO(qfloat16, Q_PRIMITIVE_TYPE);
0269
0270 Q_CORE_EXPORT void qFloatToFloat16(qfloat16 *, const float *, qsizetype length) noexcept;
0271 Q_CORE_EXPORT void qFloatFromFloat16(float *, const qfloat16 *, qsizetype length) noexcept;
0272
0273
0274 [[nodiscard]] inline bool qIsInf(qfloat16 f) noexcept { return f.isInf(); }
0275 [[nodiscard]] inline bool qIsNaN(qfloat16 f) noexcept { return f.isNaN(); }
0276 [[nodiscard]] inline bool qIsFinite(qfloat16 f) noexcept { return f.isFinite(); }
0277 [[nodiscard]] inline int qFpClassify(qfloat16 f) noexcept { return f.fpClassify(); }
0278
0279
0280 [[nodiscard]] inline qfloat16 qSqrt(qfloat16 f)
0281 {
0282 #if defined(__cpp_lib_extended_float) && defined(__STDCPP_FLOAT16_T__) && 0
0283
0284 using namespace std;
0285 return sqrt(f);
0286 #elif QFLOAT16_IS_NATIVE && defined(__HAVE_FLOAT16) && __HAVE_FLOAT16
0287
0288 return sqrtf16(f);
0289 #else
0290 bool mathUpdatesErrno = true;
0291 # if defined(__NO_MATH_ERRNO__) || defined(_M_FP_FAST)
0292 mathUpdatesErrno = false;
0293 # elif defined(math_errhandling)
0294 mathUpdatesErrno = (math_errhandling & MATH_ERRNO);
0295 # endif
0296
0297
0298
0299
0300
0301 if (!mathUpdatesErrno || !(0 > f)) {
0302 # if defined(__AVX512FP16__)
0303 __m128h v = _mm_set_sh(f);
0304 v = _mm_sqrt_sh(v, v);
0305 return _mm_cvtsh_h(v);
0306 # endif
0307 }
0308
0309
0310
0311 float f32 = float(f);
0312 f32 = sqrtf(f32);
0313 return qfloat16::NearestFloat(f32);
0314 #endif
0315 }
0316
0317
0318 [[nodiscard]] inline int qRound(qfloat16 d) noexcept
0319 { return qRound(static_cast<float>(d)); }
0320
0321 [[nodiscard]] inline qint64 qRound64(qfloat16 d) noexcept
0322 { return qRound64(static_cast<float>(d)); }
0323
0324 [[nodiscard]] inline bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
0325 {
0326 qfloat16::NearestFloat f1 = static_cast<qfloat16::NearestFloat>(p1);
0327 qfloat16::NearestFloat f2 = static_cast<qfloat16::NearestFloat>(p2);
0328
0329
0330
0331
0332
0333
0334 return (qAbs(f1 - f2) * 102.5f <= qMin(qAbs(f1), qAbs(f2)));
0335 }
0336
0337
0338
0339
0340 [[nodiscard]] inline bool qFuzzyIsNull(qfloat16 f) noexcept
0341 {
0342 return qAbs(f) < 0.00976f;
0343 }
0344
0345 [[nodiscard]] inline bool qIsNull(qfloat16 f) noexcept
0346 {
0347 return (f.b16 & static_cast<quint16>(0x7fff)) == 0;
0348 }
0349
0350 inline int qIntCast(qfloat16 f) noexcept
0351 { return int(static_cast<qfloat16::NearestFloat>(f)); }
0352
0353 #if !defined(Q_QDOC) && !QFLOAT16_IS_NATIVE
0354 QT_WARNING_PUSH
0355 QT_WARNING_DISABLE_CLANG("-Wc99-extensions")
0356 QT_WARNING_DISABLE_GCC("-Wold-style-cast")
0357 inline qfloat16::qfloat16(float f) noexcept
0358 {
0359 #if defined(QT_COMPILER_SUPPORTS_F16C) && defined(__F16C__)
0360 __m128 packsingle = _mm_set_ss(f);
0361 __m128i packhalf = _mm_cvtps_ph(packsingle, 0);
0362 b16 = _mm_extract_epi16(packhalf, 0);
0363 #elif defined (__ARM_FP16_FORMAT_IEEE)
0364 __fp16 f16 = __fp16(f);
0365 memcpy(&b16, &f16, sizeof(quint16));
0366 #else
0367 quint32 u;
0368 memcpy(&u, &f, sizeof(quint32));
0369 const quint32 signAndExp = u >> 23;
0370 const quint16 base = basetable[signAndExp];
0371 const quint16 shift = shifttable[signAndExp];
0372 const quint32 round = roundtable[signAndExp];
0373 quint32 mantissa = (u & 0x007fffff);
0374 if ((signAndExp & 0xff) == 0xff) {
0375 if (mantissa)
0376 mantissa = qMax(1U << shift, mantissa);
0377 } else {
0378
0379
0380 mantissa += round;
0381
0382
0383
0384 if (mantissa & (1 << shift))
0385 --mantissa;
0386 }
0387
0388
0389
0390 b16 = quint16(base + (mantissa >> shift));
0391 #endif
0392 }
0393 QT_WARNING_POP
0394
0395 inline qfloat16::operator float() const noexcept
0396 {
0397 #if defined(QT_COMPILER_SUPPORTS_F16C) && defined(__F16C__)
0398 __m128i packhalf = _mm_cvtsi32_si128(b16);
0399 __m128 packsingle = _mm_cvtph_ps(packhalf);
0400 return _mm_cvtss_f32(packsingle);
0401 #elif defined (__ARM_FP16_FORMAT_IEEE)
0402 __fp16 f16;
0403 memcpy(&f16, &b16, sizeof(quint16));
0404 return float(f16);
0405 #else
0406 quint32 u = mantissatable[offsettable[b16 >> 10] + (b16 & 0x3ff)]
0407 + exponenttable[b16 >> 10];
0408 float f;
0409 memcpy(&f, &u, sizeof(quint32));
0410 return f;
0411 #endif
0412 }
0413 #endif
0414
0415
0416
0417
0418 namespace QtPrivate {
0419 template <> struct QHypotType<qfloat16, qfloat16>
0420 {
0421 using type = qfloat16;
0422 };
0423 template <typename R> struct QHypotType<R, qfloat16>
0424 {
0425 using type = std::conditional_t<std::is_floating_point_v<R>, R, double>;
0426 };
0427 template <typename R> struct QHypotType<qfloat16, R> : QHypotType<R, qfloat16>
0428 {
0429 };
0430 }
0431
0432
0433
0434 inline auto qHypot(qfloat16 x, qfloat16 y)
0435 {
0436 #if defined(QT_COMPILER_SUPPORTS_F16C) && defined(__F16C__) || QFLOAT16_IS_NATIVE
0437 return QtPrivate::QHypotHelper<qfloat16>(x).add(y).result();
0438 #else
0439 return qfloat16(qHypot(float(x), float(y)));
0440 #endif
0441 }
0442
0443
0444 template<typename F, typename ...Fs> auto qHypot(F first, Fs... rest);
0445
0446 template <typename T> typename QtPrivate::QHypotType<T, qfloat16>::type
0447 qHypot(T x, qfloat16 y)
0448 {
0449 if constexpr (std::is_floating_point_v<T>)
0450 return qHypot(x, float(y));
0451 else
0452 return qHypot(qfloat16(x), y);
0453 }
0454 template <typename T> auto qHypot(qfloat16 x, T y)
0455 {
0456 return qHypot(y, x);
0457 }
0458
0459 #if defined(__cpp_lib_hypot) && __cpp_lib_hypot >= 201603L
0460
0461
0462
0463
0464 template <typename Ty, typename Tz,
0465 typename std::enable_if<
0466
0467 !(std::is_same_v<qfloat16, Ty> && std::is_same_v<qfloat16, Tz>), int>::type = 0>
0468 auto qHypot(qfloat16 x, Ty y, Tz z) { return qHypot(qfloat16::NearestFloat(x), y, z); }
0469 template <typename Tx, typename Tz,
0470 typename std::enable_if<
0471
0472 !std::is_same_v<qfloat16, Tx>, int>::type = 0>
0473 auto qHypot(Tx x, qfloat16 y, Tz z) { return qHypot(x, qfloat16::NearestFloat(y), z); }
0474 template <typename Tx, typename Ty,
0475 typename std::enable_if<
0476
0477 !std::is_same_v<qfloat16, Tx> && !std::is_same_v<qfloat16, Ty>, int>::type = 0>
0478 auto qHypot(Tx x, Ty y, qfloat16 z) { return qHypot(x, y, qfloat16::NearestFloat(z)); }
0479
0480
0481 inline auto qHypot(qfloat16 x, qfloat16 y, qfloat16 z)
0482 {
0483 #if (defined(QT_COMPILER_SUPPORTS_F16C) && defined(__F16C__)) || QFLOAT16_IS_NATIVE
0484 return QtPrivate::QHypotHelper<qfloat16>(x).add(y).add(z).result();
0485 #else
0486 return qfloat16(qHypot(float(x), float(y), float(z)));
0487 #endif
0488 }
0489 #endif
0490
0491 QT_END_NAMESPACE
0492
0493 namespace std {
0494 template<>
0495 class numeric_limits<QT_PREPEND_NAMESPACE(qfloat16)> : public numeric_limits<float>
0496 {
0497 public:
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508 static constexpr int digits = 11;
0509 static constexpr int min_exponent = -13;
0510 static constexpr int max_exponent = 16;
0511
0512 static constexpr int digits10 = 3;
0513 static constexpr int max_digits10 = 5;
0514 static constexpr int min_exponent10 = -4;
0515 static constexpr int max_exponent10 = 4;
0516
0517 static constexpr QT_PREPEND_NAMESPACE(qfloat16) epsilon()
0518 { return QT_PREPEND_NAMESPACE(qfloat16)::_limit_epsilon(); }
0519 static constexpr QT_PREPEND_NAMESPACE(qfloat16) (min)()
0520 { return QT_PREPEND_NAMESPACE(qfloat16)::_limit_min(); }
0521 static constexpr QT_PREPEND_NAMESPACE(qfloat16) denorm_min()
0522 { return QT_PREPEND_NAMESPACE(qfloat16)::_limit_denorm_min(); }
0523 static constexpr QT_PREPEND_NAMESPACE(qfloat16) (max)()
0524 { return QT_PREPEND_NAMESPACE(qfloat16)::_limit_max(); }
0525 static constexpr QT_PREPEND_NAMESPACE(qfloat16) lowest()
0526 { return QT_PREPEND_NAMESPACE(qfloat16)::_limit_lowest(); }
0527 static constexpr QT_PREPEND_NAMESPACE(qfloat16) infinity()
0528 { return QT_PREPEND_NAMESPACE(qfloat16)::_limit_infinity(); }
0529 static constexpr QT_PREPEND_NAMESPACE(qfloat16) quiet_NaN()
0530 { return QT_PREPEND_NAMESPACE(qfloat16)::_limit_quiet_NaN(); }
0531 #if QT_CONFIG(signaling_nan)
0532 static constexpr QT_PREPEND_NAMESPACE(qfloat16) signaling_NaN()
0533 { return QT_PREPEND_NAMESPACE(qfloat16)::_limit_signaling_NaN(); }
0534 #else
0535 static constexpr bool has_signaling_NaN = false;
0536 #endif
0537 };
0538
0539 template<> class numeric_limits<const QT_PREPEND_NAMESPACE(qfloat16)>
0540 : public numeric_limits<QT_PREPEND_NAMESPACE(qfloat16)> {};
0541 template<> class numeric_limits<volatile QT_PREPEND_NAMESPACE(qfloat16)>
0542 : public numeric_limits<QT_PREPEND_NAMESPACE(qfloat16)> {};
0543 template<> class numeric_limits<const volatile QT_PREPEND_NAMESPACE(qfloat16)>
0544 : public numeric_limits<QT_PREPEND_NAMESPACE(qfloat16)> {};
0545
0546
0547
0548 }
0549
0550
0551 #ifdef QT_SUPPORTS_STD_FORMAT
0552
0553 QT_BEGIN_NAMESPACE
0554
0555 namespace QtPrivate {
0556
0557
0558 template <typename T, typename CharT>
0559 constexpr bool FormatterDoesNotExist =
0560 std::negation_v<
0561 std::disjunction<
0562 std::is_default_constructible<std::formatter<T, CharT>>,
0563 std::is_copy_constructible<std::formatter<T, CharT>>,
0564 std::is_move_constructible<std::formatter<T, CharT>>,
0565 std::is_copy_assignable<std::formatter<T, CharT>>,
0566 std::is_move_assignable<std::formatter<T, CharT>>
0567 >
0568 >;
0569
0570 template <typename CharT>
0571 using QFloat16FormatterBaseType =
0572 std::conditional_t<FormatterDoesNotExist<qfloat16::NearestFloat, CharT>,
0573 float,
0574 qfloat16::NearestFloat>;
0575
0576 }
0577
0578 QT_END_NAMESPACE
0579
0580 namespace std {
0581 template <typename CharT>
0582 struct formatter<QT_PREPEND_NAMESPACE(qfloat16), CharT>
0583 : std::formatter<QT_PREPEND_NAMESPACE(QtPrivate::QFloat16FormatterBaseType<CharT>), CharT>
0584 {
0585 template <typename FormatContext>
0586 auto format(QT_PREPEND_NAMESPACE(qfloat16) val, FormatContext &ctx) const
0587 {
0588 using FloatType = QT_PREPEND_NAMESPACE(QtPrivate::QFloat16FormatterBaseType<CharT>);
0589 return std::formatter<FloatType, CharT>::format(FloatType(val), ctx);
0590 }
0591 };
0592 }
0593
0594 #endif
0595
0596 #endif