Skip to content

Commit 8c1a20f

Browse files
committed
Implement log(value, 2_bi) with std::bit_width for better codegen
1 parent 9c59b1a commit 8c1a20f

File tree

1 file changed

+10
-1
lines changed

1 file changed

+10
-1
lines changed

source/bounded/log.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ constexpr auto as_unsigned(auto const value) {
3535
return static_cast<numeric_traits::make_unsigned<decltype(value)>>(value);
3636
};
3737

38+
template<typename T>
39+
concept supports_bit_width = requires(T integer) {
40+
std::bit_width(as_unsigned(integer.value()));
41+
};
42+
3843
// TODO: It's useful for 0 to return 0, but that's not `log`.
3944
export template<bounded_integer Value, bounded_integer Base>
4045
constexpr auto log(Value const value, Base const base) {
@@ -44,7 +49,11 @@ constexpr auto log(Value const value, Base const base) {
4449
log_impl(static_cast<numeric_traits::max_unsigned_t>(builtin_min_value<Value>), static_cast<numeric_traits::max_unsigned_t>(numeric_traits::max_value<Base>)),
4550
log_impl(static_cast<numeric_traits::max_unsigned_t>(builtin_max_value<Value>), static_cast<numeric_traits::max_unsigned_t>(numeric_traits::min_value<Base>))
4651
>;
47-
return result_type(log_impl(as_unsigned(value.value()), as_unsigned(base.value())), unchecked);
52+
if constexpr (base == constant<2> and supports_bit_width<Value>) {
53+
return result_type(value == constant<0> ? 0 : std::bit_width(as_unsigned(value.value())) - 1, unchecked);
54+
} else {
55+
return result_type(log_impl(as_unsigned(value.value()), as_unsigned(base.value())), unchecked);
56+
}
4857
}
4958

5059
} // namespace bounded

0 commit comments

Comments
 (0)