9#include <QtCore/q20type_traits.h>
11#if defined(__cpp_lib_bitops) || defined(__cpp_lib_int_pow2)
14# include <QtCore/qtypes.h>
20# include <QtCore/qsimd.h>
44#if defined(__cpp_lib_bitops)
54#if defined(Q_CC_MSVC) && defined(Q_PROCESSOR_X86) && defined(__POPCNT__)
56# ifdef Q_PROCESSOR_X86_64
57 if constexpr (
sizeof(T) ==
sizeof(quint64))
58 return int(__popcnt64(v));
60 if constexpr (
sizeof(T) ==
sizeof(quint64))
61 return int(__popcnt(quint32(v)) + __popcnt(quint32(v >> 32)));
62 if constexpr (
sizeof(T) ==
sizeof(quint32))
63 return int(__popcnt(v));
64 return int(__popcnt16(v));
72#if defined(Q_CC_MSVC) && defined(Q_PROCESSOR_X86) && defined(__LZCNT__)
74# if defined(Q_PROCESSOR_X86_64)
75 if constexpr (
sizeof(T) ==
sizeof(quint64))
76 return int(__lzcnt64(v));
78 if constexpr (
sizeof(T) ==
sizeof(quint32))
79 return int(__lzcnt(v));
80 if constexpr (
sizeof(T) ==
sizeof(quint16))
81 return int(__lzcnt16(v));
82 if constexpr (
sizeof(T) ==
sizeof(quint8))
83 return int(__lzcnt(v)) - 24;
85#if defined(Q_CC_MSVC) && defined(Q_PROCESSOR_X86)
86 constexpr int Digits = std::numeric_limits<T>::digits;
89 if constexpr (
sizeof(T) ==
sizeof(quint64)) {
90# ifdef Q_PROCESSOR_X86_64
91 if (_BitScanReverse64(&result, v) == 0)
94 if (quint32 h = quint32(v >> 32))
95 return hw_countl_zero(h);
96 return hw_countl_zero(quint32(v)) + 32;
99 if (_BitScanReverse(&result, v) == 0)
106 result ^=
sizeof(T) * 8 - 1;
115#if defined(Q_CC_MSVC) && defined(Q_PROCESSOR_X86) && defined(__BMI__)
117# if defined(Q_PROCESSOR_X86_64)
118 if constexpr (
sizeof(T) ==
sizeof(quint64))
119 return int(_tzcnt_u64(v));
121 if constexpr (
sizeof(T) ==
sizeof(quint32))
122 return int(_tzcnt_u32(v));
125#if defined(Q_CC_MSVC) && defined(Q_PROCESSOR_X86)
126 constexpr int Digits = std::numeric_limits<T>::digits;
127 unsigned long result;
128 if constexpr (
sizeof(T) <=
sizeof(quint32))
129 return _BitScanForward(&result, v) ?
int(result) : Digits;
130# ifdef Q_PROCESSOR_X86_64
131 return _BitScanForward64(&result, v) ?
int(result) : Digits;
143 return __builtin_popcountg(v);
146 if constexpr (
sizeof(T) >
sizeof(quint64)) {
147 static_assert(
sizeof(T) == 16,
"Unsupported integer size");
148 return popcount(quint64(v)) + popcount(quint64(v >> 64));
154 if constexpr (
sizeof(T) >
sizeof(quint32))
155 return __builtin_popcountll(v);
156 return __builtin_popcount(v);
159# ifdef QT_SUPPORTS_IS_CONSTANT_EVALUATED
161 if (!is_constant_evaluated()) {
162 if constexpr (std::is_integral_v<
decltype(detail::hw_popcount(v))>)
163 return detail::hw_popcount(v);
167 constexpr int Digits =
std::numeric_limits<T>::digits;
168 int r = (((v ) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
169 if constexpr (Digits > 12)
170 r += (((v >> 12) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
171 if constexpr (Digits > 24)
172 r += (((v >> 24) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
173 if constexpr (Digits > 36) {
174 r += (((v >> 36) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f +
175 (((v >> 48) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f +
176 (((v >> 60) & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f;
187 return __builtin_clzg(v,
std::numeric_limits<T>::digits);
190 if constexpr (
sizeof(T) >
sizeof(quint64)) {
191 static_assert(
sizeof(T) == 16,
"Unsupported integer size");
192 if (quint64 h = quint64(v >> 64))
193 return countl_zero(h);
194 return countl_zero(quint64(v)) + 64;
201 return std::numeric_limits<T>::digits;
202 if constexpr (
sizeof(T) ==
sizeof(quint64))
203 return __builtin_clzll(v);
205 if constexpr (
sizeof(T) ==
sizeof(quint16))
206 return __builtin_clzs(v);
208 return __builtin_clz(v) - (32 -
std::numeric_limits<T>::digits);
211#ifdef QT_SUPPORTS_IS_CONSTANT_EVALUATED
213 if (!is_constant_evaluated()) {
214 if constexpr (std::is_integral_v<
decltype(detail::hw_countl_zero(v))>)
215 return detail::hw_countl_zero(v);
223 if constexpr (
sizeof(T) >
sizeof(quint8))
225 if constexpr (
sizeof(T) >
sizeof(quint16))
227 if constexpr (
sizeof(T) >
sizeof(quint32))
229 return popcount(T(~v));
238 return __builtin_ctzg(v,
std::numeric_limits<T>::digits);
241 if constexpr (
sizeof(T) >
sizeof(quint64)) {
242 static_assert(
sizeof(T) == 16,
"Unsupported integer size");
243 quint64 l = quint64(v);
244 return l ? countr_zero(l) : 64 + countr_zero(quint64(v >> 64));
251 return std::numeric_limits<T>::digits;
252 if constexpr (
sizeof(T) ==
sizeof(quint64))
253 return __builtin_ctzll(v);
255 if constexpr (
sizeof(T) ==
sizeof(quint16))
256 return __builtin_ctzs(v);
258 return __builtin_ctz(v);
261#ifdef QT_SUPPORTS_IS_CONSTANT_EVALUATED
263 if (!is_constant_evaluated()) {
264 if constexpr (std::is_integral_v<
decltype(detail::hw_countr_zero(v))>)
265 return detail::hw_countr_zero(v);
269 if constexpr (
sizeof(T) >
sizeof(quint32)) {
270 quint32 l = quint32(v);
271 return l ? countr_zero(l) : 32 + countr_zero(quint32(v >> 32));
275 int c =
std::numeric_limits<T>::digits;
277QT_WARNING_DISABLE_MSVC(4146)
281 if constexpr (
sizeof(T) ==
sizeof(quint32)) {
282 if (v & 0x0000FFFF) c -= 16;
283 if (v & 0x00FF00FF) c -= 8;
284 if (v & 0x0F0F0F0F) c -= 4;
285 if (v & 0x33333333) c -= 2;
286 if (v & 0x55555555) c -= 1;
287 }
else if constexpr (
sizeof(T) ==
sizeof(quint16)) {
288 if (v & 0x000000FF) c -= 8;
289 if (v & 0x00000F0F) c -= 4;
290 if (v & 0x00003333) c -= 2;
291 if (v & 0x00005555) c -= 1;
293 if (v & 0x0000000F) c -= 4;
294 if (v & 0x00000033) c -= 2;
295 if (v & 0x00000055) c -= 1;
303 constexpr int Digits =
std::numeric_limits<T>::digits;
304 unsigned n =
unsigned(s) % Digits;
305 return (v << n) | (v >> (Digits - n));
311 constexpr int Digits =
std::numeric_limits<T>::digits;
312 unsigned n =
unsigned(s) % Digits;
313 return (v >> n) | (v << (Digits - n));
317#if defined(__cpp_lib_int_pow2)
326 constexpr int Digits =
std::numeric_limits<T>::digits;
329 return T(1) << (Digits - countl_zero(T(v - 1)));
335 return std::numeric_limits<T>::digits - countl_zero(v);
341 return v ? T(1) << (bit_width(v) - 1) : 0;
\keyword 16-bit Floating Point Support\inmodule QtCore \inheaderfile QFloat16
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 Result qCheckedFPConversionToInteger(FP value)
auto hw_popcount(T v) noexcept
auto hw_countl_zero(T v) noexcept
auto hw_countr_zero(T v) noexcept
constexpr std::enable_if_t< std::is_unsigned_v< T >, int > popcount(T v) noexcept
constexpr std::enable_if_t< std::is_unsigned_v< T >, T > bit_floor(T v) noexcept
constexpr std::enable_if_t< std::is_unsigned_v< T >, T > rotl(T v, int s) noexcept
constexpr std::enable_if_t< std::is_unsigned_v< T >, int > countl_zero(T v) noexcept
constexpr std::enable_if_t< std::is_unsigned_v< T >, T > bit_width(T v) noexcept
constexpr std::enable_if_t< std::is_unsigned_v< T >, T > bit_ceil(T v) noexcept
constexpr std::enable_if_t< std::is_unsigned_v< T >, T > rotr(T v, int s) noexcept
constexpr std::enable_if_t< std::is_unsigned_v< T >, int > countr_zero(T v) noexcept
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)
QT_WARNING_POP int qIntCast(double f)
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)