Math functions bug?

Ref my recent post about Qiso in HTML5, I think I’ve narrowed the main issue down to this function for rounding numbers:

module.round = function(n, d) local d = d or 0 return math.floor(n \* math.pow(10, d) + 0.5) / math.pow(10, d) end

This works fine in the simulator and when compiled to Android, but it looks like with the HTML5 compile it’s always returning a floor, as if the + 0.5 never happens.

Are there any known issues that this might relate to? The following vanilla Javascript works fine:

var n = 1.6; var d = 0; document.write(Math.floor(n \* Math.pow(10, d) + 0.5) / Math.pow(10, d));

Thanks.

If you want to round to a specific number of decimal places, try this( reduces your usage of math functions as well as any side-effects):

local function round(val, n) if (n) then return math.floor( (val \* 10^n) + 0.5) / (10^n) else return math.floor(val+0.5) end end

Although this may seem the same as your code, it isn’t.  The underlying operations used to accomplish it will be different.  I worry that you may be encountering some side-effect of math.pow()

PS - Why is math.* spelled Math.* in your code?  I am assuming a typo there.  Ah, that was Javascript.

try removing the “local” from “local d = d or 0”.  firstly, it’s not needed; but secondly, it’s just “weird” (afterwards you have two locals named “d”, though the former is no longer accessible, having been obscured by the latter).

it’s just a wild guess, but would wonder if it’s a “scope” problem with the emscripten stack, potentially causing the javascript equiv of “Math.pow(10,null)”

I actually switched from the ^ operator to math.pow earlier today just to avoid confusion between Lua and JavaScript tests! In JS the ^ operator is a bitwise xor, but in both JS and Lua math.pow is the same. The production version of Qiso does actually use ^ still.

I’ll experiment with the local d line tomorrow. I’d not considered the possibility of issues there, but that’s an interesting thought…

Oh, and also interesting that you’ve opted for an if statement to reduce the math calls… I’ll do some benchmarking to see which is faster as more often than not, this function is indeed called without passing the d param.

Right, I’ve been tinkering more…

Firstly it turns out we’ve been chasing a red herring and actually the rounding is working properly in the HTML5 compile after all, both using math.pow and ^. Back to the drawing board in finding the source of these glitches then!

Secondly, benchmarking has shown ^ to be considerably faster than math.pow, and the if() check to be faster than the ^ maths + also faster than the local d = d or 0. Again the ^ was already in production but we’ll push the if() check to production now too and also see where else we can integrate it for similar optimisations. Thanks for that Ed!

Thirdly though, the benchmarking has shown some serious slugging from the HTML compile. The following completed in approx 0.0001 seconds in the simulator, but takes 0.2 seconds when built to HTML5 and opened in Chrome.

function testing(n, d) if(d) then return math.floor((n \* (10 ^ d)) + 0.5) / (10 ^ d) else return math.floor(n + 0.5) end end local s = os.clock() for i = 1, 100, 0.01 do testing(i, 1) end local e = os.clock() - s print(e)

Javascript is known to underperform compared with other languages, but this is a considerable jump. I doubt much can be done other than benchmarking the different loop variants in Javascript and then using the appropriate type of loop in Lua that translates to that variant in the compile rather than the most appropriate loop for Lua, which would defeat the purpose of writing platform independent code and in my view therefore not worth the effort, but hopefully this finding is at least useful to somebody else.

For timing you can use these two simple functions

--timing functions local startTime = nil function startTimer() startTime = system.getTimer() end function stopTimer() local elapsedTime = system.getTimer() - startTime print("Time = "..math.round(elapsedTime).." ms") end

if you want split times just call startTimer() once and then call stopTimer() many times.  Useful for benchmarking blocks of code.

comparing desktop/device builds to html for performance is sketchy at best.

on desktop/device builds the lua interpreter runs as native code.  on html, the lua interpreter (and everything else) is itself being interpreted by javascript (via emscripten).

so lua in an html build is effectively being “double interpreted”, and the fact that it performs as well as it does is truly a testament to emscripten, but there’s no way it’s going to match native code.

If you want to round to a specific number of decimal places, try this( reduces your usage of math functions as well as any side-effects):

local function round(val, n) if (n) then return math.floor( (val \* 10^n) + 0.5) / (10^n) else return math.floor(val+0.5) end end

Although this may seem the same as your code, it isn’t.  The underlying operations used to accomplish it will be different.  I worry that you may be encountering some side-effect of math.pow()

PS - Why is math.* spelled Math.* in your code?  I am assuming a typo there.  Ah, that was Javascript.

try removing the “local” from “local d = d or 0”.  firstly, it’s not needed; but secondly, it’s just “weird” (afterwards you have two locals named “d”, though the former is no longer accessible, having been obscured by the latter).

it’s just a wild guess, but would wonder if it’s a “scope” problem with the emscripten stack, potentially causing the javascript equiv of “Math.pow(10,null)”

I actually switched from the ^ operator to math.pow earlier today just to avoid confusion between Lua and JavaScript tests! In JS the ^ operator is a bitwise xor, but in both JS and Lua math.pow is the same. The production version of Qiso does actually use ^ still.

I’ll experiment with the local d line tomorrow. I’d not considered the possibility of issues there, but that’s an interesting thought…

Oh, and also interesting that you’ve opted for an if statement to reduce the math calls… I’ll do some benchmarking to see which is faster as more often than not, this function is indeed called without passing the d param.

Right, I’ve been tinkering more…

Firstly it turns out we’ve been chasing a red herring and actually the rounding is working properly in the HTML5 compile after all, both using math.pow and ^. Back to the drawing board in finding the source of these glitches then!

Secondly, benchmarking has shown ^ to be considerably faster than math.pow, and the if() check to be faster than the ^ maths + also faster than the local d = d or 0. Again the ^ was already in production but we’ll push the if() check to production now too and also see where else we can integrate it for similar optimisations. Thanks for that Ed!

Thirdly though, the benchmarking has shown some serious slugging from the HTML compile. The following completed in approx 0.0001 seconds in the simulator, but takes 0.2 seconds when built to HTML5 and opened in Chrome.

function testing(n, d) if(d) then return math.floor((n \* (10 ^ d)) + 0.5) / (10 ^ d) else return math.floor(n + 0.5) end end local s = os.clock() for i = 1, 100, 0.01 do testing(i, 1) end local e = os.clock() - s print(e)

Javascript is known to underperform compared with other languages, but this is a considerable jump. I doubt much can be done other than benchmarking the different loop variants in Javascript and then using the appropriate type of loop in Lua that translates to that variant in the compile rather than the most appropriate loop for Lua, which would defeat the purpose of writing platform independent code and in my view therefore not worth the effort, but hopefully this finding is at least useful to somebody else.

For timing you can use these two simple functions

--timing functions local startTime = nil function startTimer() startTime = system.getTimer() end function stopTimer() local elapsedTime = system.getTimer() - startTime print("Time = "..math.round(elapsedTime).." ms") end

if you want split times just call startTimer() once and then call stopTimer() many times.  Useful for benchmarking blocks of code.

comparing desktop/device builds to html for performance is sketchy at best.

on desktop/device builds the lua interpreter runs as native code.  on html, the lua interpreter (and everything else) is itself being interpreted by javascript (via emscripten).

so lua in an html build is effectively being “double interpreted”, and the fact that it performs as well as it does is truly a testament to emscripten, but there’s no way it’s going to match native code.