Skip to content

Commit

Permalink
add least_bit_set() to the math_functions.hpp
Browse files Browse the repository at this point in the history
  • Loading branch information
i80287 committed Jul 20, 2024
1 parent cf8ea89 commit ba94213
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 0 deletions.
21 changes: 21 additions & 0 deletions number_theory/math_functions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <class TInt>
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<TInt>, "integral type expected");
using TUInt = helper_ns::make_unsigned_t<TInt>;
using TUIntAtLeastUInt = std::common_type_t<TUInt, uint32_t>;
auto unsigned_n = static_cast<TUIntAtLeastUInt>(static_cast<TUInt>(n));
return static_cast<TInt>(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.
Expand Down
50 changes: 50 additions & 0 deletions number_theory/test_math_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down

0 comments on commit ba94213

Please sign in to comment.