lua-users home
lua-l archive

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

You've not understood the "Great Pedantic" (sic! visibly you use that "The Great" _expression_ as a directed insult) at all and what I really wanted to show: your suggestion does not change anything to what I meant (you've removed the call to the library "math.floor" (which does nbot matter at all, I was just speaking about what it meant, not the fact it could be overriden: the fact that even without changing/overridening it it still does not warranties to return a valid 32-bit integer).

Now you've used the "//" operator, which also does not warranty it (even without changing/overriding it): it still operates on Lua "number", which are floating points, and returns a floating point value whose value may STILL be out of range for native integers, so it's still not safe to "optimize" the compilation of this code using native integers, because this is still not what the Lua code effectively does: such compilation would be broken as well (an I insist: this is is true EVEN if there's no override at all for the Lua arithmetic operators).

The "//" operator can return a value like 1e99 which is an "integer", but given as a floatting point value, completely out of range for native integers (even if these native integers are 64 bit!). And the same applies to the math.floor() operation. 

Do you see now what I mean?

The rest of the function can still be computed, but will give "almost random"/"non-meaningful" date results if you don't take into account the maximum precision of floating point values in "Lua number" (which is 53 bit if "number" is compiled as an IEEE 64-bit double), but which successfully returns correct values when "jd" is in the range of a 50-bit signed integer.

Note also that this function is not correct if "jd" is negative: the "a // b" operation in Lua is NOT returning a "floor(a/b)" operation but a "floor(abs(a)/abs(b))*sign(a)*sign(b)" operation. But it is still defined for the whole range of Lua "numbers" (even if their absolute value is higher than 2^52 and then cannot store any fractional bits and can only represent *some* integers by rounding them to some *other* integers)

You are then making false assumptions about what are Lua numbers: they are not a simple mix of native binary integers and native floating points, they only represent floatting point values with limited precision, but much wider value ranges (plus special values for "NaNs", "infinites", "negative zero", plus "denormal values" which are normal finite numbers but with limited precision; all of them do not exist as native binary integers)

The Lua code as it is written is not simply optimizable using 32-bit or 64-bit native integers without taking into account the precision and value range of numbers (independantly of the fact that the function does not really test for the actual Lua type of its parameter).

So the real Lua code actually makes tests everywhere about types to infer which function will be used to make every step (including in the Lua virtual machine which operates only on "numbers"), and will then determine how to handle the value range and precision correctly: there are type checking and bound checking at every step).

Le lun. 26 nov. 2018 à 07:59, Sean Conner <> a écrit :
It was thus said that the Great Muh Muhten once stated:
> On 11/25/18, Philippe Verdy <> wrote:
> > Note: math.floor() is not required toi return a native binary integer. It
> > may return a variant type using integers for some ranges, and doubles
> > outside the range. So even in this case the the inference would not help
> > eliminate the necessary tests on the effective type of the variant... The
> math.floor can return literally anything. It can be redefined.

  Of course, one could rewrite the function to remove the call to
math.floor() to apease the Great Pedantic One:

        function fromjulianday(jd)
          local a = jd + 32044
          local b = (4 * a + 3) // 146097
          local c = a - (b * 146097) // 4
          local d = (4 * c + 3) // 1461
          local e = c - (1461 * d) // 4
          local m = (5 * e + 2) // 153

          return {
            day   = e - (153 * m + 2) // 5 + 1,
            month = m + 3 - 12 * (m // 10),
            year  = b * 100 + d - 4800 + (m // 10)

  This is Lua 5.3 specific code where '//' is integer division.