UNPKG

locutus

Version:

Locutus other languages' standard libraries to JavaScript for fun and educational purposes

76 lines (75 loc) 2.71 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.toRNumericArray = toRNumericArray; exports.toRNumber = toRNumber; exports.sortedRNumbers = sortedRNumbers; exports.medianOfSorted = medianOfSorted; exports.sampleVariance = sampleVariance; exports.sampleCovariance = sampleCovariance; function toRNumericArray(data, functionName) { if (!Array.isArray(data)) { throw new TypeError(`${functionName}() data must be an array`); } return data.map((value) => toRNumber(value, functionName)); } function toRNumber(value, functionName) { if (typeof value === 'number') { return value; } if (typeof value === 'boolean') { return value ? 1 : 0; } if (typeof value === 'bigint') { const numericValue = Number(value); if (!Number.isSafeInteger(numericValue)) { throw new RangeError(`${functionName}() bigint values must fit within JS safe integer precision`); } return numericValue; } throw new TypeError(`${functionName}() data must contain only numeric values`); } function sortedRNumbers(data, functionName) { return [...toRNumericArray(data, functionName)].sort((left, right) => left - right); } function medianOfSorted(values, low = false, high = false) { if (values.length === 0) { return Number.NaN; } const middle = Math.floor(values.length / 2); if (values.length % 2 === 1) { return values[middle] ?? Number.NaN; } if (low) { return values[middle - 1] ?? Number.NaN; } if (high) { return values[middle] ?? Number.NaN; } return ((values[middle - 1] ?? Number.NaN) + (values[middle] ?? Number.NaN)) / 2; } function sampleVariance(values) { if (values.length < 2) { return Number.NaN; } const mean = values.reduce((sum, value) => sum + value, 0) / values.length; const squaredDeltaSum = values.reduce((sum, value) => { const delta = value - mean; return sum + delta * delta; }, 0); return squaredDeltaSum / (values.length - 1); } function sampleCovariance(left, right, functionName) { if (left.length !== right.length) { throw new Error(`${functionName}() requires arrays with the same length`); } if (left.length < 2) { return Number.NaN; } const leftMean = left.reduce((sum, value) => sum + value, 0) / left.length; const rightMean = right.reduce((sum, value) => sum + value, 0) / right.length; let total = 0; for (let index = 0; index < left.length; index += 1) { total += ((left[index] ?? 0) - leftMean) * ((right[index] ?? 0) - rightMean); } return total / (left.length - 1); }