Converting shr() safely to simple math:
shr(v, 16) ==> v * 0x.0001 shr(v, 15) ==> v * 0x.0002 ... shr(v, 2) ==> v * 0x.4000 (or 0.25) shr(v, 1) ==> v * 0x.8000 (or 0.5)
Multiplying by the fraction avoids a hazard where a negative number can go to 0 when dividing by numbers greater than 1, which destroys the sign-extending upper bits you expect to keep with shr().
It also allows shifts up to 16, whereas dividing only allows shifts up to 14. This is because PICO-8 can't represent any powers of 2 larger then 16384.
Similarly, because it is safe to divide by a fractional number less than 1, you can use the same idea to shift left up to 16 bits:
shl(v, 16) ==> v / 0x.0001 shl(v, 15) ==> v / 0x.0002 ... shl(v, 2) ==> v / 0x.4000 (or 0.25) shl(v, 1) ==> v / 0x.8000 (or 0.5)
In this case, it's down to style or the need to shift by more than 14. Unlike dividing, multiplying by values greater than 1 is safe, so you can also obviously just convert shl(v,2) to v*4. PICO-8 performs divides as fast as multiplies, so performance is the same either way.
Basically, your safe bet is always to use the fractional power of two, whether dividing or multiplying. If you want to be sure, start your constant with "0x." and you'll always get it the right way around. :)
The reason some of us want to do this, rather than the more-intuitive shift calls, is that it saves one token per shift. That can add up quickly in a program heavy with binary math.
[Please log in to post a comment]