Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 09:04:33

0001 // Copyright (C) 2021 The Qt Company Ltd.
0002 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0003 
0004 #ifndef QNUMERIC_H
0005 #define QNUMERIC_H
0006 
0007 #if 0
0008 #pragma qt_class(QtNumeric)
0009 #endif
0010 
0011 #include <QtCore/qtconfigmacros.h>
0012 #include <QtCore/qtcoreexports.h>
0013 #include <QtCore/qtypes.h>
0014 
0015 #include <cmath>
0016 #include <limits>
0017 #include <type_traits>
0018 
0019 // min() and max() may be #defined by windows.h if that is included before, but we need them
0020 // for std::numeric_limits below. You should not use the min() and max() macros, so we just #undef.
0021 #ifdef min
0022 #  undef min
0023 #  undef max
0024 #endif
0025 
0026 //
0027 // SIMDe (SIMD Everywhere) can't be used if intrin.h has been included as many definitions
0028 // conflict.   Defining Q_NUMERIC_NO_INTRINSICS allows SIMDe users to use Qt, at the cost of
0029 // falling back to the prior implementations of qMulOverflow and qAddOverflow.
0030 //
0031 #if defined(Q_CC_MSVC) && !defined(Q_NUMERIC_NO_INTRINSICS)
0032 #  include <intrin.h>
0033 #  include <float.h>
0034 #  if defined(Q_PROCESSOR_X86) || defined(Q_PROCESSOR_X86_64)
0035 #    define Q_HAVE_ADDCARRY
0036 #  endif
0037 #  if defined(Q_PROCESSOR_X86_64) || defined(Q_PROCESSOR_ARM_64)
0038 #    define Q_INTRINSIC_MUL_OVERFLOW64
0039 #    define Q_UMULH(v1, v2) __umulh(v1, v2);
0040 #    define Q_SMULH(v1, v2) __mulh(v1, v2);
0041 #    pragma intrinsic(__umulh)
0042 #    pragma intrinsic(__mulh)
0043 #  endif
0044 #endif
0045 
0046 # if defined(Q_OS_INTEGRITY) && defined(Q_PROCESSOR_ARM_64)
0047 #  include <arm64_ghs.h>
0048 #  define Q_INTRINSIC_MUL_OVERFLOW64
0049 #  define Q_UMULH(v1, v2) __MULUH64(v1, v2);
0050 #  define Q_SMULH(v1, v2) __MULSH64(v1, v2);
0051 #endif
0052 
0053 QT_BEGIN_NAMESPACE
0054 
0055 // To match std::is{inf,nan,finite} functions:
0056 template <typename T>
0057 constexpr typename std::enable_if<std::is_integral<T>::value, bool>::type
0058 qIsInf(T) { return false; }
0059 template <typename T>
0060 constexpr typename std::enable_if<std::is_integral<T>::value, bool>::type
0061 qIsNaN(T) { return false; }
0062 template <typename T>
0063 constexpr typename std::enable_if<std::is_integral<T>::value, bool>::type
0064 qIsFinite(T) { return true; }
0065 
0066 // Floating-point types (see qfloat16.h for its overloads).
0067 Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsInf(double d);
0068 Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsNaN(double d);
0069 Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsFinite(double d);
0070 Q_CORE_EXPORT Q_DECL_CONST_FUNCTION int qFpClassify(double val);
0071 Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsInf(float f);
0072 Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsNaN(float f);
0073 Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsFinite(float f);
0074 Q_CORE_EXPORT Q_DECL_CONST_FUNCTION int qFpClassify(float val);
0075 
0076 #if QT_CONFIG(signaling_nan)
0077 Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qSNaN();
0078 #endif
0079 Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qQNaN();
0080 Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qInf();
0081 
0082 Q_CORE_EXPORT quint32 qFloatDistance(float a, float b);
0083 Q_CORE_EXPORT quint64 qFloatDistance(double a, double b);
0084 
0085 #define Q_INFINITY (QT_PREPEND_NAMESPACE(qInf)())
0086 #if QT_CONFIG(signaling_nan)
0087 #  define Q_SNAN (QT_PREPEND_NAMESPACE(qSNaN)())
0088 #endif
0089 #define Q_QNAN (QT_PREPEND_NAMESPACE(qQNaN)())
0090 
0091 // Overflow math.
0092 // This provides efficient implementations for int, unsigned, qsizetype and
0093 // size_t. Implementations for 8- and 16-bit types will work but may not be as
0094 // efficient. Implementations for 64-bit may be missing on 32-bit platforms.
0095 
0096 #if (Q_CC_GNU >= 500 || __has_builtin(__builtin_add_overflow)) \
0097     && !(QT_POINTER_SIZE == 4 && defined(Q_CC_CLANG))
0098 // GCC 5 and Clang 3.8 have builtins to detect overflows
0099 // 32 bit Clang has the builtins but tries to link a library which hasn't
0100 #define Q_INTRINSIC_MUL_OVERFLOW64
0101 
0102 template <typename T> inline
0103 typename std::enable_if_t<std::is_unsigned_v<T> || std::is_signed_v<T>, bool>
0104 qAddOverflow(T v1, T v2, T *r)
0105 { return __builtin_add_overflow(v1, v2, r); }
0106 
0107 template <typename T> inline
0108 typename std::enable_if_t<std::is_unsigned_v<T> || std::is_signed_v<T>, bool>
0109 qSubOverflow(T v1, T v2, T *r)
0110 { return __builtin_sub_overflow(v1, v2, r); }
0111 
0112 template <typename T> inline
0113 typename std::enable_if_t<std::is_unsigned_v<T> || std::is_signed_v<T>, bool>
0114 qMulOverflow(T v1, T v2, T *r)
0115 { return __builtin_mul_overflow(v1, v2, r); }
0116 
0117 #else
0118 // Generic implementations
0119 
0120 template <typename T> inline typename std::enable_if_t<std::is_unsigned_v<T>, bool>
0121 qAddOverflow(T v1, T v2, T *r)
0122 {
0123     // unsigned additions are well-defined
0124     *r = v1 + v2;
0125     return v1 > T(v1 + v2);
0126 }
0127 
0128 template <typename T> inline typename std::enable_if_t<std::is_signed_v<T>, bool>
0129 qAddOverflow(T v1, T v2, T *r)
0130 {
0131     // Here's how we calculate the overflow:
0132     // 1) unsigned addition is well-defined, so we can always execute it
0133     // 2) conversion from unsigned back to signed is implementation-
0134     //    defined and in the implementations we use, it's a no-op.
0135     // 3) signed integer overflow happens if the sign of the two input operands
0136     //    is the same but the sign of the result is different. In other words,
0137     //    the sign of the result must be the same as the sign of either
0138     //    operand.
0139 
0140     using U = typename std::make_unsigned_t<T>;
0141     *r = T(U(v1) + U(v2));
0142 
0143     // If int is two's complement, assume all integer types are too.
0144     if (std::is_same_v<int32_t, int>) {
0145         // Two's complement equivalent (generates slightly shorter code):
0146         //  x ^ y             is negative if x and y have different signs
0147         //  x & y             is negative if x and y are negative
0148         // (x ^ z) & (y ^ z)  is negative if x and z have different signs
0149         //                    AND y and z have different signs
0150         return ((v1 ^ *r) & (v2 ^ *r)) < 0;
0151     }
0152 
0153     bool s1 = (v1 < 0);
0154     bool s2 = (v2 < 0);
0155     bool sr = (*r < 0);
0156     return s1 != sr && s2 != sr;
0157     // also: return s1 == s2 && s1 != sr;
0158 }
0159 
0160 template <typename T> inline typename std::enable_if_t<std::is_unsigned_v<T>, bool>
0161 qSubOverflow(T v1, T v2, T *r)
0162 {
0163     // unsigned subtractions are well-defined
0164     *r = v1 - v2;
0165     return v1 < v2;
0166 }
0167 
0168 template <typename T> inline typename std::enable_if_t<std::is_signed_v<T>, bool>
0169 qSubOverflow(T v1, T v2, T *r)
0170 {
0171     // See above for explanation. This is the same with some signs reversed.
0172     // We can't use qAddOverflow(v1, -v2, r) because it would be UB if
0173     // v2 == std::numeric_limits<T>::min().
0174 
0175     using U = typename std::make_unsigned_t<T>;
0176     *r = T(U(v1) - U(v2));
0177 
0178     if (std::is_same_v<int32_t, int>)
0179         return ((v1 ^ *r) & (~v2 ^ *r)) < 0;
0180 
0181     bool s1 = (v1 < 0);
0182     bool s2 = !(v2 < 0);
0183     bool sr = (*r < 0);
0184     return s1 != sr && s2 != sr;
0185     // also: return s1 == s2 && s1 != sr;
0186 }
0187 
0188 template <typename T> inline
0189 typename std::enable_if_t<std::is_unsigned_v<T> || std::is_signed_v<T>, bool>
0190 qMulOverflow(T v1, T v2, T *r)
0191 {
0192     // use the next biggest type
0193     // Note: for 64-bit systems where __int128 isn't supported, this will cause an error.
0194     using LargerInt = QIntegerForSize<sizeof(T) * 2>;
0195     using Larger = typename std::conditional_t<std::is_signed_v<T>,
0196             typename LargerInt::Signed, typename LargerInt::Unsigned>;
0197     Larger lr = Larger(v1) * Larger(v2);
0198     *r = T(lr);
0199     return lr > (std::numeric_limits<T>::max)() || lr < (std::numeric_limits<T>::min)();
0200 }
0201 
0202 # if defined(Q_INTRINSIC_MUL_OVERFLOW64)
0203 template <> inline bool qMulOverflow(quint64 v1, quint64 v2, quint64 *r)
0204 {
0205     *r = v1 * v2;
0206     return Q_UMULH(v1, v2);
0207 }
0208 template <> inline bool qMulOverflow(qint64 v1, qint64 v2, qint64 *r)
0209 {
0210     // This is slightly more complex than the unsigned case above: the sign bit
0211     // of 'low' must be replicated as the entire 'high', so the only valid
0212     // values for 'high' are 0 and -1. Use unsigned multiply since it's the same
0213     // as signed for the low bits and use a signed right shift to verify that
0214     // 'high' is nothing but sign bits that match the sign of 'low'.
0215 
0216     qint64 high = Q_SMULH(v1, v2);
0217     *r = qint64(quint64(v1) * quint64(v2));
0218     return (*r >> 63) != high;
0219 }
0220 
0221 #   if defined(Q_OS_INTEGRITY) && defined(Q_PROCESSOR_ARM_64)
0222 template <> inline bool qMulOverflow(uint64_t v1, uint64_t v2, uint64_t *r)
0223 {
0224     return qMulOverflow<quint64>(v1,v2,reinterpret_cast<quint64*>(r));
0225 }
0226 
0227 template <> inline bool qMulOverflow(int64_t v1, int64_t v2, int64_t *r)
0228 {
0229     return qMulOverflow<qint64>(v1,v2,reinterpret_cast<qint64*>(r));
0230 }
0231 #    endif // OS_INTEGRITY ARM64
0232 #  endif // Q_INTRINSIC_MUL_OVERFLOW64
0233 
0234 #  if defined(Q_HAVE_ADDCARRY) && defined(Q_PROCESSOR_X86)
0235 // We can use intrinsics for the unsigned operations with MSVC
0236 template <> inline bool qAddOverflow(unsigned v1, unsigned v2, unsigned *r)
0237 { return _addcarry_u32(0, v1, v2, r); }
0238 
0239 // 32-bit qMulOverflow is fine with the generic code above
0240 
0241 template <> inline bool qAddOverflow(quint64 v1, quint64 v2, quint64 *r)
0242 {
0243 #    if defined(Q_PROCESSOR_X86_64)
0244     return _addcarry_u64(0, v1, v2, reinterpret_cast<unsigned __int64 *>(r));
0245 #    else
0246     uint low, high;
0247     uchar carry = _addcarry_u32(0, unsigned(v1), unsigned(v2), &low);
0248     carry = _addcarry_u32(carry, v1 >> 32, v2 >> 32, &high);
0249     *r = (quint64(high) << 32) | low;
0250     return carry;
0251 #    endif // !x86-64
0252 }
0253 #  endif // HAVE ADDCARRY
0254 #undef Q_HAVE_ADDCARRY
0255 #endif // !GCC
0256 
0257 // Implementations for addition, subtraction or multiplication by a
0258 // compile-time constant. For addition and subtraction, we simply call the code
0259 // that detects overflow at runtime. For multiplication, we compare to the
0260 // maximum possible values before multiplying to ensure no overflow happens.
0261 
0262 template <typename T, T V2> bool qAddOverflow(T v1, std::integral_constant<T, V2>, T *r)
0263 {
0264     return qAddOverflow(v1, V2, r);
0265 }
0266 
0267 template <auto V2, typename T> bool qAddOverflow(T v1, T *r)
0268 {
0269     return qAddOverflow(v1, std::integral_constant<T, V2>{}, r);
0270 }
0271 
0272 template <typename T, T V2> bool qSubOverflow(T v1, std::integral_constant<T, V2>, T *r)
0273 {
0274     return qSubOverflow(v1, V2, r);
0275 }
0276 
0277 template <auto V2, typename T> bool qSubOverflow(T v1, T *r)
0278 {
0279     return qSubOverflow(v1, std::integral_constant<T, V2>{}, r);
0280 }
0281 
0282 template <typename T, T V2> bool qMulOverflow(T v1, std::integral_constant<T, V2>, T *r)
0283 {
0284     // Runtime detection for anything smaller than or equal to a register
0285     // width, as most architectures' multiplication instructions actually
0286     // produce a result twice as wide as the input registers, allowing us to
0287     // efficiently detect the overflow.
0288     if constexpr (sizeof(T) <= sizeof(qregisteruint)) {
0289         return qMulOverflow(v1, V2, r);
0290 
0291 #ifdef Q_INTRINSIC_MUL_OVERFLOW64
0292     } else if constexpr (sizeof(T) <= sizeof(quint64)) {
0293         // If we have intrinsics detecting overflow of 64-bit multiplications,
0294         // then detect overflows through them up to 64 bits.
0295         return qMulOverflow(v1, V2, r);
0296 #endif
0297 
0298     } else if constexpr (V2 == 0 || V2 == 1) {
0299         // trivial cases (and simplify logic below due to division by zero)
0300         *r = v1 * V2;
0301         return false;
0302     } else if constexpr (V2 == -1) {
0303         // multiplication by -1 is valid *except* for signed minimum values
0304         // (necessary to avoid diving min() by -1, which is an overflow)
0305         if (v1 < 0 && v1 == (std::numeric_limits<T>::min)())
0306             return true;
0307         *r = -v1;
0308         return false;
0309     } else {
0310         // For 64-bit multiplications on 32-bit platforms, let's instead compare v1
0311         // against the bounds that would overflow.
0312         constexpr T Highest = (std::numeric_limits<T>::max)() / V2;
0313         constexpr T Lowest = (std::numeric_limits<T>::min)() / V2;
0314         if constexpr (Highest > Lowest) {
0315             if (v1 > Highest || v1 < Lowest)
0316                 return true;
0317         } else {
0318             // this can only happen if V2 < 0
0319             static_assert(V2 < 0);
0320             if (v1 > Lowest || v1 < Highest)
0321                 return true;
0322         }
0323 
0324         *r = v1 * V2;
0325         return false;
0326     }
0327 }
0328 
0329 template <auto V2, typename T> bool qMulOverflow(T v1, T *r)
0330 {
0331     if constexpr (V2 == 2)
0332         return qAddOverflow(v1, v1, r);
0333     return qMulOverflow(v1, std::integral_constant<T, V2>{}, r);
0334 }
0335 
0336 template <typename T>
0337 constexpr inline T qAbs(const T &t) { return t >= 0 ? t : -t; }
0338 
0339 namespace QtPrivate {
0340 template <typename T,
0341           typename std::enable_if_t<std::is_integral_v<T>, bool> = true>
0342 constexpr inline auto qUnsignedAbs(T t)
0343 {
0344     using U = std::make_unsigned_t<T>;
0345     return (t >= 0) ? U(t) : U(~U(t) + U(1));
0346 }
0347 } // namespace QtPrivate
0348 
0349 // gcc < 10 doesn't have __has_builtin
0350 #if defined(Q_PROCESSOR_ARM_64) && (__has_builtin(__builtin_round) || defined(Q_CC_GNU)) && !defined(Q_CC_CLANG)
0351 // ARM64 has a single instruction that can do C++ rounding with conversion to integer.
0352 // Note current clang versions have non-constexpr __builtin_round, ### allow clang this path when they fix it.
0353 constexpr inline int qRound(double d)
0354 { return int(__builtin_round(d)); }
0355 constexpr inline int qRound(float f)
0356 { return int(__builtin_roundf(f)); }
0357 constexpr inline qint64 qRound64(double d)
0358 { return qint64(__builtin_round(d)); }
0359 constexpr inline qint64 qRound64(float f)
0360 { return qint64(__builtin_roundf(f)); }
0361 #elif defined(__SSE2__) && (__has_builtin(__builtin_copysign) || defined(Q_CC_GNU))
0362 // SSE has binary operations directly on floating point making copysign fast
0363 constexpr inline int qRound(double d)
0364 { return int(d + __builtin_copysign(0.5, d)); }
0365 constexpr inline int qRound(float f)
0366 { return int(f + __builtin_copysignf(0.5f, f)); }
0367 constexpr inline qint64 qRound64(double d)
0368 { return qint64(d + __builtin_copysign(0.5, d)); }
0369 constexpr inline qint64 qRound64(float f)
0370 { return qint64(f + __builtin_copysignf(0.5f, f)); }
0371 #else
0372 constexpr inline int qRound(double d)
0373 { return d >= 0.0 ? int(d + 0.5) : int(d - 0.5); }
0374 constexpr inline int qRound(float d)
0375 { return d >= 0.0f ? int(d + 0.5f) : int(d - 0.5f); }
0376 
0377 constexpr inline qint64 qRound64(double d)
0378 { return d >= 0.0 ? qint64(d + 0.5) : qint64(d - 0.5); }
0379 constexpr inline qint64 qRound64(float d)
0380 { return d >= 0.0f ? qint64(d + 0.5f) : qint64(d - 0.5f); }
0381 #endif
0382 
0383 namespace QtPrivate {
0384 template <typename T>
0385 constexpr inline const T &min(const T &a, const T &b) { return (a < b) ? a : b; }
0386 }
0387 
0388 [[nodiscard]] constexpr bool qFuzzyCompare(double p1, double p2) noexcept
0389 {
0390     return (qAbs(p1 - p2) * 1000000000000. <= QtPrivate::min(qAbs(p1), qAbs(p2)));
0391 }
0392 
0393 [[nodiscard]] constexpr bool qFuzzyCompare(float p1, float p2) noexcept
0394 {
0395     return (qAbs(p1 - p2) * 100000.f <= QtPrivate::min(qAbs(p1), qAbs(p2)));
0396 }
0397 
0398 [[nodiscard]] constexpr bool qFuzzyIsNull(double d) noexcept
0399 {
0400     return qAbs(d) <= 0.000000000001;
0401 }
0402 
0403 [[nodiscard]] constexpr bool qFuzzyIsNull(float f) noexcept
0404 {
0405     return qAbs(f) <= 0.00001f;
0406 }
0407 
0408 QT_WARNING_PUSH
0409 QT_WARNING_DISABLE_FLOAT_COMPARE
0410 
0411 [[nodiscard]] constexpr bool qIsNull(double d) noexcept
0412 {
0413     return d == 0.0;
0414 }
0415 
0416 [[nodiscard]] constexpr bool qIsNull(float f) noexcept
0417 {
0418     return f == 0.0f;
0419 }
0420 
0421 QT_WARNING_POP
0422 
0423 inline int qIntCast(double f) { return int(f); }
0424 inline int qIntCast(float f) { return int(f); }
0425 
0426 QT_END_NAMESPACE
0427 
0428 #endif // QNUMERIC_H