diff --git a/number_theory/math_functions.hpp b/number_theory/math_functions.hpp index 47693f1..5c38d3a 100644 --- a/number_theory/math_functions.hpp +++ b/number_theory/math_functions.hpp @@ -1145,6 +1145,27 @@ ATTRIBUTE_CONST constexpr uint64_t nearest_pow2_ge(uint64_t n) noexcept { return uint64_t(1ull) << (k - uint32_t(countl_zero(n | 1)) - ((n & (n - 1)) == 0)); } +/// @brief If @a n != 0, return number that is power of 2 and +/// whose only bit is the lowest bit set in the @a n +/// Otherwise, return 0 +/// @tparam TInt +/// @param[in] n +/// @return +template +ATTRIBUTE_CONST constexpr TInt least_bit_set(TInt n) noexcept { + namespace helper_ns = +#ifdef INTEGERS_128_BIT_HPP + type_traits_helper_int128_t; +#else + std; +#endif + static_assert(helper_ns::is_integral_v, "integral type expected"); + using TUInt = helper_ns::make_unsigned_t; + using TUIntAtLeastUInt = std::common_type_t; + auto unsigned_n = static_cast(static_cast(n)); + return static_cast(unsigned_n & -unsigned_n); +} + ATTRIBUTE_CONST constexpr uint32_t base_2_len(uint32_t n) noexcept { // " | 1" operation does not affect answer for all // numbers except n = 0. For n = 0 answer is 1. diff --git a/number_theory/test_math_functions.cpp b/number_theory/test_math_functions.cpp index 8f09aa6..197caba 100644 --- a/number_theory/test_math_functions.cpp +++ b/number_theory/test_math_functions.cpp @@ -707,6 +707,56 @@ static_assert(nearest_pow2_ge(uint64_t(1) << 61) == uint64_t(1) << 61, "nearest_ static_assert(nearest_pow2_ge(uint64_t(1) << 62) == uint64_t(1) << 62, "nearest_pow2_ge"); static_assert(nearest_pow2_ge(uint64_t(1) << 63) == uint64_t(1) << 63, "nearest_pow2_ge"); +static_assert(least_bit_set(0b0) == 0b0, "least_bit_set"); +static_assert(least_bit_set(0b1) == 0b1, "least_bit_set"); +static_assert(least_bit_set(0b10) == 0b10, "least_bit_set"); +static_assert(least_bit_set(0b100) == 0b100, "least_bit_set"); +static_assert(least_bit_set(0b1000) == 0b1000, "least_bit_set"); +static_assert(least_bit_set(0b10000) == 0b10000, "least_bit_set"); +static_assert(least_bit_set(0b100000) == 0b100000, "least_bit_set"); +static_assert(least_bit_set(0b1000000) == 0b1000000, "least_bit_set"); +static_assert(least_bit_set(0b10000000) == 0b10000000, "least_bit_set"); +static_assert(least_bit_set(0b0u) == 0b0u, "least_bit_set"); +static_assert(least_bit_set(0b1u) == 0b1u, "least_bit_set"); +static_assert(least_bit_set(0b10u) == 0b10u, "least_bit_set"); +static_assert(least_bit_set(0b100u) == 0b100u, "least_bit_set"); +static_assert(least_bit_set(0b1000u) == 0b1000u, "least_bit_set"); +static_assert(least_bit_set(0b10000u) == 0b10000u, "least_bit_set"); +static_assert(least_bit_set(0b100000u) == 0b100000u, "least_bit_set"); +static_assert(least_bit_set(0b1000000u) == 0b1000000u, "least_bit_set"); +static_assert(least_bit_set(0b10000000u) == 0b10000000u, "least_bit_set"); +static_assert(least_bit_set(int8_t(0b0)) == int8_t(0b0), "least_bit_set"); +static_assert(least_bit_set(int8_t(0b1)) == int8_t(0b1), "least_bit_set"); +static_assert(least_bit_set(int8_t(0b10)) == int8_t(0b10), "least_bit_set"); +static_assert(least_bit_set(int8_t(0b100)) == int8_t(0b100), "least_bit_set"); +static_assert(least_bit_set(int8_t(0b1000)) == int8_t(0b1000), "least_bit_set"); +static_assert(least_bit_set(int8_t(0b10000)) == int8_t(0b10000), "least_bit_set"); +static_assert(least_bit_set(int8_t(0b100000)) == int8_t(0b100000), "least_bit_set"); +static_assert(least_bit_set(int8_t(0b1000000)) == int8_t(0b1000000), "least_bit_set"); +static_assert(least_bit_set(int8_t(0b10000000)) == int8_t(0b10000000), "least_bit_set"); +static_assert(least_bit_set(uint8_t(0b0)) == uint8_t(0b0), "least_bit_set"); +static_assert(least_bit_set(uint8_t(0b1)) == uint8_t(0b1), "least_bit_set"); +static_assert(least_bit_set(uint8_t(0b10)) == uint8_t(0b10), "least_bit_set"); +static_assert(least_bit_set(uint8_t(0b100)) == uint8_t(0b100), "least_bit_set"); +static_assert(least_bit_set(uint8_t(0b1000)) == uint8_t(0b1000), "least_bit_set"); +static_assert(least_bit_set(uint8_t(0b10000)) == uint8_t(0b10000), "least_bit_set"); +static_assert(least_bit_set(uint8_t(0b100000)) == uint8_t(0b100000), "least_bit_set"); +static_assert(least_bit_set(uint8_t(0b1000000)) == uint8_t(0b1000000), "least_bit_set"); +static_assert(least_bit_set(uint8_t(0b10000000)) == uint8_t(0b10000000), "least_bit_set"); +static_assert(least_bit_set(0b100000000) == 0b100000000, "least_bit_set"); +static_assert(least_bit_set(0b1000000000) == 0b1000000000, "least_bit_set"); +static_assert(least_bit_set(0b10000000000) == 0b10000000000, "least_bit_set"); +static_assert(least_bit_set(0b100000000u) == 0b100000000u, "least_bit_set"); +static_assert(least_bit_set(0b1000000000u) == 0b1000000000u, "least_bit_set"); +static_assert(least_bit_set(0b10000000000u) == 0b10000000000u, "least_bit_set"); +static_assert(least_bit_set(0b1000000000000000000000000000000000000000000000000000000000000000ull) == 0b1000000000000000000000000000000000000000000000000000000000000000ull, "least_bit_set"); +static_assert(least_bit_set(0b110101010101010101011001) == 0b1, "least_bit_set"); +static_assert(least_bit_set(0b1010101011001101011100010100000ll) == 0b100000ll, "least_bit_set"); +static_assert(least_bit_set(0b1010111001010101101010110101001101011100110011000ll) == 0b1000ll, "least_bit_set"); +static_assert(least_bit_set(0b110101010101010101011001u) == 0b1u, "least_bit_set"); +static_assert(least_bit_set(0b1010101011001101011100010100000llu) == 0b100000llu, "least_bit_set"); +static_assert(least_bit_set(0b1010111001010101101010110101001101011100110011000llu) == 0b1000llu, "least_bit_set"); + static_assert(log2_floor(uint32_t(0)) == uint32_t(-1), "log2_floor"); static_assert(log2_floor(uint32_t(1)) == 0, "log2_floor"); static_assert(log2_floor(uint32_t(2)) == 1, "log2_floor");