How do you efficiently convert a number n to a number with that many low significant bits set? That is, for an 8-bit integer:
0 -> 00000000
1 -> 00000001
2 -> 00000011
3 -> 00000111
4 -> 00001111
5 -> 00011111
6 -> 00111111
7 -> 01111111
8 -> 11111111
Seems trivial:
fn conv(n: u8) -> u8 { (1 << n) - 1 }
But it's not:
thread 'main' panicked at 'attempt to shift left with overflow', src/main.rs:2:5
This is because, in Rust, a number with N bits cannot be shifted left N places. It is undefined behaviour on many architectures.
u8::MAX >> (8 - n)
doesn't work either as shift right has the same overflow restriction.
So, what is an efficient way to achieve this without a lookup table or a conditional? Or is this not possible and one must resort to an implementation like:
fn conv2(n: u8) -> u8 {
match 1u8.checked_shl(n.into()) {
Some(n) => n - 1,
None => u8::MAX,
}
}