require("tests") -- Constants tests test("math.pi", function() assert_close(math.pi, 3.14159265358979323846) assert(math.pi > 3.14 and math.pi < 3.15) end) test("math.tau", function() assert_close(math.tau, 6.28318530717958647693) assert_close(math.tau, 2 * math.pi) end) test("math.e", function() assert_close(math.e, 2.71828182845904523536) assert(math.e > 2.7 and math.e < 2.8) end) test("math.phi", function() assert_close(math.phi, 1.61803398874989484820) assert_close(math.phi, (1 + math.sqrt(5)) / 2) end) test("math.infinity", function() assert_equal(math.infinity, 1/0) assert(math.infinity > 0) end) test("math.nan", function() assert_equal(math.isnan(math.nan), true) assert(math.nan ~= math.nan) -- NaN property end) -- Extended functions tests test("math.cbrt", function() assert_close(math.cbrt(8), 2) assert_close(math.cbrt(-8), -2) end) test("math.hypot", function() assert_close(math.hypot(3, 4), 5) assert_close(math.hypot(5, 12), 13) end) test("math.isnan", function() assert_equal(math.isnan(0/0), true) assert_equal(math.isnan(5), false) end) test("math.isfinite", function() assert_equal(math.isfinite(5), true) assert_equal(math.isfinite(math.infinity), false) end) test("math.sign", function() assert_equal(math.sign(5), 1) assert_equal(math.sign(-5), -1) assert_equal(math.sign(0), 0) end) test("math.clamp", function() assert_equal(math.clamp(5, 0, 3), 3) assert_equal(math.clamp(-1, 0, 3), 0) assert_equal(math.clamp(2, 0, 3), 2) end) test("math.lerp", function() assert_close(math.lerp(0, 10, 0.5), 5) assert_close(math.lerp(2, 8, 0.25), 3.5) end) test("math.smoothstep", function() assert_close(math.smoothstep(0, 1, 0.5), 0.5) assert_close(math.smoothstep(0, 10, 5), 0.5) end) test("math.map", function() assert_close(math.map(5, 0, 10, 0, 100), 50) assert_close(math.map(2, 0, 4, 10, 20), 15) end) test("math.round", function() assert_equal(math.round(2.7), 3) assert_equal(math.round(-2.7), -3) assert_equal(math.round(2.3), 2) end) test("math.roundto", function() assert_close(math.roundto(3.14159, 2), 3.14) assert_close(math.roundto(123.456, 1), 123.5) end) test("math.normalize_angle", function() assert_close(math.normalize_angle(math.pi * 2.5), math.pi * 0.5) assert_close(math.normalize_angle(-math.pi * 2.5), -math.pi * 0.5) end) test("math.distance", function() assert_close(math.distance(0, 0, 3, 4), 5) assert_close(math.distance(1, 1, 4, 5), 5) end) test("math.factorial", function() assert_equal(math.factorial(5), 120) assert_equal(math.factorial(0), 1) assert_equal(math.factorial(-1), nil) end) test("math.gcd", function() assert_equal(math.gcd(48, 18), 6) assert_equal(math.gcd(100, 25), 25) end) test("math.lcm", function() assert_equal(math.lcm(4, 6), 12) assert_equal(math.lcm(15, 20), 60) end) -- Random functions tests test("math.randomf", function() local r1 = math.randomf(0, 1) local r2 = math.randomf(5, 10) assert(r1 >= 0 and r1 < 1) assert(r2 >= 5 and r2 < 10) end) test("math.randint", function() local i1 = math.randint(1, 10) local i2 = math.randint(50, 60) assert(i1 >= 1 and i1 <= 10) assert(i2 >= 50 and i2 <= 60) end) test("math.randboolean", function() local b1 = math.randboolean() local b2 = math.randboolean(0.8) assert_equal(type(b1), "boolean") assert_equal(type(b2), "boolean") end) -- Statistics tests test("math.sum", function() assert_equal(math.sum({1, 2, 3, 4, 5}), 15) assert_equal(math.sum({10, 20, 30}), 60) end) test("math.mean", function() assert_equal(math.mean({1, 2, 3, 4, 5}), 3) assert_equal(math.mean({10, 20, 30}), 20) end) test("math.median", function() assert_equal(math.median({1, 2, 3, 4, 5}), 3) assert_equal(math.median({1, 2, 3, 4}), 2.5) end) test("math.variance", function() assert_close(math.variance({1, 2, 3, 4, 5}), 2) assert_close(math.variance({10, 10, 10}), 0) end) test("math.stdev", function() assert_close(math.stdev({1, 2, 3, 4, 5}), math.sqrt(2)) assert_close(math.stdev({10, 10, 10}), 0) end) test("math.mode", function() assert_equal(math.mode({1, 2, 2, 3}), 2) assert_equal(math.mode({5, 5, 4, 4, 4}), 4) end) test("math.minmax", function() local min1, max1 = math.minmax({1, 2, 3, 4, 5}) local min2, max2 = math.minmax({-5, 0, 10}) assert_equal(min1, 1) assert_equal(max1, 5) assert_equal(min2, -5) assert_equal(max2, 10) end) -- 2D Vector tests test("math.vec2.new", function() local v1 = math.vec2.new(3, 4) local v2 = math.vec2.new() assert_equal(v1.x, 3) assert_equal(v1.y, 4) assert_equal(v2.x, 0) assert_equal(v2.y, 0) end) test("math.vec2.add", function() local v1 = math.vec2.new(3, 4) local v2 = math.vec2.new(1, 2) local result = math.vec2.add(v1, v2) assert_equal(result.x, 4) assert_equal(result.y, 6) end) test("math.vec2.sub", function() local v1 = math.vec2.new(3, 4) local v2 = math.vec2.new(1, 2) local result = math.vec2.sub(v1, v2) assert_equal(result.x, 2) assert_equal(result.y, 2) end) test("math.vec2.mul", function() local v1 = math.vec2.new(3, 4) local result1 = math.vec2.mul(v1, 2) local result2 = math.vec2.mul(v1, math.vec2.new(2, 3)) assert_equal(result1.x, 6) assert_equal(result1.y, 8) assert_equal(result2.x, 6) assert_equal(result2.y, 12) end) test("math.vec2.dot", function() local v1 = math.vec2.new(3, 4) local v2 = math.vec2.new(1, 2) assert_equal(math.vec2.dot(v1, v2), 11) assert_equal(math.vec2.dot(math.vec2.new(1, 0), math.vec2.new(0, 1)), 0) end) test("math.vec2.length", function() local v1 = math.vec2.new(3, 4) local v2 = math.vec2.new(0, 5) assert_close(math.vec2.length(v1), 5) assert_close(math.vec2.length(v2), 5) end) test("math.vec2.distance", function() local v1 = math.vec2.new(0, 0) local v2 = math.vec2.new(3, 4) assert_close(math.vec2.distance(v1, v2), 5) assert_close(math.vec2.distance(math.vec2.new(1, 1), math.vec2.new(4, 5)), 5) end) test("math.vec2.normalize", function() local v1 = math.vec2.new(3, 4) local normalized = math.vec2.normalize(v1) assert_close(math.vec2.length(normalized), 1) assert_close(normalized.x, 0.6) assert_close(normalized.y, 0.8) end) test("math.vec2.rotate", function() local v1 = math.vec2.new(1, 0) local rotated90 = math.vec2.rotate(v1, math.pi/2) local rotated180 = math.vec2.rotate(v1, math.pi) assert_close(rotated90.x, 0, 1e-10) assert_close(rotated90.y, 1) assert_close(rotated180.x, -1) assert_close(rotated180.y, 0, 1e-10) end) -- 3D Vector tests test("math.vec3.new", function() local v1 = math.vec3.new(1, 2, 3) local v2 = math.vec3.new() assert_equal(v1.x, 1) assert_equal(v1.y, 2) assert_equal(v1.z, 3) assert_equal(v2.x, 0) assert_equal(v2.y, 0) assert_equal(v2.z, 0) end) test("math.vec3.cross", function() local v1 = math.vec3.new(1, 0, 0) local v2 = math.vec3.new(0, 1, 0) local cross = math.vec3.cross(v1, v2) assert_equal(cross.x, 0) assert_equal(cross.y, 0) assert_equal(cross.z, 1) end) test("math.vec3.length", function() local v1 = math.vec3.new(1, 2, 3) local v2 = math.vec3.new(0, 0, 5) assert_close(math.vec3.length(v1), math.sqrt(14)) assert_close(math.vec3.length(v2), 5) end) -- Matrix tests test("math.mat2.det", function() local m1 = math.mat2.new(1, 2, 3, 4) local m2 = math.mat2.new(2, 0, 0, 3) assert_equal(math.mat2.det(m1), -2) assert_equal(math.mat2.det(m2), 6) end) test("math.mat2.mul", function() local m1 = math.mat2.new(1, 2, 3, 4) local m2 = math.mat2.new(2, 0, 1, 3) 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) end) test("math.mat2.rotation", function() local rot90 = math.mat2.rotation(math.pi/2) local rot180 = math.mat2.rotation(math.pi) assert_close(rot90[1][1], 0, 1e-10) assert_close(rot90[1][2], -1) assert_close(rot180[1][1], -1) assert_close(rot180[2][2], -1) end) test("math.mat3.transform_point", function() local translation = math.mat3.translation(5, 10) local point1 = {x = 1, y = 2} local point2 = {x = 0, y = 0} local t1 = math.mat3.transform_point(translation, point1) local t2 = math.mat3.transform_point(translation, point2) assert_equal(t1.x, 6) assert_equal(t1.y, 12) assert_equal(t2.x, 5) assert_equal(t2.y, 10) end) test("math.mat3.det", function() local identity = math.mat3.identity() local scale = math.mat3.scale(2, 3) assert_close(math.mat3.det(identity), 1) assert_close(math.mat3.det(scale), 6) end) -- Geometry tests test("math.geometry.triangle_area", function() local area1 = math.geometry.triangle_area(0, 0, 4, 0, 0, 3) local area2 = math.geometry.triangle_area(0, 0, 2, 0, 1, 2) assert_close(area1, 6) assert_close(area2, 2) end) test("math.geometry.point_in_triangle", function() local inside1 = math.geometry.point_in_triangle(1, 1, 0, 0, 4, 0, 0, 3) local inside2 = math.geometry.point_in_triangle(5, 5, 0, 0, 4, 0, 0, 3) assert_equal(inside1, true) assert_equal(inside2, false) end) test("math.geometry.line_intersect", function() local intersects1, x1, y1 = math.geometry.line_intersect(0, 0, 2, 2, 0, 2, 2, 0) local intersects2, x2, y2 = math.geometry.line_intersect(0, 0, 1, 1, 2, 2, 3, 3) assert_equal(intersects1, true) assert_close(x1, 1) assert_close(y1, 1) assert_equal(intersects2, false) end) test("math.geometry.closest_point_on_segment", function() local x1, y1 = math.geometry.closest_point_on_segment(1, 3, 0, 0, 4, 0) local x2, y2 = math.geometry.closest_point_on_segment(5, 1, 0, 0, 4, 0) assert_close(x1, 1) assert_close(y1, 0) assert_close(x2, 4) assert_close(y2, 0) end) -- Interpolation tests test("math.interpolation.bezier", function() local result1 = math.interpolation.bezier(0.5, 0, 1, 2, 3) local result2 = math.interpolation.bezier(0, 0, 1, 2, 3) assert_close(result1, 1.5) assert_close(result2, 0) end) test("math.interpolation.quadratic_bezier", function() local result1 = math.interpolation.quadratic_bezier(0.5, 0, 2, 4) local result2 = math.interpolation.quadratic_bezier(1, 0, 2, 4) assert_close(result1, 2) assert_close(result2, 4) end) test("math.interpolation.smootherstep", function() local result1 = math.interpolation.smootherstep(0, 1, 0.5) local result2 = math.interpolation.smootherstep(0, 10, 5) assert_close(result1, 0.5) assert_close(result2, 0.5) end) test("math.interpolation.catmull_rom", function() local result1 = math.interpolation.catmull_rom(0.5, 0, 1, 2, 3) local result2 = math.interpolation.catmull_rom(0, 0, 1, 2, 3) assert_close(result1, 1.5) assert_close(result2, 1) end) summary() test_exit()