#!/usr/bin/env lua5.3

-- NOTE: Lua uses double-precision float and 64-bit integer
-- (except when being specifically compiled with single-precision float and 32-bit integer)
-- Double-precision floating-point number: exact integers up to 2^53
--         [1 bit](sign) + [11 bits](exponent) + [53 bits (52 explicitly stored)](fraction)
-- Single-precision floating-point number: exact integers up to 2^24
--         [1 bit](sign) + [8 bits](exponent) + [24 bits (23 explicitly stored)](fraction)

-- Integer wraps around
-- Below are max(min)imum presentable integers
print(math.maxinteger == 0x7fffffffffffffff) -- 2^63 - 1
print(math.mininteger == 0x8000000000000000)

-- Convert ineger to float (up to 2^53)
print(math.type(3 + 0.0))
-- Force a number to be integer (has no fractional part)
local function cond2int(x)
    return math.tointeger(x) or x
end
print(math.type(3.0 | 0))
print(math.tointeger(356.00))
print(math.tointeger(5.6))
print(cond2int(5.6))

-- Hex numbers are auto-converted to dec
print(0xffa4)

-- NOTE: operators of floats/integers returns a float/integer
-- Exception: division always returns a float. Use `//` to get an integer division
print(3 / 2)
print(math.pi // 1.2)

-- Rounding decimal digits
local pi = math.pi
print(pi - pi % 0.0001)

-- Radian is used by default
print(math.sin(30))
print(math.deg(2 * math.pi))

-- Unbiased rounding number function (haft-integers are rounded to the nearest even integer)
-- Using simply math.floor(x + 0.5) will always round the number up (eg. 2.5 -> 3)
-- also 2^52 + 0.5 cannot be represent (2^52 -> 2^53 has fixed interval 1)
local function round(x)
    local f = math.floor(x)
    if x == f or (x % 2.0 == 0.5) then
        return f
    else
        return math.floor(x + 0.5)
    end
end
print(round(2.5))
print(round(3.5))
