Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions math/deg_to_rad.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2018-2026 the Deno authors. MIT license.
// This module is browser compatible.

/**
* Converts degrees to radians.
*
* @param degrees The angle in degrees
* @returns The angle in radians
*
* @example Usage
* ```ts
* import { degToRad } from "@std/math/deg-to-rad";
* import { assertEquals } from "@std/assert";
*
* assertEquals(degToRad(180), Math.PI);
* assertEquals(degToRad(90), Math.PI / 2);
* ```
*/
export function degToRad(degrees: number): number {
return degrees * (Math.PI / 180);
}
19 changes: 19 additions & 0 deletions math/deg_to_rad_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2018-2026 the Deno authors. MIT license.
import { assertEquals } from "@std/assert";
import { degToRad } from "./deg_to_rad.ts";

Deno.test("degToRad() converts 180 degrees to PI", () => {
assertEquals(degToRad(180), Math.PI);
});

Deno.test("degToRad() converts 90 degrees to PI/2", () => {
assertEquals(degToRad(90), Math.PI / 2);
});

Deno.test("degToRad() converts 0 degrees to 0", () => {
assertEquals(degToRad(0), 0);
});

Deno.test("degToRad() converts 360 degrees to 2*PI", () => {
assertEquals(degToRad(360), Math.PI * 2);
});
13 changes: 12 additions & 1 deletion math/deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,18 @@
"exports": {
".": "./mod.ts",
"./clamp": "./clamp.ts",
"./deg-to-rad": "./deg_to_rad.ts",
"./gcd": "./gcd.ts",
"./lcm": "./lcm.ts",
"./lerp": "./lerp.ts",
"./mean": "./mean.ts",
"./median": "./median.ts",
"./mode": "./mode.ts",
"./modulo": "./modulo.ts",
"./round-to": "./round_to.ts"
"./rad-to-deg": "./rad_to_deg.ts",
"./round-to": "./round_to.ts",
"./std-dev": "./std_dev.ts",
"./sum": "./sum.ts",
"./variance": "./variance.ts"
}
}
27 changes: 27 additions & 0 deletions math/gcd.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2018-2026 the Deno authors. MIT license.
// This module is browser compatible.

/**
* Calculates the greatest common divisor of two numbers.
*
* @param a The first number
* @param b The second number
* @returns The greatest common divisor
*
* @example Usage
* ```ts
* import { gcd } from "@std/math/gcd";
* import { assertEquals } from "@std/assert";
*
* assertEquals(gcd(12, 8), 4);
* assertEquals(gcd(7, 3), 1);
* ```
*/
export function gcd(a: number, b: number): number {
a = Math.abs(a);
b = Math.abs(b);
while (b !== 0) {
[a, b] = [b, a % b];
}
return a;
}
20 changes: 20 additions & 0 deletions math/gcd_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright 2018-2026 the Deno authors. MIT license.
import { assertEquals } from "@std/assert";
import { gcd } from "./gcd.ts";

Deno.test("gcd() handles basic cases", () => {
assertEquals(gcd(12, 8), 4);
assertEquals(gcd(7, 3), 1);
assertEquals(gcd(0, 5), 5);
assertEquals(gcd(5, 0), 5);
});

Deno.test("gcd() handles negative numbers", () => {
assertEquals(gcd(-12, 8), 4);
assertEquals(gcd(12, -8), 4);
assertEquals(gcd(-12, -8), 4);
});

Deno.test("gcd() handles same numbers", () => {
assertEquals(gcd(7, 7), 7);
});
25 changes: 25 additions & 0 deletions math/lcm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2018-2026 the Deno authors. MIT license.
// This module is browser compatible.

import { gcd } from "./gcd.ts";

/**
* Calculates the least common multiple of two numbers.
*
* @param a The first number
* @param b The second number
* @returns The least common multiple
*
* @example Usage
* ```ts
* import { lcm } from "@std/math/lcm";
* import { assertEquals } from "@std/assert";
*
* assertEquals(lcm(12, 8), 24);
* assertEquals(lcm(7, 3), 21);
* ```
*/
export function lcm(a: number, b: number): number {
if (a === 0 || b === 0) return 0;
return Math.abs(a * b) / gcd(a, b);
}
22 changes: 22 additions & 0 deletions math/lcm_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2018-2026 the Deno authors. MIT license.
import { assertEquals } from "@std/assert";
import { lcm } from "./lcm.ts";

