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
33 changes: 33 additions & 0 deletions Maths/ClampNumber.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* @function clampNumber
* @description Clamps a number between a minimum and maximum value.
* If the number is less than min, returns min.
* If the number is greater than max, returns max.
* Otherwise returns the number itself.
* @param {number} num - The number to clamp
* @param {number} min - The minimum value
* @param {number} max - The maximum value
* @returns {number} - The clamped number
* @see https://en.wikipedia.org/wiki/Clamping_(graphics)
* @example clampNumber(5, 1, 10) => 5
* @example clampNumber(-5, 1, 10) => 1
* @example clampNumber(15, 1, 10) => 10
*/
const clampNumber = (num, min, max) => {
if (
typeof num !== 'number' ||
typeof min !== 'number' ||
typeof max !== 'number' ||
isNaN(num) ||
isNaN(min) ||
isNaN(max)
) {
throw new TypeError('All inputs must be numbers')
}
if (min > max) {
throw new RangeError('min must be less than or equal to max')
}
return Math.min(Math.max(num, min), max)
}

export { clampNumber }
47 changes: 47 additions & 0 deletions Maths/test/ClampNumber.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { clampNumber } from '../ClampNumber.js'

describe('clampNumber', () => {
test('clampNumber(5, 1, 10) returns 5', () => {
expect(clampNumber(5, 1, 10)).toBe(5)
})

test('clampNumber(-5, 1, 10) returns 1', () => {
expect(clampNumber(-5, 1, 10)).toBe(1)
})

test('clampNumber(15, 1, 10) returns 10', () => {
expect(clampNumber(15, 1, 10)).toBe(10)
})

test('clampNumber(1, 1, 10) returns 1 (at min)', () => {
expect(clampNumber(1, 1, 10)).toBe(1)
})

test('clampNumber(10, 1, 10) returns 10 (at max)', () => {
expect(clampNumber(10, 1, 10)).toBe(10)
})

test('clampNumber works with negative range', () => {
expect(clampNumber(-5, -10, -1)).toBe(-5)
})

test('clampNumber works with decimals', () => {
expect(clampNumber(1.5, 1.0, 2.0)).toBe(1.5)
})

test('clampNumber(0, 0, 0) returns 0', () => {
expect(clampNumber(0, 0, 0)).toBe(0)
})

test('throws TypeError for non-number input', () => {
expect(() => clampNumber('5', 1, 10)).toThrow(TypeError)
})

test('throws TypeError for NaN', () => {
expect(() => clampNumber(NaN, 1, 10)).toThrow(TypeError)
})

test('throws RangeError when min > max', () => {
expect(() => clampNumber(5, 10, 1)).toThrow(RangeError)
})
})
Loading