mcy / best

The Best Library: a C++ STL replacement
Apache License 2.0
158 stars 1 forks source link

`best::count_zeros` doesn't handle integer promotion properly #27

Open sarah-ek opened 2 months ago

sarah-ek commented 2 months ago

it currently returns

return std::popcount(~to_unsigned(x));

when x is smaller than int, e.g., short. to_unsigned(x) returns a value of type unsigned short. using it as an operand of an arithmetic operation ~x, it first gets promoted to int, then the operation gets applied, returning another int, which causes the call to std::popcount to fail since it's a signed integer type.

to fix this we could write it as

auto u = to_unsigned(x);
using unsigned = decltype(u);

return std::popcount(static_cast<unsigned>(~u));
mcy commented 2 months ago

I think the easiest fix is gonna be std::popcount(to_unsigned(~to_unsigned(x)). Casting to unsigned isn't correct because it won't work right for 64-bit arguments. Feel free to file a pull request here.

sarah-ek commented 2 months ago

oh oops. i haven't written c++ in a while so i forgot unsigned is a keyword :skull: the unsigned in the cast refers to the type alias on the second line.