Deno.test("lcm() handles basic cases", () => {
assertEquals(lcm(12, 8), 24);
assertEquals(lcm(7, 3), 21);
});

Deno.test("lcm() handles zero", () => {
assertEquals(lcm(0, 5), 0);
assertEquals(lcm(5, 0), 0);
});

Deno.test("lcm() handles negative numbers", () => {
assertEquals(lcm(-12, 8), 24);
assertEquals(lcm(12, -8), 24);
});

Deno.test("lcm() returns the number when both are the same", () => {
assertEquals(lcm(7, 7), 7);
});
25 changes: 25 additions & 0 deletions math/lerp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2018-2026 the Deno authors. MIT license.
// This module is browser compatible.

/**
* Performs linear interpolation between two values.
*
* @param a The start value
* @param b The end value
* @param t The interpolation parameter (0 returns `a`, 1 returns `b`)
* @returns The interpolated value
*
* @example Usage
* ```ts
* import { lerp } from "@std/math/lerp";
* import { assertEquals } from "@std/assert";
*
* assertEquals(lerp(0, 10, 0.5), 5);
* assertEquals(lerp(0, 10, 0), 0);
* assertEquals(lerp(0, 10, 1), 10);
* ```
*/
// deno-lint-ignore deno-style-guide/exported-function-args-maximum
export function lerp(a: number, b: number, t: number): number {
return a + (b - a) * t;
}
19 changes: 19 additions & 0 deletions math/lerp_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2018-2026 the Deno authors. MIT license.
import { assertEquals } from "@std/assert";
import { lerp } from "./lerp.ts";

Deno.test("lerp() returns start when t = 0", () => {
assertEquals(lerp(0, 10, 0), 0);
});

Deno.test("lerp() returns end when t = 1", () => {
assertEquals(lerp(0, 10, 1), 10);
});

Deno.test("lerp() returns midpoint when t = 0.5", () => {
assertEquals(lerp(0, 10, 0.5), 5);
});

Deno.test("lerp() handles negative values", () => {
assertEquals(lerp(-10, 10, 0.5), 0);
});
25 changes: 25 additions & 0 deletions math/mean.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2018-2026 the Deno authors. MIT license.
// This module is browser compatible.

/**
* Calculates the arithmetic mean of an array of numbers.
*
* @param numbers The numbers to calculate the mean of
* @returns The arithmetic mean of the numbers
*
* @example Usage
* ```ts
* import { mean } from "@std/math/mean";
* import { assertEquals } from "@std/assert";
*
* assertEquals(mean([1, 2, 3, 4]), 2.5);
* ```
*/
export function mean(numbers: readonly number[]): number {
if (numbers.length === 0) {
throw new RangeError("`numbers` must contain at least one element");
}
let total = 0;
for (const n of numbers) total += n;
return total / numbers.length;
}
21 changes: 21 additions & 0 deletions math/mean_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2018-2026 the Deno authors. MIT license.
import { assertEquals, assertThrows } from "@std/assert";
import { mean } from "./mean.ts";

Deno.test("mean() handles basic cases", () => {
assertEquals(mean([1, 2, 3, 4]), 2.5);
assertEquals(mean([10]), 10);
assertEquals(mean([0, 0, 0]), 0);
});

Deno.test("mean() handles decimals", () => {
assertEquals(mean([1.5, 2.5, 3]), 7 / 3);
});

Deno.test("mean() throws on empty array", () => {
assertThrows(
() => mean([]),
RangeError,
"`numbers` must contain at least one element",
);
});
28 changes: 28 additions & 0 deletions math/median.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2018-2026 the Deno authors. MIT license.
// This module is browser compatible.

