Log In  

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.

P#50047 2018-03-07 08:10 ( Edited 2018-03-07 15:32)

Thanks for the advices.
They are going to be very helpful.

P#50052 2018-03-07 10:32 ( Edited 2018-03-07 15:32)

[Please log in to post a comment]

Follow Lexaloffle:          
Generated 2024-03-29 06:11:18 | 0.004s | Q:8