lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

Paige DePol <> wrote

> In lvm.c:
> #define forstepcheck(ns,ni,nl) \
>          (luai_numne(ns, luai_numsub(L, luai_numadd(L, ni, ns), ni)) || \
>           luai_numne(ns, luai_numsub(L, nl, luai_numsub(L, nl, ns))))

This worked... until it didn't. Floating point numbers are so strange! 

3.2 == (1.0 + 3.2) - 1.0  [3.2]
3.2 == (16.0 + 3.2) - 16.0  [3.2]

Looks like that should pass the test... but it failed (sorry for the excessive width):

3.200000000000000177636 == (1.000000000000000000000 + 3.200000000000000177636) - 1.000000000000000000000  [3.200000000000000177636]
3.200000000000000177636 == (16.000000000000000000000 + 3.200000000000000177636) - 16.000000000000000000000  [3.199999999999999289457]

I remember encountering this issue with floating-point values once before
and having a discussion about it. However, I realised I have made this patch
a bit more complicated than necessary... I updated the 'forstepcheck' macro
as follows and now invalid step magnitude detection works with 1 or 2 less
floating point operations per OP_FORPREP instruction.

#define forstepcheck(ns,ni,nl)  \
          (luai_numeq(ni, luai_numadd(L, ni, ns)) ||  \
           luai_numeq(nl, luai_numsub(L, nl, ns)))

In essence it just checks if the init and/or limit values are the same after
a single step is added or subtracted. If the value is the same then the step
magnitude is too small to affect the loop index and an error will be thrown.

My other optimisation idea wound up working for integers only, however,
considering the overall impact of the extra check per loop iteration is
negligible I decided not to bother, premature optimisation and all that.

Thanks to everyone for the feedback and providing extra cases and conditions
to think about, that assistance is very appreciated!