/**
* Calculates the median of an array of numbers.
*
* @param numbers The numbers to calculate the median of
* @returns The median of the numbers
*
* @example Usage
* ```ts
* import { median } from "@std/math/median";
* import { assertEquals } from "@std/assert";
*
* assertEquals(median([1, 2, 3, 4, 5]), 3);
* assertEquals(median([1, 2, 3, 4]), 2.5);
* ```
*/
export function median(numbers: readonly number[]): number {
if (numbers.length === 0) {
throw new RangeError("`numbers` must contain at least one element");
}
const sorted = [...numbers].sort((a, b) => a - b);
const mid = sorted.length >> 1;
return sorted.length % 2 === 1
? sorted[mid]!
: (sorted[mid - 1]! + sorted[mid]!) / 2;
}
27 changes: 27 additions & 0 deletions math/median_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2018-2026 the Deno authors. MIT license.
import { assertEquals, assertThrows } from "@std/assert";
import { median } from "./median.ts";

Deno.test("median() handles odd length", () => {
assertEquals(median([1, 2, 3, 4, 5]), 3);
});

Deno.test("median() handles even length", () => {
assertEquals(median([1, 2, 3, 4]), 2.5);
});

Deno.test("median() handles single element", () => {
assertEquals(median([42]), 42);
});

Deno.test("median() handles unsorted input", () => {
assertEquals(median([5, 1, 3, 2, 4]), 3);
});

Deno.test("median() throws on empty array", () => {
assertThrows(
() => median([]),
RangeError,
"`numbers` must contain at least one element",
);
});
11 changes: 11 additions & 0 deletions math/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,16 @@
*/

export * from "./clamp.ts";
export * from "./deg_to_rad.ts";
export * from "./gcd.ts";
export * from "./lcm.ts";
export * from "./lerp.ts";
export * from "./mean.ts";
export * from "./median.ts";
export * from "./mode.ts";
export * from "./modulo.ts";
export * from "./rad_to_deg.ts";
export * from "./round_to.ts";
export * from "./std_dev.ts";
export * from "./sum.ts";
export * from "./variance.ts";
41 changes: 41 additions & 0 deletions math/mode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright 2018-2026 the Deno authors. MIT license.
// This module is browser compatible.

/**
* Calculates the mode of an array of numbers.
*
* If there are multiple modes (multimodal), all of them are returned.
*
* @param numbers The numbers to calculate the mode of
* @returns An array of the most frequent value(s)
*
* @example Usage
* ```ts
* import { mode } from "@std/math/mode";
* import { assertEquals } from "@std/assert";
*
* assertEquals(mode([1, 2, 2, 3, 4]), [2]);
* assertEquals(mode([1, 1, 2, 2, 3]), [1, 2]);
* ```
*/
export function mode(numbers: readonly number[]): number[] {
if (numbers.length === 0) {
throw new RangeError("`numbers` must contain at least one element");
}
const counts = new Map<number, number>();
for (const n of numbers) {
counts.set(n, (counts.get(n) ?? 0) + 1);
}
let maxCount = 0;
const result: number[] = [];
for (const [value, count] of counts) {
if (count > maxCount) {
result.length = 0;
result.push(value);
maxCount = count;
} else if (count === maxCount) {
result.push(value);
}
}
return result;
}
27 changes: 27 additions & 0 deletions math/mode_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2018-2026 the Deno authors. MIT license.
import { assertEquals, assertThrows } from "@std/assert";
import { mode } from "./mode.ts";

Deno.test("mode() handles unimodal data", () => {
assertEquals(mode([1, 2, 2, 3, 4]), [2]);
});

Deno.test("mode() handles multimodal data", () => {
assertEquals(mode([1, 1, 2, 2, 3]), [1, 2]);
});

Deno.test("mode() handles all same values", () => {
assertEquals(mode([5, 5, 5]), [5]);
});

Deno.test("mode() handles single element", () => {
assertEquals(mode([42]), [42]);
});

Deno.test("mode() throws on empty array", () => {
assertThrows(
() => mode([]),
RangeError,
"`numbers` must contain at least one element",
);
});
Loading
Loading