/* MathJS v1.3.7 Last Modified: 04/06/2024
Author: Satyam Verma Description: A JavaScript library for basic and advanced arithmetic operations, Satistical functions, logical functions, factorial and fibonacci functions, random number functions, and trigonometric functions. Note: The author is not resposible fo accuracy of the results Repository: github.com/SatyamV7/MathJS License: MIT License */ /* Helper Functions */ function getUnits(str: string): string { str = str.toString(); const units = str.match(/(?!\b(pi|tau)\b)\b[a-z]+\b/gi); math.debuggingMode ? console.log('Units:', units) : null; return units ? units.join('') : ''; } function convertToRadians(n: string): number { //Convert the parameter to radians let num = math.evaluate(n.toString().replace(/(? p ? match : ''), {}) as number; switch (getUnits(n)) { case 'deg': case '': return num * Math.PI / 180; case 'grad': return num * Math.PI / 200; case 'rad': return num; default: throw new Error('Invalid Unit'); } } function validateAngle(Angle: number, Function: string): number { return ((Function === 'tan' || Function === 'sec') && (Angle === Math.PI / 2 || Angle === 3 * Math.PI / 2)) ? Number.POSITIVE_INFINITY : ((Function === 'cot' || Function === 'csc') && (Angle === 0 || Angle === Math.PI)) ? Number.POSITIVE_INFINITY : Angle; } const math = { // Debugging Mode debuggingMode: false, /* Mathematical Constants */ e: Math.E, PI: Math.PI, LN2: Math.LN2, LN10: Math.LN10, TAU: 2 * Math.PI, LOG2E: Math.LOG2E, LOG10E: Math.LOG10E, EPSILON: Number.EPSILON, PHI: (1 + Math.sqrt(5)) / 2, /* Basic Arithmetic Functions */ add: (...n: number[]): number => n.reduce((a, b) => a + b, 0), subtract: (...n: number[]): number => n.reduce((a, b) => a - b), multiply: (...n: number[]): number => n.reduce((a, b) => a * b), divide: (...n: number[]): number => n.reduce((a, b) => a / b), remainder: (...n: number[]): number => n.reduce((a, b) => a % b), /* Statistical Functions */ max: (...n: number[]): number => Math.max(...n), min: (...n: number[]): number => Math.min(...n), average: (...n: number[]): number => n.reduce((a, b) => a + b, 0) / n.length, mean: (...n: number[]): number => math.average(...n), median: (...n: number[]): number => { n.sort((a, b) => a - b); const mid = Math.floor(n.length / 2); return n.length % 2 !== 0 ? n[mid] : (n[mid - 1] + n[mid]) / 2; }, mode: (...n: (number | string | any)[]): string | any[] => { let returnType: 'Str' | 'Arr' = 'Str'; if (typeof n[n.length - 1] === 'string' && ['Str', 'Arr'].includes(n[n.length - 1] as string)) { returnType = n.pop() as 'Str' | 'Arr'; } const count: { [key: string]: number } = {}; const modes: any[] = []; let maxCount = 0; n.forEach(e => { const key = typeof e === 'string' ? `s_${e}` : e.toString(); count[key] = (count[key] || 0) + 1; if (count[key] > maxCount) { modes.splice(0, modes.length, e); maxCount = count[key]; } else if (count[key] === maxCount) { modes.push(e); } }); return returnType === 'Str' ? modes.map(e => typeof e === 'string' ? e : e.toString()).join(', ') : modes; }, range: (...n: (number | 'Str' | 'Arr')[]): string | number[] => { let returnType: 'Str' | 'Arr' = 'Str'; if (typeof n[n.length - 1] === 'string' && ['Str', 'Arr'].includes(n[n.length - 1] as string)) { returnType = n.pop() as 'Str' | 'Arr'; } const numbers = n.filter((item): item is number => typeof item === 'number'); const min = Math.min(...numbers); const max = Math.max(...numbers); const range: number[] = [min, max]; return returnType === 'Str' ? range.join(', ') : range; }, variance: (...n: number[]): number => { const mean = math.mean(...n); return math.mean(...n.map(e => math.square(e - mean))); }, standardDeviation: (...n: number[]): number => Math.sqrt(math.variance(...n)), /* Logical Functions */ isEqual: (a: number, b: number): boolean => a === b, isNearlyEqual: (a: number, b: number, epsilon: number = Number.EPSILON): boolean => Math.abs(a - b) < epsilon, isEven: (n: number): boolean => n % 2 === 0, isOdd: (n: number): boolean => n % 2 !== 0, isPositive: (n: number): boolean => n > 0, isNegative: (n: number): boolean => n < 0, isZero: (n: number): boolean => n === 0, isInteger: (n: number): boolean => Number.isInteger(n), isFloat: (n: number): boolean => Number(n) === n && n % 1 !== 0, isPrime: (n: number): boolean => { if (n === 2) { return true; } if (n === 1 || n % 2 === 0) { return false; } const sqrt = Math.sqrt(n); for (let i = 3; i <= sqrt; i += 2) { if (n % i === 0) { return false; } } return true; }, isComposite: (n: number): boolean => !math.isPrime(n), isDivisible: (n: number, d: number): boolean => n % d === 0, isPowerOf: (n: number, e: number): boolean => Math.log(n) / Math.log(e) % 1 === 0, isPerfectSquare: (n: number): boolean => Math.sqrt(n) % 1 === 0, isPerfectCube: (n: number): boolean => Math.cbrt(n) % 1 === 0, isPerfectPower: (n: number, b: number): boolean => Math.log(n) / Math.log(b) % 1 === 0, isMultiple: (n: number, m: number): boolean => n % m === 0, isFactor: (n: number, f: number): boolean => f % n === 0, isArmstrong: (n: number): boolean => n === n.toString().split('').reduce((a, b) => a + Math.pow(parseInt(b), n.toString().length), 0), isPalindrome: (n: number): boolean => n.toString() === n.toString().split('').reverse().join(''), isFinite: (n: number): boolean => Number.isFinite(n), isInfinite: (n: number): boolean => !Number.isFinite(n), /* Factorial and Fibonacci Functions */ factorial: (n: number): number => { if (n === 0) return 1; let factorial = 1; for (let i = 1; i <= n; i++) { factorial *= i; } return factorial; }, fibonacci: (n: number): number => { let a = 0, b = 1; for (let i = 2; i <= n; i++) { [a, b] = [b, a + b]; } return b; }, fibonacciSeries: (n: number, returnType: 'Str' | 'Arr' = 'Str'): string | number[] => { const series: number[] = Array.from({ length: n }, (_, i) => math.fibonacci(i)); return returnType === 'Str' ? series.join(', ') : series; }, /* Random Number Functions */ random: (a: number, b: number): number => Math.floor(Math.random() * (b - a + 1)) + a, /* Advanced Arithmetic Functions */ log: (n: number, b?: number): number => { if (b !== undefined) { const log = Math.log(n) / Math.log(b); return +log.toFixed(2); } const log = Math.log(n); return +log.toFixed(2); }, logBase2: (n: number): number => Math.log2(n), logBase5: (n: number): number => Math.log(n) / Math.log(5), logBase10: (n: number): number => Math.log10(n), square: (n: number): number => n ** 2, cube: (n: number): number => n ** 3, power: (n: number, e: number): number => n ** e, root: (n: number, e: number): number => n ** (1 / e), round: (n: number): number => Math.round(n), roundUp: (n: number): number => Math.ceil(n), roundDown: (n: number): number => Math.floor(n), absolute: (n: number): number => Math.abs(n), sqrt: (n: number): number => Math.sqrt(n), cbrt: (n: number): number => Math.cbrt(n), hypotenuse: (a: number, b: number): number => Math.hypot(a, b), factorsOf: (n: number, returnType: 'Str' | 'Arr' = 'Arr'): string | number[] => { const factors: number[] = []; for (let i = 1; i <= n; i++) { if (n % i === 0) { factors.push(i); } } return returnType === 'Str' ? factors.join(', ') : factors; }, primeFactorsOf: (n: number, returnType: 'Str' | 'Arr' = 'Arr'): string | number[] => { const primeFactors: number[] = []; for (let i = 2; i <= n; i++) { while (n % i === 0) { if (!primeFactors.includes(i)) { primeFactors.push(i); } n /= i; } } return returnType === 'Str' ? primeFactors.join(', ') : primeFactors; }, primeFactorizationOf: (n: number, returnType: 'Str' | 'Arr' = 'Arr'): string | number[] => { const factors: number[] = []; for (let i = 2; i <= Math.sqrt(n); i++) { while (n % i === 0) { factors.push(i); n /= i; } } if (n > 1) { factors.push(n); } return returnType === 'Str' ? factors.join(', ') : factors; }, greatestCommonDivisor: (...n: number[]): number => { const gcd = (x: number, y: number): number => (!y ? x : gcd(y, x % y)); return n.reduce((a, b) => gcd(a, b)); }, GCD: (...n: number[]): number => math.greatestCommonDivisor(...n), highestCommonFactor: (...n: number[]): number => math.greatestCommonDivisor(...n), HCF: (...n: number[]): number => math.greatestCommonDivisor(...n), leastCommonMultiple: (...n: number[]): number => { const hcf = (x: number, y: number): number => (!y ? x : hcf(y, x % y)); const lcm = (x: number, y: number): number => (x * y) / n.reduce((a, b) => hcf(a, b)); return n.reduce((a, b) => lcm(a, b)); }, LCM: (...n: number[]): number => math.leastCommonMultiple(...n), /* Trigonometric Functions */ sin: (n: string): number => { const angle = convertToRadians(n); const sine = Math.sin(angle); return +sine.toFixed(2); }, cos: (n: string): number => { const angle = convertToRadians(n); const cosine = Math.cos(angle); return +cosine.toFixed(2); }, tan: (n: string): number => { const angle = validateAngle(convertToRadians(n), 'tan'); const tangent = Math.tan(angle); return +tangent.toFixed(2); }, cot: (n: string): number => { const angle = validateAngle(convertToRadians(n), 'cot'); const cotangent = 1 / Math.tan(angle); return +cotangent.toFixed(2); }, sec: (n: string): number => { const angle = validateAngle(convertToRadians(n), 'sec'); const secant = 1 / Math.cos(angle); return +secant.toFixed(2); }, csc: (n: string): number => { const angle = validateAngle(convertToRadians(n), 'csc'); const cosecant = 1 / Math.sin(angle); return +cosecant.toFixed(2); }, /* Evaluate Function */ evaluate: (expression: string, variables: { [key: string]: number }) => { try { if (typeof expression !== 'string') { throw new Error('Expression must be a string'); } expression = expression.replace(/(\d)(?=[a-zA-Z])/g, '$1*'); if (variables) { for (let variable in variables) { const regex = new RegExp('\\b' + variable + '\\b', 'g'); expression = expression.replace(regex, variables[variable].toString()); } } expression = expression .replace(/\^/g, '**') .replace(/÷/g, '/') .replace(/×/g, '*') .replace(/\bpi\b/gi, 'PI') .replace(/\btau\b/gi, 'TAU'); for (let method in math) { if (method !== 'pi' && method !== 'tau') { const regex = new RegExp(`\\b${method}\\b`, 'g'); expression = expression.replace(regex, `math['${method}']`); } } const allowedCharactersRegex = /^[\d\s+\-*/()a-zA-Z"''\[\].,]+$/; for (let i = 0; i < expression.length; i++) { if (!allowedCharactersRegex.test(expression[i])) { throw new Error(`Expression contains disallowed character: ${expression[i]} at character position: ${i} in expression: ${expression}`); } } math.debuggingMode ? console.log('Expression:', expression) : null; return Function('math', `'use strict'; return (${expression})`)(math); } catch (error) { throw new Error('Error occurred while evaluating the expression: ' + error); } }, /* Chain Handler */ chain: (initialValue: number = 0): { [key: string]: Function } => { let result: number = initialValue; const chained: { [key: string]: Function } = {}; for (const method in math) { if (typeof math[method as keyof typeof math] === 'function' && method !== 'chain') { chained[method] = (...args: number[]) => { try { if (typeof result === 'number') { result = (math[method as keyof typeof math] as (...args: number[]) => number)(result, ...args); } } catch (error) { console.error(`Error executing method ${method}:`, error); } return chained; }; } } chained.result = () => { return result; }; if (typeof initialValue === 'number') { return chained; } else { throw new Error('Initial value must be a number'); } } }; // Export the math object for different environments declare var module: any; declare var exports: any; declare var define: { (id: string[], factory: () => any): void; amd: any; }; (function (root: any, factory: any) { if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define([], factory); } else if (typeof exports === 'object') { // Node. Does not work with strict CommonJS, but // only CommonJS-like environments that support module.exports, // like Node. module.exports = factory(); } else if (typeof module === 'object' && typeof module.exports === 'object') { // CommonJS and ES6 Modules module.exports = factory(); // This line is for CommonJS module.exports.default = factory(); // This line is for ES6 default import } else { // Browser globals (root is window) root.math = factory(); } }(typeof self !== 'undefined' ? self : this, function () { return math; }));