diff --git a/src/corelib/kernel/qmath.h b/src/corelib/kernel/qmath.h index 42cbe9bc606..d5ba97c0fd5 100644 --- a/src/corelib/kernel/qmath.h +++ b/src/corelib/kernel/qmath.h @@ -288,67 +288,16 @@ constexpr inline long double qRadiansToDegrees(long double radians) // questionable that someone is manipulating quantities in radians // using integral datatypes... -namespace QtPrivate { -constexpr inline quint32 qConstexprNextPowerOfTwo(quint32 v) -{ - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - ++v; - return v; -} - -constexpr inline quint64 qConstexprNextPowerOfTwo(quint64 v) -{ - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - v |= v >> 32; - ++v; - return v; -} - -constexpr inline quint32 qConstexprNextPowerOfTwo(qint32 v) -{ - return qConstexprNextPowerOfTwo(quint32(v)); -} - -constexpr inline quint64 qConstexprNextPowerOfTwo(qint64 v) -{ - return qConstexprNextPowerOfTwo(quint64(v)); -} -} // namespace QtPrivate - constexpr inline quint32 qNextPowerOfTwo(quint32 v) { Q_ASSERT(static_cast(v) >= 0); // There is a next power of two -#if defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L - return std::bit_ceil(v + 1); -#elif defined(QT_HAS_BUILTIN_CLZ) - if (v == 0) - return 1; - return 2U << (31 ^ QAlgorithmsPrivate::qt_builtin_clz(v)); -#else - return QtPrivate::qConstexprNextPowerOfTwo(v); -#endif + return q20::bit_ceil(v + 1); } constexpr inline quint64 qNextPowerOfTwo(quint64 v) { Q_ASSERT(static_cast(v) >= 0); // There is a next power of two -#if defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L - return std::bit_ceil(v + 1); -#elif defined(QT_HAS_BUILTIN_CLZLL) - if (v == 0) - return 1; - return Q_UINT64_C(2) << (63 ^ QAlgorithmsPrivate::qt_builtin_clzll(v)); -#else - return QtPrivate::qConstexprNextPowerOfTwo(v); -#endif + return q20::bit_ceil(v + 1); } constexpr inline quint32 qNextPowerOfTwo(qint32 v) diff --git a/src/corelib/tools/qtaggedpointer.h b/src/corelib/tools/qtaggedpointer.h index e446fba1206..b518121017b 100644 --- a/src/corelib/tools/qtaggedpointer.h +++ b/src/corelib/tools/qtaggedpointer.h @@ -25,7 +25,7 @@ namespace QtPrivate { static_assert(tagBits > 0, "Alignment of template parameter does not allow any tags"); - static constexpr size_t tagSize = QtPrivate::qConstexprNextPowerOfTwo(nextByteSize(tagBits)); + static constexpr size_t tagSize = qNextPowerOfTwo(nextByteSize(tagBits)); static_assert(tagSize < sizeof(quintptr), "Alignment of template parameter allows tags masking away pointer"); diff --git a/tests/auto/corelib/kernel/qmath/tst_qmath.cpp b/tests/auto/corelib/kernel/qmath/tst_qmath.cpp index 1961b71d83e..438c77781b8 100644 --- a/tests/auto/corelib/kernel/qmath/tst_qmath.cpp +++ b/tests/auto/corelib/kernel/qmath/tst_qmath.cpp @@ -6,6 +6,8 @@ #include #include +#include + class tst_QMath : public QObject { Q_OBJECT @@ -294,6 +296,12 @@ void tst_QMath::qNextPowerOfTwo32U_data() void tst_QMath::qNextPowerOfTwo32U() { + // confirm constexprness + static_assert(q20::bit_ceil(0U) == 1); + static_assert(q20::bit_ceil(1U) == 1); + static_assert(q20::bit_ceil(2U) == 2); + static_assert(q20::bit_ceil(3U) == 4); + static_assert(q20::bit_ceil(0x7fff'ffffU) == 0x8000'0000U); QFETCH(quint32, input); QFETCH(quint32, output); @@ -343,6 +351,13 @@ void tst_QMath::qNextPowerOfTwo64U_data() void tst_QMath::qNextPowerOfTwo64U() { + static_assert(q20::bit_ceil(Q_UINT64_C(0)) == 1); + static_assert(q20::bit_ceil(Q_UINT64_C(1)) == 1); + static_assert(q20::bit_ceil(Q_UINT64_C(2)) == 2); + static_assert(q20::bit_ceil(Q_UINT64_C(3)) == 4); + static_assert(q20::bit_ceil(quint64(~0U)) == Q_UINT64_C(0x1'0000'0000)); + static_assert(q20::bit_ceil(Q_UINT64_C(0x7FFFFFFFFFFFFFFF)) + == Q_UINT64_C(0x8000000000000000)); QFETCH(quint64, input); QFETCH(quint64, output);