100 lines
2.8 KiB
TypeScript
100 lines
2.8 KiB
TypeScript
import { clamp01, lerp, remap, smoothstep, damp, seeded } from "./math";
|
|
|
|
describe("optimization/math — clamp01()", () => {
|
|
it("clamps to [0,1]", () => {
|
|
expect(clamp01(-2)).toBe(0);
|
|
expect(clamp01(0)).toBe(0);
|
|
expect(clamp01(0.37)).toBe(0.37);
|
|
expect(clamp01(1)).toBe(1);
|
|
expect(clamp01(5)).toBe(1);
|
|
});
|
|
});
|
|
|
|
describe("optimization/math — lerp()", () => {
|
|
it("interpolates linearly", () => {
|
|
expect(lerp(0, 10, 0)).toBe(0);
|
|
expect(lerp(0, 10, 1)).toBe(10);
|
|
expect(lerp(0, 10, 0.5)).toBe(5);
|
|
expect(lerp(2, 4, 0.25)).toBe(2.5);
|
|
});
|
|
|
|
it("extrapolates past the endpoints", () => {
|
|
expect(lerp(0, 10, 2)).toBe(20);
|
|
expect(lerp(0, 10, -1)).toBe(-10);
|
|
});
|
|
});
|
|
|
|
describe("optimization/math — remap()", () => {
|
|
it("remaps and clamps to the output range", () => {
|
|
expect(remap(5, 0, 10, 0, 100)).toBe(50);
|
|
expect(remap(-5, 0, 10, 0, 100)).toBe(0);
|
|
expect(remap(15, 0, 10, 0, 100)).toBe(100);
|
|
});
|
|
|
|
it("defaults the output range to [0,1]", () => {
|
|
expect(remap(2.5, 0, 10)).toBeCloseTo(0.25, 10);
|
|
});
|
|
|
|
it("guards against a zero-width input range (no NaN)", () => {
|
|
const v = remap(5, 2, 2, 0, 1);
|
|
expect(Number.isNaN(v)).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("optimization/math — smoothstep()", () => {
|
|
it("hits 0 and 1 at the edges and 0.5 at the middle", () => {
|
|
expect(smoothstep(0, 1, 0)).toBe(0);
|
|
expect(smoothstep(0, 1, 1)).toBe(1);
|
|
expect(smoothstep(0, 1, 0.5)).toBeCloseTo(0.5, 10);
|
|
});
|
|
|
|
it("clamps outside the edges", () => {
|
|
expect(smoothstep(0, 1, -1)).toBe(0);
|
|
expect(smoothstep(0, 1, 2)).toBe(1);
|
|
});
|
|
|
|
it("is monotonically non-decreasing", () => {
|
|
let prev = -Infinity;
|
|
for (let x = -0.2; x <= 1.2; x += 0.1) {
|
|
const v = smoothstep(0, 1, x);
|
|
expect(v).toBeGreaterThanOrEqual(prev);
|
|
prev = v;
|
|
}
|
|
});
|
|
|
|
it("guards against equal edges (no NaN)", () => {
|
|
expect(Number.isNaN(smoothstep(1, 1, 1))).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("optimization/math — damp()", () => {
|
|
it("does not move when dt is 0", () => {
|
|
expect(damp(3, 10, 5, 0)).toBe(3);
|
|
});
|
|
|
|
it("moves toward the target and converges with large lambda*dt", () => {
|
|
const once = damp(0, 10, 1, 0.5);
|
|
expect(once).toBeGreaterThan(0);
|
|
expect(once).toBeLessThan(10);
|
|
expect(damp(0, 10, 50, 1)).toBeCloseTo(10, 5);
|
|
});
|
|
});
|
|
|
|
describe("optimization/math — seeded()", () => {
|
|
it("is deterministic for a given input", () => {
|
|
expect(seeded(7)).toBe(seeded(7));
|
|
});
|
|
|
|
it("returns values within [0,1)", () => {
|
|
for (let i = 0; i < 200; i++) {
|
|
const v = seeded(i);
|
|
expect(v).toBeGreaterThanOrEqual(0);
|
|
expect(v).toBeLessThan(1);
|
|
}
|
|
});
|
|
|
|
it("produces different values for different seeds", () => {
|
|
expect(seeded(1)).not.toBe(seeded(2));
|
|
});
|
|
});
|