There is a strange bit of history to bit_width
.
The function that would eventually become known as bit_width
started life as log2
, as part of a proposal adding integer power-of-two functions. log2
was specified to produce UB when passed 0.
Because that’s how logarithms work.
But then, things changed. The function later became log2p1
, and for reasons that are not specified was given a wider contract (“wide contract” in C++ parlance means that more stuff is considered valid input). Specifically, 0 is valid input, and yields the value of 0.
Which is not how logarithms work, but whatever.
As C++20 neared standardization, a name conflict was discovered (PDF). The name log2p1
happens to correspond to the name of an IEEE-754 algorithm, but it’s a radically different one. Also, functions in other languages with similar inputs and results use a name like bit_length
. So it was renamed to bit_width
.
And since it’s not pretending to do a logarithm anymore, the behavior at 0 can be whatever we want.
Indeed, the Python function int.bit_length
has the exact same behavior. Leading zeros are not considered part of the bit length, and since a value of 0
contains all leading zeros…