UNPKG

mathjs

Version:

Math.js is an extensive math library for JavaScript and Node.js. It features a flexible expression parser with support for symbolic computation, comes with a large set of built-in functions and constants, and offers an integrated solution to work with dif

1,275 lines (1,119 loc) 31.4 kB
import { create, factory, all, MathJsFunctionName, fractionDependencies, addDependencies, divideDependencies, formatDependencies, MathNode, } from 'mathjs' import * as assert from 'assert' import { expectTypeOf } from 'expect-type' // This file serves a dual purpose: // 1) examples of how to use math.js in TypeScript // 2) tests for the TypeScript declarations provided by math.js /* Basic usage examples */ { const math = create(all) const m2by2 = [ [-1, 2], [3, 1], ] const m2by3 = [ [1, 2, 3], [4, 5, 6], ] // functions and constants math.round(math.e, 3) math.round(100.123, 3) math.atan2(3, -3) / math.pi math.log(10000, 10) math.sqrt(-4) math.pow(m2by2, 2) const angle = 0.2 math.add(math.pow(math.sin(angle), 2), math.pow(math.cos(angle), 2)) // std and variance check math.std(1, 2, 3) math.std([1, 2, 3]) math.std([1, 2, 3], 'biased') math.std([1, 2, 3], 0, 'biased') math.std(m2by3, 1, 'unbiased') math.std(m2by3, 1, 'uncorrected') math.variance(1, 2, 3) math.variance([1, 2, 3]) math.variance([1, 2, 3], 'biased') math.variance([1, 2, 3], 0, 'biased') math.variance(m2by3, 1, 'unbiased') math.variance(m2by3, 1, 'uncorrected') // std and variance on chain math.chain([1, 2, 3]).std('unbiased') math.chain(m2by3).std(0, 'biased').std(0, 'uncorrected') math.chain(m2by3).std(0, 'biased').std(0, 'uncorrected') math.chain([1, 2, 3]).std('unbiased') math.chain(m2by3).variance(0, 'biased') math.chain(m2by3).variance(1, 'uncorrected').variance('unbiased') // expressions math.evaluate('1.2 * (2 + 4.5)') // chained operations const a = math.chain(3).add(4).multiply(2).done() assert.strictEqual(a, 14) // mixed use of different data types in functions assert.deepStrictEqual(math.add(4, [5, 6]), [9, 10]) // number + Array assert.deepStrictEqual( math.multiply(math.unit('5 mm'), 3), math.unit('15 mm') ) // Unit * number assert.deepStrictEqual(math.subtract([2, 3, 4], 5), [-3, -2, -1]) // Array - number assert.deepStrictEqual( math.add(math.matrix([2, 3]), [4, 5]), math.matrix([6, 8]) ) // Matrix + Array // narrowed type inference const _b: math.Matrix = math.add(math.matrix([2]), math.matrix([3])) const _c: math.Matrix = math.subtract(math.matrix([4]), math.matrix([5])) } /* Bignumbers examples */ { // configure the default type of numbers as BigNumbers const math = create(all, { number: 'BigNumber', precision: 20, }) { assert.deepStrictEqual( math.add(math.bignumber(0.1), math.bignumber(0.2)), math.bignumber(0.3) ) assert.deepStrictEqual( math.divide(math.bignumber(0.3), math.bignumber(0.2)), math.bignumber(1.5) ) } } /* Chaining examples */ { const math = create(all, {}) const a = math.chain(3).add(4).multiply(2).done() assert.strictEqual(a, 14) // Another example, calculate square(sin(pi / 4)) const _b = math.chain(math.pi).divide(4).sin().square().done() // toString will return a string representation of the chain's value const chain = math.chain(2).divide(3) const str: string = chain.toString() assert.strictEqual(str, '0.6666666666666666') chain.valueOf() // the function subset can be used to get or replace sub matrices const array = [ [1, 2], [3, 4], ] const v = math.chain(array).subset(math.index(1, 0)).done() assert.strictEqual(v, 3) const _m = math.chain(array).subset(math.index(0, 0), 8).multiply(3).done() // filtering assert.deepStrictEqual( math .chain([-1, 0, 1.1, 2, 3, 1000]) .filter(math.isPositive) .filter(math.isInteger) .filter((n) => n !== 1000) .done(), [2, 3] ) const r = math.chain(-0.483).round([0, 1, 2]).floor().add(0.52).fix(1).done() assert.deepStrictEqual(r, [0.5, -0.4, -0.4]) expectTypeOf(math.chain('x + y').parse().resolve({ x: 1 }).done()) // eslint-disable-next-line @typescript-eslint/no-explicit-any .toMatchTypeOf<any>() expectTypeOf(math.chain('x + y').parse().resolve().done()) // eslint-disable-next-line @typescript-eslint/no-explicit-any .toMatchTypeOf<any>() } /* Simplify examples */ { const math = create(all) math.simplify('2 * 1 * x ^ (2 - 1)') math.simplify('2 * 3 * x', { x: 4 }) const f = math.parse('2 * 1 * x ^ (2 - 1)') math.simplify(f) math.simplify('0.4 * x', {}, { exactFractions: true }) math.simplify('0.4 * x', {}, { exactFractions: false }) } /* Complex numbers examples */ { const math = create(all, {}) const a = math.complex(2, 3) // create a complex number by providing a string with real and complex parts const b = math.complex('3 - 7i') // read the real and complex parts of the complex number { const _x: number = a.re const _y: number = a.im // adjust the complex value a.re = 5 } // clone a complex value { const _clone = a.clone() } // perform operations with complex numbers { math.add(a, b) math.multiply(a, b) math.sin(a) } // create a complex number from polar coordinates { const p: math.PolarCoordinates = { r: math.sqrt(2), phi: math.pi / 4 } const _c: math.Complex = math.complex(p) } // get polar coordinates of a complex number { const _p: math.PolarCoordinates = math.complex(3, 4).toPolar() } } /* Expressions examples */ { const math = create(all, {}) // evaluate expressions { math.evaluate('sqrt(3^2 + 4^2)') } // evaluate multiple expressions at once { math.evaluate(['f = 3', 'g = 4', 'f * g']) } // get content of a parenthesis node { const node = math.parse('(1)') if (node.type !== 'ParenthesisNode') { throw Error(`expected ParenthesisNode, got ${node.type}`) } const _innerNode = node.content } // scope can contain both variables and functions { const scope = { hello: (name: string) => `hello, ${name}!` } assert.strictEqual(math.evaluate('hello("hero")', scope), 'hello, hero!') } // define a function as an expression { // eslint-disable-next-line @typescript-eslint/no-explicit-any const scope: any = { a: 3, b: 4, } const f = math.evaluate('f(x) = x ^ a', scope) f(2) scope.f(2) } { const node2 = math.parse('x^a') const _code2: math.EvalFunction = node2.compile() node2.toString() } // 3. using function math.compile // parse an expression { // provide a scope for the variable assignment const code2 = math.compile('a = a + 3') const scope = { a: 7 } code2.evaluate(scope) } // 4. using a parser const parser = math.parser() // get and set variables and functions { assert.strictEqual(parser.evaluate('x = 7 / 2'), 3.5) assert.strictEqual(parser.evaluate('x + 3'), 6.5) parser.evaluate('f(x, y) = x^y') // f(x, y) assert.strictEqual(parser.evaluate('f(2, 3)'), 8) const _x = parser.get('x') const f = parser.get('f') const _y = parser.getAll() const _g = f(3, 3) parser.set('h', 500) parser.set('hello', (name: string) => `hello, ${name}!`) } // clear defined functions and variables parser.clear() } /* Fractions examples */ { // configure the default type of numbers as Fractions const math = create(all, { number: 'Fraction', }) const x = math.fraction(0.125) const y = math.fraction('1/3') math.fraction(2, 3) math.add(x, y) math.divide(x, y) // output formatting const _a = math.fraction('2/3') } /* Matrices examples */ { const math = create(all, {}) // create matrices and arrays. a matrix is just a wrapper around an Array, // providing some handy utilities. const a: math.Matrix = math.matrix([1, 4, 9, 16, 25]) const b: math.Matrix = math.matrix(math.ones([2, 3])) b.size() // the Array data of a Matrix can be retrieved using valueOf() const _array = a.valueOf() // Matrices can be cloned const _clone: math.Matrix = a.clone() // perform operations with matrices math.sqrt(a) math.factorial(a) // create and manipulate matrices. Arrays and Matrices can be used mixed. { const a = [ [1, 2], [3, 4], ] const b: math.Matrix = math.matrix([ [5, 6], [1, 1], ]) b.subset(math.index(1, [0, 1]), [[7, 8]]) const _c = math.multiply(a, b) const f: math.Matrix = math.matrix([1, 0]) const _d: math.Matrix = f.subset(math.index(1)) } // get a sub matrix { const a: math.Matrix = math.diag(math.range(1, 4)) a.subset(math.index([1, 2], [1, 2])) const b: math.Matrix = math.range(1, 6) b.subset(math.index(math.range(1, 4))) } // resize a multi dimensional matrix { const a = math.matrix() a.resize([2, 2, 2], 0) a.size() a.resize([2, 2]) a.size() } // can set a subset of a matrix to uninitialized { const m = math.matrix() m.subset(math.index(2), 6, math.uninitialized) } // create ranges { math.range(1, 6) math.range(0, 18, 3) math.range('2:-1:-3') math.factorial(math.range('1:6')) } // map matrix { assert.deepStrictEqual( math.map([1, 2, 3], function (value) { return value * value }), [1, 4, 9] ) } // filter matrix { assert.deepStrictEqual( math.filter([6, -2, -1, 4, 3], function (x) { return x > 0 }), [6, 4, 3] ) assert.deepStrictEqual( math.filter(['23', 'foo', '100', '55', 'bar'], /[0-9]+/), ['23', '100', '55'] ) } // concat matrix { assert.deepStrictEqual(math.concat([[0, 1, 2]], [[1, 2, 3]]), [ [0, 1, 2, 1, 2, 3], ]) assert.deepStrictEqual(math.concat([[0, 1, 2]], [[1, 2, 3]], 0), [ [0, 1, 2], [1, 2, 3], ]) } // Matrix is available as a constructor for instanceof checks { assert.strictEqual(math.matrix([1, 2, 3]) instanceof math.Matrix, true) } } /* Sparse matrices examples */ { const math = create(all, {}) // create a sparse matrix const a = math.identity(1000, 1000, 'sparse') // do operations with a sparse matrix const b = math.multiply(a, a) const _c = math.multiply(b, math.complex(2, 2)) const d = math.matrix([0, 1]) const e = math.transpose(d) const _f = math.multiply(e, d) } /* Units examples */ { const math = create(all, {}) // units can be created by providing a value and unit name, or by providing // a string with a valued unit. const a = math.unit(45, 'cm') // 450 mm const b = math.unit('0.1m') // 100 mm const _c = math.unit(b) // creating units math.createUnit('foo') math.createUnit('furlong', '220 yards') math.createUnit('furlong', '220 yards', { override: true }) math.createUnit('testunit', { definition: '0.555556 kelvin', offset: 459.67 }) math.createUnit( 'testunit', { definition: '0.555556 kelvin', offset: 459.67 }, { override: true } ) math.createUnit('knot', { definition: '0.514444 m/s', aliases: ['knots', 'kt', 'kts'], }) math.createUnit( 'knot', { definition: '0.514444 m/s', aliases: ['knots', 'kt', 'kts'] }, { override: true } ) math.createUnit( 'knot', { definition: '0.514444 m/s', aliases: ['knots', 'kt', 'kts'], prefixes: 'long', }, { override: true } ) math.createUnit( { foo2: { prefixes: 'long', }, bar: '40 foo', baz: { definition: '1 bar/hour', prefixes: 'long', }, }, { override: true, } ) // use Unit as definition math.createUnit('c', { definition: b }) math.createUnit('c', { definition: b }, { override: true }) // units can be added, subtracted, and multiplied or divided by numbers and by other units math.add(a, b) math.multiply(b, 2) math.divide(math.unit('1 m'), math.unit('1 s')) math.pow(math.unit('12 in'), 3) // units can be converted to a specific type, or to a number b.to('cm') math.to(b, 'inch') b.toNumber('cm') math.number(b, 'cm') // the expression parser supports units too math.evaluate('2 inch to cm') // units can be converted to SI math.unit('1 inch').toSI() // units can be split into other units math.unit('1 m').splitUnit(['ft', 'in']) } /* Expression tree examples */ { const math = create(all, {}) // Filter an expression tree const node: math.MathNode = math.parse('x^2 + x/4 + 3*y') const filtered: math.MathNode[] = node.filter( (node: math.MathNode) => node.type === 'SymbolNode' && node.name === 'x' ) const _arr: string[] = filtered.map((node: math.MathNode) => node.toString()) // Traverse an expression tree const node1: math.MathNode = math.parse('3 * x + 2') node1.traverse( (node: math.MathNode, _path: string, _parent: math.MathNode) => { switch (node.type) { case 'OperatorNode': return node.type === 'OperatorNode' case 'ConstantNode': return node.type === 'ConstantNode' case 'SymbolNode': return node.type === 'SymbolNode' default: return } } ) } /* Function ceil examples */ { const math = create(all, {}) // number input assert.strictEqual(math.ceil(3.2), 4) assert.strictEqual(math.ceil(-4.2), -4) // number input // roundoff result to 2 decimals assert.strictEqual(math.ceil(3.212, 2), 3.22) assert.deepStrictEqual( math.ceil(3.212, math.bignumber(2)), math.bignumber(3.22) ) assert.strictEqual(math.ceil(-4.212, 2), -4.21) // bignumber input assert.deepStrictEqual(math.ceil(math.bignumber(3.212)), math.bignumber(4)) assert.deepStrictEqual( math.ceil(math.bignumber(3.212), 2), math.bignumber(3.22) ) assert.deepStrictEqual( math.ceil(math.bignumber(3.212), math.bignumber(2)), math.bignumber(3.22) ) // fraction input assert.deepStrictEqual(math.ceil(math.fraction(44, 7)), math.fraction(7)) assert.deepStrictEqual(math.ceil(math.fraction(-44, 7)), math.fraction(-6)) assert.deepStrictEqual( math.ceil(math.fraction(44, 7), 2), math.fraction(629, 100) ) assert.deepStrictEqual( math.ceil(math.fraction(44, 7), math.bignumber(2)), math.fraction(629, 100) ) // Complex input const c = math.complex(3.24, -2.71) assert.deepStrictEqual(math.ceil(c), math.complex(4, -2)) assert.deepStrictEqual(math.ceil(c, 1), math.complex(3.3, -2.7)) assert.deepStrictEqual( math.ceil(c, math.bignumber(1)), math.complex(3.3, -2.7) ) // array input assert.deepStrictEqual(math.ceil([3.2, 3.8, -4.7]), [4, 4, -4]) assert.deepStrictEqual(math.ceil([3.21, 3.82, -4.71], 1), [3.3, 3.9, -4.7]) assert.deepStrictEqual( math.ceil([3.21, 3.82, -4.71], math.bignumber(1)), math.bignumber([3.3, 3.9, -4.7]) ) // numeric input, array or matrix of decimals const numCeiled: math.MathArray = math.ceil(math.tau, [2, 3]) assert.deepStrictEqual(numCeiled, [6.29, 6.284]) const bigCeiled: math.Matrix = math.ceil( math.bignumber(6.28318), math.matrix([2, 3]) ) assert.deepStrictEqual(bigCeiled, math.matrix(math.bignumber([6.29, 6.284]))) assert.deepStrictEqual(math.ceil(math.fraction(44, 7), [2, 3]), [ math.fraction(629, 100), math.fraction(6286, 1000), ]) // @ts-expect-error ... verify ceil(array, array) throws an error (for now) assert.throws(() => math.ceil([3.21, 3.82], [1, 2]), TypeError) } /* Function fix examples */ { const math = create(all, {}) // number input assert.strictEqual(math.fix(3.2), 3) assert.strictEqual(math.fix(-4.2), -4) // number input // roundoff result to 2 decimals assert.strictEqual(math.fix(3.212, 2), 3.21) assert.deepStrictEqual( math.fix(3.212, math.bignumber(2)), math.bignumber(3.21) ) assert.strictEqual(math.fix(-4.212, 2), -4.21) // bignumber input assert.deepStrictEqual(math.fix(math.bignumber(3.212)), math.bignumber(3)) assert.deepStrictEqual( math.fix(math.bignumber(3.212), 2), math.bignumber(3.21) ) assert.deepStrictEqual( math.fix(math.bignumber(3.212), math.bignumber(2)), math.bignumber(3.21) ) // fraction input assert.deepStrictEqual(math.fix(math.fraction(44, 7)), math.fraction(6)) assert.deepStrictEqual(math.fix(math.fraction(-44, 7)), math.fraction(-6)) assert.deepStrictEqual( math.fix(math.fraction(44, 7), 2), math.fraction(628, 100) ) assert.deepStrictEqual( math.fix(math.fraction(44, 7), math.bignumber(2)), math.fraction(628, 100) ) // Complex input const c = math.complex(3.24, -2.71) assert.deepStrictEqual(math.fix(c), math.complex(3, -2)) assert.deepStrictEqual(math.fix(c, 1), math.complex(3.2, -2.7)) assert.deepStrictEqual( math.fix(c, math.bignumber(1)), math.complex(3.2, -2.7) ) // array input assert.deepStrictEqual(math.fix([3.2, 3.8, -4.7]), [3, 3, -4]) assert.deepStrictEqual(math.fix([3.21, 3.82, -4.71], 1), [3.2, 3.8, -4.7]) assert.deepStrictEqual( math.fix([3.21, 3.82, -4.71], math.bignumber(1)), math.bignumber([3.2, 3.8, -4.7]) ) // numeric input, array or matrix of decimals const numFixed: math.MathArray = math.fix(math.tau, [2, 3]) assert.deepStrictEqual(numFixed, [6.28, 6.283]) const bigFixed: math.Matrix = math.fix( math.bignumber(6.28318), math.matrix([2, 3]) ) assert.deepStrictEqual(bigFixed, math.matrix(math.bignumber([6.28, 6.283]))) assert.deepStrictEqual(math.fix(math.fraction(44, 7), [2, 3]), [ math.fraction(628, 100), math.fraction(6285, 1000), ]) // @ts-expect-error ... verify fix(array, array) throws an error (for now) assert.throws(() => math.fix([3.21, 3.82], [1, 2]), TypeError) } /* Function floor examples */ { const math = create(all, {}) // number input assert.strictEqual(math.floor(3.2), 3) assert.strictEqual(math.floor(-4.2), -5) // number input // roundoff result to 2 decimals assert.strictEqual(math.floor(3.212, 2), 3.21) assert.deepStrictEqual( math.floor(3.212, math.bignumber(2)), math.bignumber(3.21) ) assert.strictEqual(math.floor(-4.212, 2), -4.22) // bignumber input assert.deepStrictEqual(math.floor(math.bignumber(3.212)), math.bignumber(3)) assert.deepStrictEqual( math.floor(math.bignumber(3.212), 2), math.bignumber(3.21) ) assert.deepStrictEqual( math.floor(math.bignumber(3.212), math.bignumber(2)), math.bignumber(3.21) ) // fraction input assert.deepStrictEqual(math.floor(math.fraction(44, 7)), math.fraction(6)) assert.deepStrictEqual(math.floor(math.fraction(-44, 7)), math.fraction(-7)) assert.deepStrictEqual( math.floor(math.fraction(44, 7), 2), math.fraction(628, 100) ) assert.deepStrictEqual( math.floor(math.fraction(44, 7), math.bignumber(2)), math.fraction(628, 100) ) // Complex input const c = math.complex(3.24, -2.71) assert.deepStrictEqual(math.floor(c), math.complex(3, -3)) assert.deepStrictEqual(math.floor(c, 1), math.complex(3.2, -2.8)) assert.deepStrictEqual( math.floor(c, math.bignumber(1)), math.complex(3.2, -2.8) ) // array input assert.deepStrictEqual(math.floor([3.2, 3.8, -4.7]), [3, 3, -5]) assert.deepStrictEqual(math.floor([3.21, 3.82, -4.71], 1), [3.2, 3.8, -4.8]) assert.deepStrictEqual( math.floor([3.21, 3.82, -4.71], math.bignumber(1)), math.bignumber([3.2, 3.8, -4.8]) ) // numeric input, array or matrix of decimals const numFloored: math.MathArray = math.floor(math.tau, [2, 3]) assert.deepStrictEqual(numFloored, [6.28, 6.283]) const bigFloored: math.Matrix = math.floor( math.bignumber(6.28318), math.matrix([2, 3]) ) assert.deepStrictEqual(bigFloored, math.matrix(math.bignumber([6.28, 6.283]))) assert.deepStrictEqual(math.floor(math.fraction(44, 7), [2, 3]), [ math.fraction(628, 100), math.fraction(6285, 1000), ]) // @ts-expect-error ... verify floor(array, array) throws an error (for now) assert.throws(() => math.floor([3.21, 3.82], [1, 2]), TypeError) } /* Function round examples */ { const math = create(all, {}) // number input assert.strictEqual(math.round(3.2), 3) assert.strictEqual(math.round(-4.2), -4) // number input // roundoff result to 2 decimals assert.strictEqual(math.round(3.212, 2), 3.21) assert.deepStrictEqual( math.round(3.212, math.bignumber(2)), math.bignumber(3.21) ) assert.strictEqual(math.round(-4.212, 2), -4.21) // bignumber input assert.deepStrictEqual(math.round(math.bignumber(3.212)), math.bignumber(3)) assert.deepStrictEqual( math.round(math.bignumber(3.212), 2), math.bignumber(3.21) ) assert.deepStrictEqual( math.round(math.bignumber(3.212), math.bignumber(2)), math.bignumber(3.21) ) // fraction input assert.deepStrictEqual(math.round(math.fraction(44, 7)), math.fraction(6)) assert.deepStrictEqual(math.round(math.fraction(-44, 7)), math.fraction(-6)) assert.deepStrictEqual( math.round(math.fraction(44, 7), 2), math.fraction(629, 100) ) assert.deepStrictEqual( math.round(math.fraction(44, 7), math.bignumber(2)), math.fraction(629, 100) ) // Complex input const c = math.complex(3.24, -2.71) assert.deepStrictEqual(math.round(c), math.complex(3, -3)) assert.deepStrictEqual(math.round(c, 1), math.complex(3.2, -2.7)) assert.deepStrictEqual( math.round(c, math.bignumber(1)), math.complex(3.2, -2.7) ) // array input assert.deepStrictEqual(math.round([3.2, 3.8, -4.7]), [3, 4, -5]) assert.deepStrictEqual(math.round([3.21, 3.82, -4.71], 1), [3.2, 3.8, -4.7]) assert.deepStrictEqual( math.round([3.21, 3.82, -4.71], math.bignumber(1)), math.bignumber([3.2, 3.8, -4.7]) ) // numeric input, array or matrix of decimals const numRounded: math.MathArray = math.round(math.tau, [2, 3]) assert.deepStrictEqual(numRounded, [6.28, 6.283]) const bigRounded: math.Matrix = math.round( math.bignumber(6.28318), math.matrix([2, 3]) ) assert.deepStrictEqual(bigRounded, math.matrix(math.bignumber([6.28, 6.283]))) assert.deepStrictEqual(math.round(math.fraction(44, 7), [2, 3]), [ math.fraction(629, 100), math.fraction(6286, 1000), ]) // @ts-expect-error ... verify round(array, array) throws an error (for now) assert.throws(() => math.round([3.21, 3.82], [1, 2]), TypeError) } /* JSON serialization/deserialization */ { const math = create(all, {}) const data = { bigNumber: math.bignumber('1.5'), } const stringified = JSON.stringify(data) const parsed = JSON.parse(stringified, math.reviver) assert.deepStrictEqual(parsed.bigNumber, math.bignumber('1.5')) } /* Extend functionality with import */ declare module 'mathjs' { interface MathJsStatic { testFun(): number value: number } } { const math = create(all, {}) const testFun = () => 5 math.import( { testFun, value: 10, }, {} ) math.testFun() expectTypeOf(math.testFun()).toMatchTypeOf<number>() expectTypeOf( math.import({ myvalue: 42, myFunc: (name: string) => `myFunc ${name}`, }) ).toMatchTypeOf<void>() expectTypeOf( math.import( { myvalue: 42, myFunc: (name: string) => `myFunc ${name}`, }, { override: true, } ) ).toMatchTypeOf<void>() expectTypeOf( math.import( { myvalue2: 42, }, { silent: true, } ) ).toMatchTypeOf<void>() expectTypeOf( math.import( { myvalue3: 42, }, { wrap: true, } ) ).toMatchTypeOf<void>() expectTypeOf( math.import({ myvalue4: 42, }) ).toMatchTypeOf<void>() expectTypeOf( math.import([ { myvalue5: 42, }, { myFunc2: (name: string) => `myFunc2 ${name}`, }, ]) ).toMatchTypeOf<void>() } /* Renamed functions from v5 => v6 */ { const math = create(all, {}) math.typeOf(1) math.variance([1, 2, 3, 4]) math.evaluate('1 + 2') // chained operations math.chain(3).typeOf().done() math.chain([1, 2, 3]).variance().done() math.chain('1 + 2').evaluate().done() } /* Factory Test */ { // create a factory function const name = 'negativeSquare' const dependencies: MathJsFunctionName[] = ['multiply', 'unaryMinus'] const createNegativeSquare = factory(name, dependencies, (injected) => { const { multiply, unaryMinus } = injected return function negativeSquare(x: number): number { return unaryMinus(multiply(x, x)) } }) // create an instance of the function yourself: const multiply = (a: number, b: number) => a * b const unaryMinus = (a: number) => -a const negativeSquare = createNegativeSquare({ multiply, unaryMinus }) negativeSquare(3) } /** * Dependency map typing test from mathjs official document: * https://mathjs.org/docs/custom_bundling.html#using-just-a-few-functions */ { const config = { // optionally, you can specify configuration } // Create just the functions we need const { fraction, add, divide, format } = create( { fractionDependencies, addDependencies, divideDependencies, formatDependencies, }, config ) // Use the created functions const a = fraction(1, 3) const b = fraction(3, 7) const c = add(a, b) const d = divide(a, b) assert.strictEqual(format(c), '16/21') assert.strictEqual(format(d), '7/9') } /** * Custom parsing functions * https://mathjs.org/docs/expressions/customization.html#customize-supported-characters */ { const math = create(all, {}) const isAlphaOriginal = math.parse.isAlpha math.parse.isAlpha = (c, cPrev, cNext) => { return isAlphaOriginal(c, cPrev, cNext) || c === '\u260E' } // now we can use the \u260E (phone) character in expressions const result = math.evaluate('\u260Efoo', { '\u260Efoo': 42 }) assert.strictEqual(result, 42) } /** * Util functions * https://mathjs.org/docs/reference/functions.html#utils-functions */ { const math = create(all, {}) // hasNumericValue function assert.strictEqual(math.hasNumericValue(2), true) assert.strictEqual(math.hasNumericValue('2'), true) assert.strictEqual(math.isNumeric('2'), false) assert.strictEqual(math.hasNumericValue(0), true) assert.strictEqual(math.hasNumericValue(math.bignumber(500)), true) assert.deepStrictEqual(math.hasNumericValue([2.3, 'foo', false]), [ true, false, true, ]) assert.strictEqual(math.hasNumericValue(math.fraction(4)), true) assert.strictEqual(math.hasNumericValue(math.complex('2-4i')), false) } /** * src/util/is functions */ { const math = create(all, {}) type IsFunc = (x: unknown) => boolean const isFuncs: IsFunc[] = [ math.isNumber, math.isBigNumber, math.isComplex, math.isFraction, math.isUnit, math.isString, math.isArray, math.isMatrix, math.isCollection, math.isDenseMatrix, math.isSparseMatrix, math.isRange, math.isIndex, math.isBoolean, math.isResultSet, math.isHelp, math.isFunction, math.isDate, math.isRegExp, math.isObject, math.isNull, math.isUndefined, math.isAccessorNode, math.isArrayNode, math.isAssignmentNode, math.isBlockNode, math.isConditionalNode, math.isConstantNode, math.isFunctionAssignmentNode, math.isFunctionNode, math.isIndexNode, math.isNode, math.isObjectNode, math.isOperatorNode, math.isParenthesisNode, math.isRangeNode, math.isSymbolNode, math.isChain, ] isFuncs.forEach((f) => { const result = f(1) const isResultBoolean = result === true || result === false assert.ok(isResultBoolean) }) // Check guards do type refinement let x: unknown if (math.isNumber(x)) { expectTypeOf(x).toMatchTypeOf<number>() } if (math.isBigNumber(x)) { expectTypeOf(x).toMatchTypeOf<math.BigNumber>() } if (math.isComplex(x)) { expectTypeOf(x).toMatchTypeOf<math.Complex>() } if (math.isFraction(x)) { expectTypeOf(x).toMatchTypeOf<math.Fraction>() } if (math.isUnit(x)) { expectTypeOf(x).toMatchTypeOf<math.Unit>() } if (math.isString(x)) { expectTypeOf(x).toMatchTypeOf<string>() } if (math.isArray(x)) { expectTypeOf(x).toMatchTypeOf<unknown[]>() } if (math.isMatrix(x)) { expectTypeOf(x).toMatchTypeOf<math.Matrix>() } if (math.isDenseMatrix(x)) { expectTypeOf(x).toMatchTypeOf<math.Matrix>() } if (math.isSparseMatrix(x)) { expectTypeOf(x).toMatchTypeOf<math.Matrix>() } if (math.isIndex(x)) { expectTypeOf(x).toMatchTypeOf<math.Index>() } if (math.isBoolean(x)) { expectTypeOf(x).toMatchTypeOf<boolean>() } if (math.isHelp(x)) { expectTypeOf(x).toMatchTypeOf<math.Help>() } if (math.isDate(x)) { expectTypeOf(x).toMatchTypeOf<Date>() } if (math.isRegExp(x)) { expectTypeOf(x).toMatchTypeOf<RegExp>() } if (math.isNull(x)) { expectTypeOf(x).toMatchTypeOf<null>() } if (math.isUndefined(x)) { expectTypeOf(x).toMatchTypeOf<undefined>() } if (math.isAccessorNode(x)) { expectTypeOf(x).toMatchTypeOf<math.AccessorNode>() } if (math.isArrayNode(x)) { expectTypeOf(x).toMatchTypeOf<math.ArrayNode>() } if (math.isAssignmentNode(x)) { expectTypeOf(x).toMatchTypeOf<math.AssignmentNode>() } if (math.isBlockNode(x)) { expectTypeOf(x).toMatchTypeOf<math.BlockNode>() } if (math.isConditionalNode(x)) { expectTypeOf(x).toMatchTypeOf<math.ConditionalNode>() } if (math.isConstantNode(x)) { expectTypeOf(x).toMatchTypeOf<math.ConstantNode>() } if (math.isFunctionAssignmentNode(x)) { expectTypeOf(x).toMatchTypeOf<math.FunctionAssignmentNode>() } if (math.isFunctionNode(x)) { expectTypeOf(x).toMatchTypeOf<math.FunctionNode>() } if (math.isIndexNode(x)) { expectTypeOf(x).toMatchTypeOf<math.IndexNode>() } if (math.isNode(x)) { expectTypeOf(x).toMatchTypeOf<math.MathNodeCommon>() } if (math.isNode(x)) { expectTypeOf(x).toMatchTypeOf<math.MathNodeCommon>() } if (math.isObjectNode(x)) { expectTypeOf(x).toMatchTypeOf<math.ObjectNode>() } if (math.isOperatorNode(x)) { expectTypeOf(x).toMatchTypeOf<math.OperatorNode>() } if (math.isParenthesisNode(x)) { expectTypeOf(x).toMatchTypeOf<math.ParenthesisNode>() } if (math.isRangeNode(x)) { expectTypeOf(x).toMatchTypeOf<math.RangeNode>() } if (math.isSymbolNode(x)) { expectTypeOf(x).toMatchTypeOf<math.SymbolNode>() } if (math.isChain(x)) { expectTypeOf(x).toMatchTypeOf<math.MathJsChain>() } } /* Probability function examples */ { const math = create(all, {}) expectTypeOf(math.lgamma(1.5)).toMatchTypeOf<number>() expectTypeOf( math.lgamma(math.complex(1.5, -1.5)) ).toMatchTypeOf<math.Complex>() } /* toTex examples */ { const math = create(all, {}) expectTypeOf(math.parse('a/b').toTex()).toMatchTypeOf<string>() // TODO add proper types for toTex options expectTypeOf( math.parse('a/b').toTex({ a: '123', }) ).toMatchTypeOf<string>() } /* Resolve examples */ { const math = create(all, {}) expectTypeOf(math.resolve(math.parse('x + y'))).toMatchTypeOf<MathNode>() expectTypeOf( math.resolve(math.parse('x + y'), { x: 0 }) ).toMatchTypeOf<MathNode>() expectTypeOf(math.resolve([math.parse('x + y')], { x: 0 })).toMatchTypeOf< MathNode[] >() }