Log In  


This quirk exists in Pico8 0.1.10C, and possibly other versions. Try this code out, and you'll see the results for i>=16 are the same:

for i=1,20 do
 print(i .. ' ' .. 1.11^i)
end

1.11 raised to the 20th power (equal to ~8.062) is still well within the overflow limits of pico8, but currently pico8 limits the possible exponent to 16 (resulting in ~5.309).

Here's a workaround for raising to higher power (if y is a positive power), that takes advantage of the property x^m * x^n = x^(m+n):

function pow(x,y)
local r=1
while y>0 do
r*=x^min(y,16)
y-=16
end
return r
end

Using this you can get the correct results. Just wondering, is this limitation intentional? It makes sense for integers, because 2^15-1 is the greatest positive integer you can express, and occasionally you might want to do 2^16 (if you're careful about the sign bit), but for fractions it seems a little strange. It's kind of uncommon to do this kind of math in pico8, so I could maybe live with it being a quirk of pico-8 though. If this behaviour isn't changed, could this limitation be documented in the manual?

1


It should also be documented that it's only valid for positive integers. I dunno if standard Lua allows fractions & negative numbers either, but it'd still be good to point this info out for people.


Whoa, heh you're right, the right-hand side of the exponent gets truncated to an int and only works for non-negative values in the range 0..16. Must be using a repeated multiplication loop behind the scenes! You can still use sqrt(x) to do x^0.5 though, or do 1/x instead of x^-1, so not too bad.

It'd be to nice document though, saying it only handles ints between 0 and 16, and that you can use repeated multiplication, sqrt and 1/x to fill in some of the gaps.

In standard Lua 5.2, ^ is equivalent to math.pow and is defined in terms of C's pow function so any double value can be passed as an exponent.


Yeah, I wonder why the limit on 16 though. I'm not against "multiplication loop" method, because you rarely need negative powers (and if you do, there are workarounds as mentioned), but why the limit?


You can do it a bit like multiplication, where you're keeping a running square you multiply through the result where the power value has 1 bits. You can do the same by sqrting and checking the fractional bits. The end result shouldn't really be more expensive than a naïve implementation using a multiply loop.

This is a lua implementation that handles all values, including fractional and negative numbers:

function pow(v,e)
  if(e<0) return 1/pow(v,-e)
  local ei=band(e,0xffff)
  local vi=v
  e-=ei
  local r=1
  while ei!=0 do
    if(band(ei,1)!=0) r*=vi
    vi*=vi
    ei=band(ei/2,0xffff)
  end
  while e!=0 do
    v=sqrt(v)
    if(band(e,0x.8)!=0) r*=v
    e=band(e*2,0x.ffff)
  end
  return r
end

Not extensively tested, and not nearly as convenient as a caret operator, but it ought to work for anything that doesn't inherently overflow.



[Please log in to post a comment]