Assorted common math functions & utilities for TypeScript/JavaScript applications
—
Functions for controlling numerical precision, rounding to specific increments, and handling floating-point precision issues.
Functions for modular arithmetic and extracting fractional parts.
/**
* GLSL-style modulo: a - b * floor(a / b)
* Different from JavaScript % operator which uses truncation
* @param a - Dividend
* @param b - Divisor
* @returns GLSL-style modulo result
*/
function mod(a: number, b: number): number;
/**
* Returns fractional part of x (equivalent to x - floor(x))
* @param x - Input value
* @returns Fractional part in range [0, 1)
*/
function fract(x: number): number;
/**
* Truncates x towards zero (removes fractional part)
* @param x - Input value
* @returns Integer part of x
*/
function trunc(x: number): number;Usage Examples:
import { mod, fract, trunc } from "@thi.ng/math/prec";
// GLSL-style modulo (always positive result)
const glslMod = mod(-3, 2); // 1 (not -1 like JS %)
const jsMod = -3 % 2; // -1 (JavaScript behavior)
// Extract fractional part
const fractional = fract(3.14159); // 0.14159
const wholePart = trunc(3.14159); // 3
// Useful for wrapping textures coordinates
const wrappedU = fract(2.7); // 0.7 (wrapped texture coordinate)Functions for rounding to specific increments and precision levels.
/**
* Rounds x to nearest multiple of prec
* @param x - Value to round
* @param prec - Precision increment (default: 1)
* @returns Value rounded to nearest multiple of prec
*/
function roundTo(x: number, prec?: number): number;
/**
* Floors x to nearest multiple of prec
* @param x - Value to floor
* @param prec - Precision increment (default: 1)
* @returns Value floored to multiple of prec
*/
function floorTo(x: number, prec?: number): number;
/**
* Ceils x to nearest multiple of prec
* @param x - Value to ceil
* @param prec - Precision increment (default: 1)
* @returns Value ceiled to multiple of prec
*/
function ceilTo(x: number, prec?: number): number;
/**
* Only rounds x if fractional part is within epsilon of 0 or 1
* Helps avoid floating-point precision issues
* @param x - Value to conditionally round
* @param eps - Epsilon threshold (default: EPS constant)
* @returns Rounded value if close to integer, otherwise original value
*/
function roundEps(x: number, eps?: number): number;Usage Examples:
import { roundTo, floorTo, ceilTo, roundEps, EPS } from "@thi.ng/math/prec";
// Round to specific increments
const rounded = roundTo(3.14159, 0.01); // 3.14
const stepped = roundTo(127, 25); // 125 (nearest multiple of 25)
// Floor and ceil to increments
const floored = floorTo(3.7, 0.5); // 3.5
const ceiled = ceilTo(3.1, 0.5); // 3.5
// Precision-aware rounding
const almostInteger = 2.9999999999999996;
const cleaned = roundEps(almostInteger); // 3 (within epsilon of integer)
const notClose = roundEps(2.5); // 2.5 (not close enough to integer)
// Grid snapping
const snapToGrid = (value: number, gridSize: number) =>
roundTo(value, gridSize);
const snapped = snapToGrid(127.3, 10); // 130import { roundEps, fract, mod } from "@thi.ng/math/prec";
// Handle accumulated floating-point errors
function cleanupFloat(value: number, precision: number = 1e-10): number {
return roundEps(value, precision);
}
// Reliable fractional part extraction
function safeFract(x: number): number {
const f = fract(x);
return cleanupFloat(f);
}
// Animation time cycling with precision cleanup
function cycleTime(time: number, duration: number): number {
const cycled = mod(time, duration);
return cleanupFloat(cycled);
}
// Usage examples
const cleanValue = cleanupFloat(0.30000000000000004); // 0.3
const safeFractional = safeFract(123.9999999999999); // 0 (cleaned)
const animTime = cycleTime(5.0000000001, 2); // 1 (clean cycle)Install with Tessl CLI
npx tessl i tessl/npm-thi-ng--math