qNextPowerOfTwo: rewrite using the newly added q20::bit_ceil()

Change-Id: I6f6d8110327d1ba7d519fffd0aa2e18d87477e56
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
This commit is contained in:
Thiago Macieira 2025-08-20 20:34:47 -07:00
parent b027f12392
commit 4d1004fe1e
3 changed files with 18 additions and 54 deletions

View File

@ -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<qint32>(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<qint64>(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)

View File

@ -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");

View File

@ -6,6 +6,8 @@
#include <qmath.h>
#include <qfloat16.h>
#include <q20bit.h>
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);