Hmm, I think 32-bits is enough.  The problem was this:

(s32)1 << 31 == 0x80000000 = as negative as it gets
(u32)1 << 31 == 0x80000000 = just a big positive number

It's enough to make the 1 unsigned, since it can't be shifted by more than 31 (`& 0x1f` above.)

-[Unknown]