lua-users home
lua-l archive

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


On Fri, Aug 24, 2018 at 11:12 PM, Roberto Ierusalimschy wrote:
>
> More exactly, Lua uses this definition:
>
>   { (m) = l_mathop(fmod)(a,b); if ((m)*(b) < 0) (m) += (b); }
>
> Earlier Lua versions used the mathematical definition:
>
>   (m) = ((a) - l_mathop(floor)((a)/(b))*(b))
>
> It is *much* faster than 'fmod', but it gives NaN when 'b' is infinite
> (it should give 'a'). I am not sure whether there are other problematic
> cases besides 'b' being inf or -inf.

Apparently, the following formula gives the correct answer for all
cases:

  { (m) = l_mathop(floor)((a)/(b)); \
    (m) = ((m) == 0) ? ((a) * (b) < 0 ? (a) + (b) : (a)) : (a) - (m)*(b); }

In my machine, it can be up to 5x faster than 'fmod'. ('fmod' time
seems to depend heavily on the parameters.)



Another problem of "fast modulo" is possibility of negative result due to precision loss.
Example:
Obviously, (3*2^52+2) is congruent to 2 modulo 3.
Let's test it on Lua 5.2 and 5.3

C:\>lua52.exe -e"local a = 3*2^52+2; local b = 3; print(a%b)"
-2

C:\>lua53.exe -e"local a = 3*2^52+2; local b = 3; print(a%b)"
2.0

Users are expecting (N % M) to be between 0 and (M-1).
Correct modulo operation is not very simple, that's why fmod() is expensive.