neyuki 0.6.2

A small Lua-like scripting language implemented in Rust
local math = require("@neyuki/math")

local function near(a: number, b: number): bool
    return math.abs(a - b) < 1e-9
end

-- rounding
assert(math.ceil(1.2) == 2, "ceil")
assert(math.ceil(-1.2) == -1, "ceil negative")
assert(math.round(2.5) == 3, "round half away from zero")
assert(math.round(-2.5) == -3, "round negative half")
assert(math.round(2.4) == 2, "round down")

-- trig
assert(near(math.sin(0), 0), "sin 0")
assert(near(math.sin(math.pi / 2), 1), "sin pi/2")
assert(near(math.cos(0), 1), "cos 0")
assert(near(math.cos(math.pi), -1), "cos pi")
assert(near(math.tan(math.pi / 4), 1), "tan pi/4")
assert(near(math.asin(1), math.pi / 2), "asin 1")
assert(near(math.acos(1), 0), "acos 1")
assert(near(math.atan(1), math.pi / 4), "atan 1")
assert(near(math.atan2(1, 1), math.pi / 4), "atan2")
assert(near(math.atan2(1, -1), 3 * math.pi / 4), "atan2 quadrant 2")
assert(near(math.sinh(0), 0), "sinh 0")
assert(near(math.cosh(0), 1), "cosh 0")
assert(near(math.tanh(0), 0), "tanh 0")
assert(near(math.sinh(1), (math.e - 1 / math.e) / 2), "sinh 1")

local ok7, _ = try(math.asin, 2)
assert(not ok7, "asin should reject values outside [-1, 1]")

-- angle conversion
assert(near(math.deg(math.pi), 180), "deg")
assert(near(math.rad(180), math.pi), "rad")
assert(near(math.deg(math.rad(37)), 37), "deg/rad roundtrip")

-- logs and powers
assert(near(math.log(math.e), 1), "log e")
assert(near(math.log(8, 2), 3), "log base 2")
assert(near(math.log10(1000), 3), "log10")
assert(near(math.pow(2, 10), 1024), "pow")
assert(near(math.pow(4, 0.5), 2), "pow fractional")
local ok1, _ = try(math.log, -1)
assert(not ok1, "log should reject negatives")

-- fmod / modf / frexp / ldexp
assert(near(math.fmod(7, 3), 1), "fmod")
assert(near(math.fmod(-7, 3), -1), "fmod keeps sign of dividend")
assert(near(math.fmod(5.5, 2), 1.5), "fmod fractional")
local ok2, _ = try(math.fmod, 1, 0)
assert(not ok2, "fmod should reject zero divisor")

local ipart, fpart = math.modf(3.75)
assert(near(ipart, 3) and near(fpart, 0.75), "modf")
local ipart2, fpart2 = math.modf(-3.75)
assert(near(ipart2, -3) and near(fpart2, -0.75), "modf negative")

local m, e = math.frexp(8)
assert(near(m, 0.5) and e == 4, "frexp 8")
local m2, e2 = math.frexp(0.3)
assert(m2 >= 0.5 and m2 < 1 and near(math.ldexp(m2, e2), 0.3), "frexp/ldexp roundtrip")
local m3, e3 = math.frexp(-10)
assert(near(m3, -0.625) and e3 == 4, "frexp negative")
local m4, e4 = math.frexp(0)
assert(m4 == 0 and e4 == 0, "frexp zero")
assert(near(math.ldexp(3, 4), 48), "ldexp")
assert(near(math.ldexp(1, -2), 0.25), "ldexp negative exponent")

-- finiteness
assert(math.isfinite(1.5), "isfinite")
assert(math.isfinite(42), "isfinite int")
assert(not math.isfinite(math.huge), "isfinite huge")
assert(not math.isfinite(0 / 0), "isfinite nan")
assert(math.isinf(math.huge), "isinf")
assert(math.isinf(-math.huge), "isinf negative")
assert(not math.isinf(0 / 0), "isinf nan")
assert(not math.isinf(3), "isinf finite")

-- interpolation
assert(near(math.lerp(0, 10, 0.5), 5), "lerp")
assert(near(math.lerp(10, 20, 0), 10), "lerp start")
assert(near(math.lerp(10, 20, 1), 20), "lerp end")
assert(near(math.map(5, 0, 10, 0, 100), 50), "map")
assert(near(math.map(0, -1, 1, 10, 20), 15), "map offset")
local ok3, _ = try(math.map, 1, 2, 2, 0, 1)
assert(not ok3, "map should reject an empty input range")

-- noise
assert(math.noise(1, 2, 3) == 0, "noise at integer lattice is zero")
local n1 = math.noise(0.5, 0.25, 0.75)
assert(n1 == math.noise(0.5, 0.25, 0.75), "noise is deterministic")
assert(n1 >= -1 and n1 <= 1, "noise in range")
assert(math.noise(0.3) == math.noise(0.3, 0, 0), "noise defaults y and z to 0")
assert(math.noise(0.3, 0.7) != math.noise(0.3, 0.2), "noise varies along y")
local ok4, _ = try(math.noise, math.huge)
assert(not ok4, "noise should reject infinite coordinates")

-- argument validation
local ok5, _ = try(math.sin, "x")
assert(not ok5, "sin should reject strings")
local ok6, _ = try(math.ceil)
assert(not ok6, "ceil should reject nil")

print("[pass] math functions")