diff options
author | Fabian Kosmale <fabian.kosmale@qt.io> | 2020-03-09 11:11:32 +0100 |
---|---|---|
committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2020-03-16 08:21:49 +0100 |
commit | e464e1eb8eb63c631fb0916c3ea4540a88d8aad3 (patch) | |
tree | e8aec126d84650377dce21dbc2ad76b8b5e0bff6 /src/corelib/tools/qalgorithms.h | |
parent | cb8eb0f86c1bbdfbd6cfa789e7596a0e05d7fe66 (diff) |
Introduce always constexpr variants of qCountTrailingZeroBits
qt_builtin_ctz is unfortunately not constexpr on MSVC, so the whole
function cannot be used in constexpr contexts, unless v is exactly 0. As we
don't have std::is_costant_evaluated until C++20, we need to introduce a new
helper function, which always works in constexpr contexts.
Change-Id: I36290acb61e430d6bdb3da112a9b2263be4b9fbf
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/corelib/tools/qalgorithms.h')
-rw-r--r-- | src/corelib/tools/qalgorithms.h | 65 |
1 files changed, 46 insertions, 19 deletions
diff --git a/src/corelib/tools/qalgorithms.h b/src/corelib/tools/qalgorithms.h index aa79e0d4a9..838e8472d8 100644 --- a/src/corelib/tools/qalgorithms.h +++ b/src/corelib/tools/qalgorithms.h @@ -744,11 +744,9 @@ Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR inline uint qPopulationCount(long un #endif #undef QT_POPCOUNT_CONSTEXPR -Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint32 v) noexcept +namespace QtPrivate { +constexpr inline uint qConstexprCountTrailingZeroBits(quint32 v) noexcept { -#if defined(QT_HAS_BUILTIN_CTZ) - return v ? QAlgorithmsPrivate::qt_builtin_ctz(v) : 32U; -#else // see http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightParallel unsigned int c = 32; // c will be the number of zero bits on the right v &= -signed(v); @@ -759,14 +757,17 @@ Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint32 v) noexcept if (v & 0x33333333) c -= 2; if (v & 0x55555555) c -= 1; return c; -#endif } -Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint8 v) noexcept +constexpr inline uint qConstexprCountTrailingZeroBits(quint64 v) noexcept +{ + quint32 x = static_cast<quint32>(v); + return x ? qConstexprCountTrailingZeroBits(x) + : 32 + qConstexprCountTrailingZeroBits(static_cast<quint32>(v >> 32)); +} + +constexpr inline uint qConstexprCountTrailingZeroBits(quint8 v) noexcept { -#if defined(QT_HAS_BUILTIN_CTZ) - return v ? QAlgorithmsPrivate::qt_builtin_ctz(v) : 8U; -#else unsigned int c = 8; // c will be the number of zero bits on the right v &= -signed(v); if (v) c--; @@ -774,14 +775,10 @@ Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint8 v) noexcept if (v & 0x00000033) c -= 2; if (v & 0x00000055) c -= 1; return c; -#endif } -Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint16 v) noexcept +constexpr inline uint qConstexprCountTrailingZeroBits(quint16 v) noexcept { -#if defined(QT_HAS_BUILTIN_CTZS) - return v ? QAlgorithmsPrivate::qt_builtin_ctzs(v) : 16U; -#else unsigned int c = 16; // c will be the number of zero bits on the right v &= -signed(v); if (v) c--; @@ -790,21 +787,51 @@ Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint16 v) noexcept if (v & 0x00003333) c -= 2; if (v & 0x00005555) c -= 1; return c; +} + +constexpr inline uint qConstexprCountTrailingZeroBits(unsigned long v) noexcept +{ + return qConstexprCountTrailingZeroBits(QIntegerForSizeof<long>::Unsigned(v)); +} +} + +constexpr inline uint qCountTrailingZeroBits(quint32 v) noexcept +{ +#if defined(QT_HAS_BUILTIN_CTZ) + return v ? QAlgorithmsPrivate::qt_builtin_ctz(v) : 32U; +#else + return QtPrivate::qConstexprCountTrailingZeroBits(v); +#endif +} + +constexpr inline uint qCountTrailingZeroBits(quint8 v) noexcept +{ +#if defined(QT_HAS_BUILTIN_CTZ) + return v ? QAlgorithmsPrivate::qt_builtin_ctz(v) : 8U; +#else + return QtPrivate::qConstexprCountTrailingZeroBits(v); +#endif +} + +constexpr inline uint qCountTrailingZeroBits(quint16 v) noexcept +{ +#if defined(QT_HAS_BUILTIN_CTZS) + return v ? QAlgorithmsPrivate::qt_builtin_ctzs(v) : 16U; +#else + return QtPrivate::qConstexprCountTrailingZeroBits(v); #endif } -Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(quint64 v) noexcept +constexpr inline uint qCountTrailingZeroBits(quint64 v) noexcept { #if defined(QT_HAS_BUILTIN_CTZLL) return v ? QAlgorithmsPrivate::qt_builtin_ctzll(v) : 64; #else - quint32 x = static_cast<quint32>(v); - return x ? qCountTrailingZeroBits(x) - : 32 + qCountTrailingZeroBits(static_cast<quint32>(v >> 32)); + return QtPrivate::qConstexprCountTrailingZeroBits(v); #endif } -Q_DECL_RELAXED_CONSTEXPR inline uint qCountTrailingZeroBits(unsigned long v) noexcept +constexpr inline uint qCountTrailingZeroBits(unsigned long v) noexcept { return qCountTrailingZeroBits(QIntegerForSizeof<long>::Unsigned(v)); } |