/* * Copyright (c) 2022, Leon Albrecht * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include namespace AK { template constexpr T exp2(T exponent) { return 1u << exponent; } template constexpr T log2(T x) { return x ? (8 * sizeof(T) - 1) - count_leading_zeroes(static_cast>(x)) : 0; } template constexpr T ceil_log2(T x) { if (!x) return 0; T log = AK::log2(x); log += (x & ((((T)1) << (log - 1)) - 1)) != 0; return log; } template constexpr I pow(I base, I exponent) { // https://en.wikipedia.org/wiki/Exponentiation_by_squaring if (exponent < 0) return 0; if (exponent == 0) return 1; I res = 1; while (exponent > 0) { if (exponent & 1) res *= base; base *= base; exponent /= 2u; } return res; } template constexpr bool is_power_of(U x) { if constexpr (base == 2) return is_power_of_two(x); // FIXME: I am naive! A log2-based approach (pow(base, (log2(x) / log2(base))) == x) does not work due to rounding errors. for (U exponent = 0; exponent <= log2(x) / log2(base) + 1; ++exponent) { if (pow(base, exponent) == x) return true; } return false; } }