Suppose we have an index that fits in a u27, and a flag that fits in a u5. We can store both in a u32 as either:
(index << 5) + flag
(flag << 27) + index
In practice, is there any advantage/standard for picking one over the other? [Context: compressing stuff in b tree nodes, so not using 2 u32 is important]
You could do it without bit shifting, using u32 flags that are multiples of 227, combine them with | (bitwise or), and extract the values with & (bitwise and) and an appropriate mask. In that case, the representation would be the
(flag << 27) + index
version. Disclaimer: I don’t know about practical advantages/standards and don’t have any experience doing something like this myself.
I’d assume your k is actually a constant? Then it doesn’t really matter how you calculate it, and I would maybe just put the mask in a const.
const LOWER_27_BITS: u32 = (1 << 27) - 1;
I’m personally not aware of any more idiomatic approach. You have to make sure to use 28 in the shift for getting 27 bits to be 1 use parentheses even though the shift is used somewhat like an exponential here, and exponentiation usually binds tighter than addition. Maybe it’s slightly less confusing to use 2.pow then…
Thanks, good catch. Makes sense now, thinking about it again. I've messed up my testing by forgetting the parentheses, so that the result of 1 << 28 - 1 looked closer to the correct anwer. But only because that's 1 << (28 - 1).
So the code I had wouldn't have given 27 ones or 28 ones but instead a single one followed by 27 zeroes.