import { describe, it, expect } from "vitest"; import { gcd, lcm, Fraction } from "./fractions"; const f = (n: number, d: number) => new Fraction(n, d); describe("gcd / lcm", () => { it("computes gcd", () => { expect(gcd(12, 8)).toBe(4); expect(gcd(7, 3)).toBe(1); expect(gcd(0, 5)).toBe(5); expect(gcd(-12, 8)).toBe(4); }); it("computes lcm", () => { expect(lcm(4, 6)).toBe(12); expect(lcm(3, 5)).toBe(15); }); }); describe("Fraction sign + simplify", () => { it("keeps the sign on the numerator", () => { expect([f(2, -4).n, f(2, -4).d]).toEqual([-2, 4]); expect([f(-2, -4).n, f(-2, -4).d]).toEqual([2, 4]); }); it("reduces to lowest terms", () => { const check = (n: number, d: number, en: number, ed: number) => { const s = f(n, d).simplified(); expect([s.n, s.d]).toEqual([en, ed]); }; check(5, 10, 1, 2); check(8, 12, 2, 3); check(3, 1, 3, 1); check(2, -4, -1, 2); check(-2, -4, 1, 2); check(0, 5, 0, 1); }); it("reports whether it is already simplified", () => { expect(f(1, 2).isSimplified).toBe(true); expect(f(5, 10).isSimplified).toBe(false); }); }); describe("Fraction arithmetic (raw, then .simplified())", () => { const s = (fr: Fraction) => [fr.simplified().n, fr.simplified().d]; it("adds", () => { expect(s(f(1, 2).plus(f(1, 2)))).toEqual([1, 1]); expect(s(f(2, 10).plus(f(3, 10)))).toEqual([1, 2]); expect(s(f(1, 3).plus(f(1, 4)))).toEqual([7, 12]); }); it("subtracts", () => { expect(s(f(7, 8).minus(f(6, 8)))).toEqual([1, 8]); expect(s(f(1, 2).minus(f(1, 2)))).toEqual([0, 1]); }); it("multiplies", () => { expect(s(f(2, 3).times(f(3, 4)))).toEqual([1, 2]); expect(s(f(1, 2).times(f(1, 2)))).toEqual([1, 4]); }); it("divides (invert and multiply)", () => { expect(s(f(1, 2).dividedBy(f(1, 4)))).toEqual([2, 1]); expect(s(f(3, 4).dividedBy(f(1, 2)))).toEqual([3, 2]); }); it("handles negative fractions with the sign rules", () => { expect(s(f(-1, 2).plus(f(3, 4)))).toEqual([1, 4]); // -1/2 + 3/4 expect(s(f(1, 2).minus(f(-3, 4)))).toEqual([5, 4]); // subtracting a negative adds expect(s(f(-2, 3).times(f(1, 4)))).toEqual([-1, 6]); // different signs -> negative expect(s(f(-2, 3).times(f(-3, 5)))).toEqual([2, 5]); // same signs -> positive expect(s(f(-1, 2).dividedBy(f(1, 4)))).toEqual([-2, 1]); // -1/2 รท 1/4 }); }); describe("Fraction presentation + equality", () => { it("renders KaTeX, collapsing whole numbers", () => { expect(f(1, 2).toKatex()).toBe("\\frac{1}{2}"); expect(f(3, 1).toKatex()).toBe("3"); }); it("renders signed KaTeX with the sign in front", () => { expect(f(-3, 4).toSignedKatex()).toBe("-\\frac{3}{4}"); expect(f(3, 4).toSignedKatex()).toBe("\\frac{3}{4}"); expect(f(-5, 1).toSignedKatex()).toBe("-5"); }); it("compares by value, not written form", () => { expect(f(5, 10).equals(f(1, 2))).toBe(true); expect(f(1, 2).equals(f(1, 3))).toBe(false); }); });