• Subject: Re: [PATCH] Loop Overflow Bug Fix
• From: Dirk Laurie <dirk.laurie@...>
• Date: Fri, 17 Nov 2017 08:38:34 +0200

```2017-11-17 0:26 GMT+02:00 Paige DePol <lual@serfnet.org>:
> Paige DePol <lual@serfnet.org> 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]

A for loop with floating-point increment, and what appears to be an
integer multiple of it as upper limit, is obscene code. In a numerical
analysis course, it is a standard example of what one should not do,
and a fix is taught. (It basically involves adding half the increment
to the upper limit.)

I know only one language that on a routine basis accepts that its
users may not know all that, and therefore provides a built-in fix for
the problem. I won't mention its name since it is a language that
people either love or hate. If the same idea is implemented in Lua, it
would involve two additional predefined constants math.abstol and
math.reltol. A floating-point loop 'for x in start,stop,inc' would be
equivalent to

do local x=start
while math.abs(x-stop) <= math.max(math.abstol,math.reltol*math.abs(x)) do
-- loop body
x = x+inc
end

The defaults are such that loops like "for x=1,5,0.1" give the
intuitively expected behaviour, but the user is permitted to change
either tolerance. Most commonly one would set one of them to 0, so
that the test simplifies to either relative or absolute tolerance.

I guess that the bottom line is that the VM instruction should right
at the start determine whether integer or floating-point arithmetic is
to be used, and that different algorithms coping with the different
problems (integer overflow, floating-point inexactness) shoukd be
applied.

-- Dirk

```