Moonshark/tests/math.lua
2025-07-14 20:45:26 -05:00

192 lines
5.3 KiB
Lua

local math = require("math")
local function assert_close(a, b, tolerance)
tolerance = tolerance or 1e-10
if math.abs(a - b) > tolerance then
error(string.format("Expected %g, got %g (diff: %g)", a, b, math.abs(a - b)))
end
end
local function assert_equal(a, b)
if a ~= b then
error(string.format("Expected %s, got %s", tostring(a), tostring(b)))
end
end
local function test(name, fn)
print("Testing " .. name .. "...")
local ok, err = pcall(fn)
if ok then
print(" ✓ PASS")
else
print(" ✗ FAIL: " .. err)
end
end
-- Test constants
test("Constants", function()
assert_close(math.pi, 3.14159265358979323846)
assert_close(math.tau, 6.28318530717958647693)
assert_close(math.e, 2.71828182845904523536)
assert_close(math.phi, 1.61803398874989484820)
assert_equal(math.infinity, 1/0)
assert_equal(math.isnan(math.nan), true)
end)
-- Test extended functions
test("Extended Functions", function()
assert_close(math.cbrt(8), 2)
assert_close(math.cbrt(-8), -2)
assert_close(math.hypot(3, 4), 5)
assert_equal(math.isnan(0/0), true)
assert_equal(math.isnan(5), false)
assert_equal(math.isfinite(5), true)
assert_equal(math.isfinite(math.infinity), false)
assert_equal(math.sign(5), 1)
assert_equal(math.sign(-5), -1)
assert_equal(math.sign(0), 0)
assert_equal(math.clamp(5, 0, 3), 3)
assert_equal(math.clamp(-1, 0, 3), 0)
assert_close(math.lerp(0, 10, 0.5), 5)
assert_close(math.map(5, 0, 10, 0, 100), 50)
assert_equal(math.round(2.7), 3)
assert_equal(math.round(-2.7), -3)
assert_close(math.roundto(3.14159, 2), 3.14)
assert_close(math.distance(0, 0, 3, 4), 5)
end)
-- Test random functions
test("Random Functions", function()
local r = math.randomf(0, 1)
assert_equal(r >= 0 and r < 1, true)
local i = math.randint(1, 10)
assert_equal(i >= 1 and i <= 10, true)
assert_equal(type(math.randboolean()), "boolean")
end)
-- Test statistics
test("Statistics", function()
local data = {1, 2, 3, 4, 5}
assert_equal(math.sum(data), 15)
assert_equal(math.mean(data), 3)
assert_equal(math.median(data), 3)
assert_close(math.variance(data), 2.5)
assert_close(math.stdev(data), math.sqrt(2.5))
local min, max = math.minmax(data)
assert_equal(min, 1)
assert_equal(max, 5)
assert_equal(math.mode({1, 2, 2, 3}), 2)
end)
-- Test 2D vectors
test("2D Vectors", function()
local v1 = math.vec2.new(3, 4)
local v2 = math.vec2.new(1, 2)
assert_equal(v1.x, 3)
assert_equal(v1.y, 4)
assert_close(math.vec2.length(v1), 5)
assert_equal(math.vec2.length_squared(v1), 25)
local v3 = math.vec2.add(v1, v2)
assert_equal(v3.x, 4)
assert_equal(v3.y, 6)
local v4 = math.vec2.sub(v1, v2)
assert_equal(v4.x, 2)
assert_equal(v4.y, 2)
local v5 = math.vec2.mul(v1, 2)
assert_equal(v5.x, 6)
assert_equal(v5.y, 8)
assert_equal(math.vec2.dot(v1, v2), 11)
assert_close(math.vec2.distance(v1, v2), math.sqrt(8))
local normalized = math.vec2.normalize(v1)
assert_close(math.vec2.length(normalized), 1)
end)
-- Test 3D vectors
test("3D Vectors", function()
local v1 = math.vec3.new(1, 2, 3)
local v2 = math.vec3.new(4, 5, 6)
assert_close(math.vec3.length(v1), math.sqrt(14))
assert_equal(math.vec3.dot(v1, v2), 32)
local cross = math.vec3.cross(v1, v2)
assert_equal(cross.x, -3)
assert_equal(cross.y, 6)
assert_equal(cross.z, -3)
local add = math.vec3.add(v1, v2)
assert_equal(add.x, 5)
assert_equal(add.y, 7)
assert_equal(add.z, 9)
end)
-- Test 2x2 matrices
test("2x2 Matrices", function()
local m1 = math.mat2.new(1, 2, 3, 4)
local m2 = math.mat2.new(2, 0, 1, 3)
assert_equal(math.mat2.det(m1), -2)
local product = math.mat2.mul(m1, m2)
assert_equal(product[1][1], 4)
assert_equal(product[1][2], 6)
assert_equal(product[2][1], 10)
assert_equal(product[2][2], 12)
local rotation = math.mat2.rotation(math.pi/2)
assert_close(rotation[1][1], 0, 1e-10)
assert_close(rotation[1][2], -1)
assert_close(rotation[2][1], 1)
assert_close(rotation[2][2], 0, 1e-10)
end)
-- Test 3x3 matrices
test("3x3 Matrices", function()
local identity = math.mat3.identity()
assert_equal(identity[1][1], 1)
assert_equal(identity[2][2], 1)
assert_equal(identity[3][3], 1)
assert_equal(identity[1][2], 0)
local translation = math.mat3.translation(5, 10)
assert_equal(translation[1][3], 5)
assert_equal(translation[2][3], 10)
local point = {x = 1, y = 2}
local transformed = math.mat3.transform_point(translation, point)
assert_equal(transformed.x, 6)
assert_equal(transformed.y, 12)
end)
-- Test geometry functions
test("Geometry", function()
assert_close(math.geometry.triangle_area(0, 0, 4, 0, 0, 3), 6)
assert_equal(math.geometry.point_in_triangle(1, 1, 0, 0, 4, 0, 0, 3), true)
assert_equal(math.geometry.point_in_triangle(5, 5, 0, 0, 4, 0, 0, 3), false)
local intersects, x, y = math.geometry.line_intersect(0, 0, 2, 2, 0, 2, 2, 0)
assert_equal(intersects, true)
assert_close(x, 1)
assert_close(y, 1)
local closest_x, closest_y = math.geometry.closest_point_on_segment(1, 3, 0, 0, 4, 0)
assert_close(closest_x, 1)
assert_close(closest_y, 0)
end)
-- Test interpolation
test("Interpolation", function()
assert_close(math.interpolation.bezier(0.5, 0, 1, 2, 3), 1.5)
assert_close(math.interpolation.quadratic_bezier(0.5, 0, 2, 4), 2)
assert_close(math.interpolation.smoothstep(0, 1, 0.5), 0.5)
assert_close(math.interpolation.smootherstep(0, 1, 0.5), 0.5)
assert_close(math.interpolation.catmull_rom(0.5, 0, 1, 2, 3), 1.5)
end)
print("\nAll tests completed!")