mathjs/types/index.ts
2022-07-25 10:02:52 +02:00

2245 lines
53 KiB
TypeScript

import {
AccessorNode,
addDependencies,
all,
ArrayNode,
AssignmentNode,
BigNumber,
BlockNode,
Complex,
ConditionalNode,
ConstantNode,
create,
divideDependencies,
EvalFunction,
factory,
formatDependencies,
Fraction,
fractionDependencies,
FunctionAssignmentNode,
FunctionNode,
Help,
Index,
IndexNode,
LUDecomposition,
MathArray,
MathCollection,
MathJsChain,
MathJsFunctionName,
MathNode,
MathNodeCommon,
MathNumericType,
MathType,
Matrix,
ObjectNode,
OperatorNode,
OperatorNodeFn,
OperatorNodeOp,
ParenthesisNode,
PolarCoordinates,
QRDecomposition,
RangeNode,
SimplifyRule,
SLUDecomposition,
SymbolNode,
Unit,
} 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')
math.variance(math.variance(m2by3, 'uncorrected'))
// count and sum check
math.count([10, 10, 10])
math.count([
[1, 2, 3],
[4, 5, 6],
])
math.count('mathjs')
math.sum(1, 2, 3, 4)
math.sum([1, 2, 3, 4])
math.sum([
[1, 2],
[3, 4],
[5, 6],
])
// 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: Matrix = math.add(math.matrix([2]), math.matrix([3]))
const _c: 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)
)
}
}
/*
Arithmetic function examples
*/
{
const math = create(all, {})
const _e: number = math.exp(1)
const _bige: BigNumber = math.exp(math.bignumber(1))
const _compe: Complex = math.exp(math.complex(1, 0))
// TODO: Typescript type declarations are not understanding typed-function's
// automatic conversions, so the following do not work:
// const _compeagain: Complex = math.exp(math.fraction(1, 1))
// const _eagain: number = math.exp('1')
// const _eanother: number = math.exp(true)
}
/*
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()
).toMatchTypeOf<MathNode>()
expectTypeOf(
math.chain('x + y').parse().resolve().done()
).toMatchTypeOf<MathNode>()
// bignum
expectTypeOf(math.chain(math.bignumber(12))).toMatchTypeOf<
MathJsChain<BigNumber>
>()
expectTypeOf(math.chain(12).bignumber()).toMatchTypeOf<
MathJsChain<BigNumber>
>()
expectTypeOf(math.chain([12, 13, 14]).bignumber()).toMatchTypeOf<
MathJsChain<MathCollection>
>()
// chain
expectTypeOf(math.chain(12).bignumber().clone()).toMatchTypeOf<
MathJsChain<BigNumber>
>()
// boolean
expectTypeOf(math.chain(math.boolean(true))).toMatchTypeOf<
MathJsChain<boolean>
>()
expectTypeOf(math.chain(true).boolean()).toMatchTypeOf<MathJsChain<boolean>>()
expectTypeOf(math.chain([12, 13, 14]).boolean()).toMatchTypeOf<
MathJsChain<MathCollection>
>()
// complex
expectTypeOf(math.chain(math.complex('123'))).toMatchTypeOf<
MathJsChain<Complex>
>()
expectTypeOf(math.chain('123').complex()).toMatchTypeOf<
MathJsChain<Complex>
>()
expectTypeOf(math.chain('123').complex(1)).toMatchTypeOf<
MathJsChain<Complex>
>()
expectTypeOf(math.chain([12, 13, 14]).complex()).toMatchTypeOf<
MathJsChain<MathCollection>
>()
// createUnit
expectTypeOf(math.chain(math.createUnit('furlong'))).toMatchTypeOf<
MathJsChain<Unit>
>()
expectTypeOf(
math.chain(
math.createUnit({
fresnel: '1234',
})
)
).toMatchTypeOf<MathJsChain<Unit>>()
// fraction
expectTypeOf(math.chain(math.fraction('123'))).toMatchTypeOf<
MathJsChain<Fraction>
>()
expectTypeOf(math.chain('123').fraction()).toMatchTypeOf<
MathJsChain<Fraction>
>()
expectTypeOf(math.chain('123').fraction(2)).toMatchTypeOf<
MathJsChain<Fraction>
>()
expectTypeOf(math.chain([12, 13, 14]).fraction()).toMatchTypeOf<
MathJsChain<MathCollection>
>()
expectTypeOf(math.chain([12, 13, 14]).fraction()).toMatchTypeOf<
MathJsChain<MathCollection>
>()
// index
expectTypeOf(math.chain([12, 13, 14]).index()).toMatchTypeOf<
MathJsChain<Index>
>()
// matrix
expectTypeOf(math.chain([12, 13, 14, 15]).matrix()).toMatchTypeOf<
MathJsChain<Matrix>
>()
// number
expectTypeOf(math.chain('12').number()).toMatchTypeOf<MathJsChain<number>>()
expectTypeOf(math.chain([12, 13, 14]).number()).toMatchTypeOf<
MathJsChain<MathCollection>
>()
// sparse
expectTypeOf(math.chain([12, 13, 14, 15]).sparse()).toMatchTypeOf<
MathJsChain<Matrix>
>()
// split unit
expectTypeOf(math.chain(math.unit('furlong')).splitUnit([])).toMatchTypeOf<
MathJsChain<Unit[]>
>()
// string
expectTypeOf(math.chain('test').string()).toMatchTypeOf<MathJsChain<string>>()
expectTypeOf(math.chain([1, 2, 3]).string()).toMatchTypeOf<
MathJsChain<MathCollection>
>()
// unit
expectTypeOf(math.chain(12).unit()).toMatchTypeOf<MathJsChain<Unit>>()
expectTypeOf(math.chain([1, 2, 3]).unit()).toMatchTypeOf<
MathJsChain<Unit[]>
>()
// compile
expectTypeOf(math.chain('a + b').compile()).toMatchTypeOf<
MathJsChain<EvalFunction>
>()
// evaluate
// eslint-disable-next-line @typescript-eslint/no-explicit-any
expectTypeOf(math.chain('1 + 1').evaluate()).toMatchTypeOf<MathJsChain<any>>()
expectTypeOf(math.chain(['1 + 1', '2 + 2']).evaluate()).toMatchTypeOf<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
MathJsChain<any[]>
>()
// parse
expectTypeOf(math.chain('1 + 1').parse()).toMatchTypeOf<
MathJsChain<MathNode>
>()
expectTypeOf(math.chain(['1 + 1', '2 + 2']).parse()).toMatchTypeOf<
MathJsChain<MathNode[]>
>()
// resolve
expectTypeOf(math.chain(math.parse('1 + 1')).resolve({})).toMatchTypeOf<
MathJsChain<MathNode>
>()
expectTypeOf(
math.chain([math.parse('1 + 1'), math.parse('1 + 1')]).resolve({})
).toMatchTypeOf<MathJsChain<MathNode[]>>()
// derivative
expectTypeOf(math.chain(math.parse('x^2')).derivative('x')).toMatchTypeOf<
MathJsChain<MathNode>
>()
// lsolve
expectTypeOf(
math
.chain([
[1, 2],
[3, 4],
])
.lsolve([1, 2])
).toMatchTypeOf<MathJsChain<MathArray>>()
expectTypeOf(
math
.chain(
math.matrix([
[1, 2],
[3, 4],
])
)
.lsolve([1, 2])
).toMatchTypeOf<MathJsChain<Matrix>>()
// lup
expectTypeOf(
math
.chain([
[1, 2],
[3, 4],
])
.lup()
).toMatchTypeOf<MathJsChain<LUDecomposition>>()
expectTypeOf(
math
.chain(
math.matrix([
[1, 2],
[3, 4],
])
)
.lup()
).toMatchTypeOf<MathJsChain<LUDecomposition>>()
// lusolve
expectTypeOf(
math
.chain(
math.matrix([
[1, 2],
[3, 4],
])
)
.lusolve(math.matrix([1, 2]))
).toMatchTypeOf<MathJsChain<Matrix>>()
expectTypeOf(
math
.chain(
math.matrix([
[1, 2],
[3, 4],
])
)
.lusolve([1, 2])
).toMatchTypeOf<MathJsChain<Matrix>>()
expectTypeOf(
math
.chain([
[1, 2],
[3, 4],
])
.lusolve(math.matrix([1, 2]))
).toMatchTypeOf<MathJsChain<MathArray>>()
expectTypeOf(
math
.chain([
[1, 2],
[3, 4],
])
.lusolve([1, 2])
).toMatchTypeOf<MathJsChain<MathArray>>()
// qr
expectTypeOf(
math
.chain([
[1, 2],
[3, 4],
])
.qr()
).toMatchTypeOf<MathJsChain<QRDecomposition>>()
expectTypeOf(
math
.chain(
math.matrix([
[1, 2],
[3, 4],
])
)
.qr()
).toMatchTypeOf<MathJsChain<QRDecomposition>>()
// rationalize
expectTypeOf(math.chain('1.23').rationalize()).toMatchTypeOf<
MathJsChain<MathNode>
>()
expectTypeOf(math.chain(math.parse('1.23')).rationalize()).toMatchTypeOf<
MathJsChain<MathNode>
>()
// simplify
expectTypeOf(math.chain('a + a + b').simplify()).toMatchTypeOf<
MathJsChain<MathNode>
>()
expectTypeOf(math.chain(math.parse('a + a + b')).simplify()).toMatchTypeOf<
MathJsChain<MathNode>
>()
// slu
expectTypeOf(
math
.chain(
math.sparse([
[1, 2],
[3, 4],
])
)
.slu(2, 0.5)
).toMatchTypeOf<MathJsChain<SLUDecomposition>>()
// usolve
expectTypeOf(
math
.chain([
[1, 2],
[3, 4],
])
.usolve([1, 2])
).toMatchTypeOf<MathJsChain<MathArray>>()
expectTypeOf(
math
.chain(
math.matrix([
[1, 2],
[3, 4],
])
)
.usolve([1, 2])
).toMatchTypeOf<MathJsChain<Matrix>>()
// abs
expectTypeOf(math.chain(1).abs()).toMatchTypeOf<MathJsChain<number>>()
expectTypeOf(math.chain(math.bignumber(1)).abs()).toMatchTypeOf<
MathJsChain<BigNumber>
>()
expectTypeOf(math.chain(math.fraction(1, 2)).abs()).toMatchTypeOf<
MathJsChain<Fraction>
>()
expectTypeOf(math.chain(math.complex(1, 2)).abs()).toMatchTypeOf<
MathJsChain<Complex>
>()
expectTypeOf(math.chain([1, 2]).abs()).toMatchTypeOf<MathJsChain<MathArray>>()
expectTypeOf(
math
.chain(
math.matrix([
[1, 2],
[3, 4],
])
)
.abs()
).toMatchTypeOf<MathJsChain<Matrix>>()
expectTypeOf(math.chain(math.unit('furlong')).abs()).toMatchTypeOf<
MathJsChain<Unit>
>()
// add
expectTypeOf(math.chain(1).add(2)).toMatchTypeOf<MathJsChain<MathType>>()
expectTypeOf(math.chain([1]).add(2)).toMatchTypeOf<MathJsChain<MathType>>()
expectTypeOf(
math.chain(
math.matrix([
[1, 2],
[3, 4],
])
)
).toMatchTypeOf<MathJsChain<Matrix>>()
// apply
expectTypeOf(math.chain([1, 2, 3]).apply(0, () => 1)).toMatchTypeOf<
MathJsChain<number[]>
>()
// cbrt
expectTypeOf(math.chain(1).cbrt()).toMatchTypeOf<MathJsChain<number>>()
expectTypeOf(math.chain(math.bignumber(1)).cbrt()).toMatchTypeOf<
MathJsChain<BigNumber>
>()
expectTypeOf(math.chain(math.complex(1, 2)).cbrt()).toMatchTypeOf<
MathJsChain<Complex>
>()
// @ts-expect-error ... verify cbrt does not run on arrays.
assert.throws(() => math.chain([1, 2]).cbrt(), TypeError)
assert.throws(
() =>
// @ts-expect-error ... verify cbrt does not run on matrices.
math
.chain(
math.matrix([
[1, 2],
[3, 4],
])
)
.cbrt(),
TypeError
)
// ceil
expectTypeOf(math.chain(1).ceil()).toMatchTypeOf<
MathJsChain<MathNumericType>
>()
expectTypeOf(math.chain([1]).ceil()).toMatchTypeOf<
MathJsChain<MathCollection>
>()
// fix
expectTypeOf(math.chain(1).fix()).toMatchTypeOf<
MathJsChain<MathNumericType>
>()
expectTypeOf(math.chain([1]).fix()).toMatchTypeOf<
MathJsChain<MathCollection>
>()
// floor
expectTypeOf(math.chain(1).floor()).toMatchTypeOf<
MathJsChain<MathNumericType>
>()
expectTypeOf(math.chain([1]).floor()).toMatchTypeOf<
MathJsChain<MathCollection>
>()
// round
expectTypeOf(math.chain(1).round()).toMatchTypeOf<
MathJsChain<MathNumericType>
>()
expectTypeOf(math.chain([1]).round()).toMatchTypeOf<
MathJsChain<MathCollection>
>()
// cube
expectTypeOf(math.chain(1).cube()).toMatchTypeOf<MathJsChain<number>>()
expectTypeOf(math.chain(math.bignumber(1)).cube()).toMatchTypeOf<
MathJsChain<BigNumber>
>()
expectTypeOf(math.chain(math.fraction(1, 2)).cube()).toMatchTypeOf<
MathJsChain<Fraction>
>()
expectTypeOf(math.chain(math.complex(1, 2)).cube()).toMatchTypeOf<
MathJsChain<Complex>
>()
// @ts-expect-error ... verify cube does not run on arrays.
assert.throws(() => math.chain([1, 2]).cube(), TypeError)
assert.throws(
() =>
// @ts-expect-error ... verify cube does not run on matrices.
math
.chain(
math.matrix([
[1, 2],
[3, 4],
])
)
.cube(),
TypeError
)
expectTypeOf(math.chain(math.unit('furlong')).cube()).toMatchTypeOf<
MathJsChain<Unit>
>()
// divide
expectTypeOf(
math.chain(math.unit('furlong')).divide(math.unit('femtosecond'))
).toMatchTypeOf<MathJsChain<number | Unit>>()
expectTypeOf(math.chain(math.unit('furlong')).divide(6)).toMatchTypeOf<
MathJsChain<Unit>
>()
expectTypeOf(math.chain(2).divide(6)).toMatchTypeOf<MathJsChain<number>>()
expectTypeOf(math.chain([1, 2, 3]).divide(6)).toMatchTypeOf<
MathJsChain<MathType>
>()
// dotDivide
expectTypeOf(math.chain(1).dotDivide(2)).toMatchTypeOf<
MathJsChain<MathType>
>()
expectTypeOf(
math
.chain(
math.matrix([
[1, 2],
[3, 4],
])
)
.dotDivide(2)
).toMatchTypeOf<MathJsChain<MathType>>()
// dotMultiply
expectTypeOf(math.chain(1).dotMultiply(2)).toMatchTypeOf<
MathJsChain<MathType>
>()
expectTypeOf(
math
.chain(
math.matrix([
[1, 2],
[3, 4],
])
)
.dotMultiply(2)
).toMatchTypeOf<MathJsChain<MathType>>()
// dotPow
expectTypeOf(math.chain(1).dotPow(2)).toMatchTypeOf<MathJsChain<MathType>>()
expectTypeOf(
math
.chain(
math.matrix([
[1, 2],
[3, 4],
])
)
.dotPow(2)
).toMatchTypeOf<MathJsChain<MathType>>()
// exp
expectTypeOf(math.chain(1).exp()).toMatchTypeOf<MathJsChain<MathType>>()
// @ts-expect-error ... verify exp does not run on arrays.
assert.throws(() => math.chain([1, 2]).exp(), TypeError)
assert.throws(
() =>
// @ts-expect-error ... verify exp does not run on matrices.
math
.chain(
math.matrix([
[1, 2],
[3, 4],
])
)
.exp(),
TypeError
)
// expm1
expectTypeOf(math.chain(1).expm1()).toMatchTypeOf<MathJsChain<MathType>>()
// @ts-expect-error ... verify expm1 does not run on arrays
assert.throws(() => math.chain([1, 2]).expm1(), TypeError)
assert.throws(
() =>
// @ts-expect-error ... verify expm1 does not run on arrays
math
.chain(
math.matrix([
[1, 2],
[3, 4],
])
)
.expm1(),
TypeError
)
// gcd
expectTypeOf(math.chain([1, 2]).gcd(3)).toMatchTypeOf<MathJsChain<number>>()
expectTypeOf(math.chain([1, 2]).gcd(3, 4)).toMatchTypeOf<
MathJsChain<number>
>()
// TODO make gcd() work in the following cases
// expectTypeOf(math.chain([1, 2]).gcd()).toMatchTypeOf<MathJsChain<number>>()
// expectTypeOf(math.chain([[1], [2]]).gcd()).toMatchTypeOf<
// MathJsChain<MathArray>
// >()
// expectTypeOf(
// math.chain([math.bignumber(1), math.bignumber(1)]).gcd()
// ).toMatchTypeOf<MathJsChain<BigNumber>>()
// expectTypeOf(
// math.chain([math.complex(1, 2), math.complex(1, 2)]).gcd()
// ).toMatchTypeOf<MathJsChain<Complex>>()
// expectTypeOf(
// math
// .chain(
// math.matrix([
// [1, 2],
// [3, 4],
// ])
// )
// .expm1()
// ).toMatchTypeOf<MathJsChain<Matrix>>()
// hypot
expectTypeOf(math.chain([1, 2]).hypot()).toMatchTypeOf<MathJsChain<number>>()
expectTypeOf(
math.chain([math.bignumber(1), math.bignumber(1)]).hypot()
).toMatchTypeOf<MathJsChain<BigNumber>>()
// lcm
expectTypeOf(math.chain(1).lcm(2)).toMatchTypeOf<MathJsChain<number>>()
expectTypeOf(
math.chain(math.bignumber(1)).lcm(math.bignumber(2))
).toMatchTypeOf<MathJsChain<BigNumber>>()
expectTypeOf(math.chain([1, 2]).lcm([3, 4])).toMatchTypeOf<
MathJsChain<MathArray>
>()
expectTypeOf(
math
.chain(
math.matrix([
[1, 2],
[3, 4],
])
)
.lcm(
math.matrix([
[1, 2],
[3, 4],
])
)
).toMatchTypeOf<MathJsChain<Matrix>>()
// log
expectTypeOf(math.chain(1).log(2)).toMatchTypeOf<MathJsChain<number>>()
expectTypeOf(
math.chain(math.bignumber(1)).log(math.bignumber(2))
).toMatchTypeOf<MathJsChain<BigNumber>>()
// log10
expectTypeOf(math.chain(1).log10()).toMatchTypeOf<MathJsChain<number>>()
expectTypeOf(math.chain(math.bignumber(1)).log10()).toMatchTypeOf<
MathJsChain<BigNumber>
>()
expectTypeOf(math.chain([1, 2]).log10()).toMatchTypeOf<
MathJsChain<MathArray>
>()
expectTypeOf(
math
.chain(
math.matrix([
[1, 2],
[3, 4],
])
)
.log10()
).toMatchTypeOf<MathJsChain<Matrix>>()
expectTypeOf(math.chain([1, 2]).count()).toMatchTypeOf<MathJsChain<number>>()
expectTypeOf(math.chain('mathjs').count()).toMatchTypeOf<
MathJsChain<number>
>()
expectTypeOf(math.chain([1, 2]).sum()).toMatchTypeOf<MathJsChain<number>>()
// TODO complete the rest of these...
}
/*
Simplify examples
*/
{
const math = create(all)
math.simplify('2 * 1 * x ^ (2 - 1)')
math.simplifyConstant('2 * 1 * x ^ (2 - 1)')
math.simplifyCore('2 * 1 * x ^ (2 - 1)')
math.simplify('2 * 3 * x', { x: 4 })
expectTypeOf(math.simplify.rules).toMatchTypeOf<Array<SimplifyRule>>()
const f = math.parse('2 * 1 * x ^ (2 - 1)')
math.simplify(f)
math.simplify('0.4 * x', {}, { exactFractions: true })
math.simplifyConstant('0.4 * x', { exactFractions: true })
math.simplify('0.4 * x', {}, { exactFractions: false })
math.simplify('0.4 * x', {}, { fractionsLimit: 2 })
math.simplify('0.4 * x', {}, { consoleDebug: false })
math.simplify(
'0.4 * x',
{},
{
context: {
xor: {
trivial: true,
total: true,
commutative: true,
associative: true,
},
},
}
)
math.simplify('0.4 * x', [])
math.simplify('0.4 * x', [
'n * n -> 2n',
{
s: 'n * n -> 2n',
repeat: true,
assuming: {
multiply: {
trivial: true,
total: true,
commutative: true,
associative: true,
},
},
imposeContext: {
multiply: {
trivial: true,
total: true,
commutative: true,
associative: true,
},
},
},
{
l: 'n * n',
r: '2n',
repeat: true,
assuming: {
multiply: {
trivial: true,
total: true,
commutative: true,
associative: true,
},
},
imposeContext: {
multiply: {
trivial: true,
total: true,
commutative: true,
associative: true,
},
},
},
(node: MathNode) => node,
])
math.simplifyCore('0.4 * x + 0', { exactFractions: false })
math
.chain('0.4 * x + 0')
.parse()
.simplifyCore({ exactFractions: false })
.simplifyConstant()
}
/*
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: PolarCoordinates = {
r: math.sqrt(2) as number, // must be real but a sqrt could be Complex
phi: math.pi / 4,
}
const c: Complex = math.complex(p)
assert.strictEqual(c.im, 1)
assert.ok(Math.abs(c.re - 1) < 1e-12)
}
// get polar coordinates of a complex number
{
const _p: PolarCoordinates = math.complex(3, 4).toPolar()
}
}
/*
Parenthesis examples
*/
{
const math = create(all, {})
expectTypeOf(
new math.ParenthesisNode(new math.ConstantNode(3))
).toMatchTypeOf<ParenthesisNode<ConstantNode>>()
}
/*
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: 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')
}
/*
Transform examples
*/
{
const math = create(all, {})
{
const myTransform1 = (node: MathNode): OperatorNode<'+', 'add'> =>
new OperatorNode('+', 'add', [node, new ConstantNode(1)])
const myTransform2 = (
node: OperatorNode<'+', 'add'>
): OperatorNode<'-', 'subtract'> =>
new OperatorNode('-', 'subtract', [node, new ConstantNode(5)])
expectTypeOf(
math.parse('sqrt(3^2 + 4^2)').transform(myTransform1)
).toMatchTypeOf<OperatorNode<'+', 'add', MathNode[]>>()
assert.deepStrictEqual(
math.parse('sqrt(3^2 + 4^2)').transform(myTransform1).toString(),
'sqrt(3 ^ 2 + 4 ^ 2) + 1'
)
expectTypeOf(
math
.parse('sqrt(3^2 + 4^2)')
.transform(myTransform1)
.transform(myTransform2)
).toMatchTypeOf<OperatorNode<'-', 'subtract', MathNode[]>>()
assert.deepStrictEqual(
math
.parse('sqrt(3^2 + 4^2)')
.transform(myTransform1)
.transform(myTransform2)
.toString(),
'sqrt(3 ^ 2 + 4 ^ 2) + 1 - 5'
)
}
}
/*
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: Matrix = math.matrix([1, 4, 9, 16, 25])
const b: Matrix = math.matrix(math.ones([2, 3]))
b.size()
// @ts-expect-error ... ones() in a chain cannot take more dimensions
assert.throws(() => math.chain(3).ones(2, 'dense').done(), /Error:.*ones/)
// @ts-expect-error ... and neither can zeros()
assert.throws(() => math.chain(3).zeros(2, 'sparse').done(), /Error:.*zeros/)
// the Array data of a Matrix can be retrieved using valueOf()
const _array = a.valueOf()
// Matrices can be cloned
const _clone: Matrix = a.clone()
// perform operations with matrices
math.map(a, math.sqrt)
math.factorial(a)
// create and manipulate matrices. Arrays and Matrices can be used mixed.
{
const a = [
[1, 2],
[3, 4],
]
const b: Matrix = math.matrix([
[5, 6],
[1, 1],
])
b.subset(math.index(1, [0, 1]), [[7, 8]])
const _c = math.multiply(a, b)
const f: Matrix = math.matrix([1, 0])
const _d: Matrix = f.subset(math.index(1))
}
// get a sub matrix
{
const a: Matrix = math.diag(math.range(1, 4))
a.subset(math.index([1, 2], [1, 2]))
const b: 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'], /\d+/),
['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)
}
// Fourier transform and inverse
{
assert.ok(
math.deepEqual(
math.fft([
[1, 0],
[1, 0],
]),
[
[math.complex(2, 0), math.complex(2, 0)],
[math.complex(0, 0), math.complex(0, 0)],
]
)
)
assert.ok(
math.deepEqual(
math.fft(
math.matrix([
[1, 0],
[1, 0],
])
),
math.matrix([
[math.complex(2, 0), math.complex(2, 0)],
[math.complex(0, 0), math.complex(0, 0)],
])
)
)
assert.ok(
math.deepEqual(
math.ifft([
[2, 2],
[0, 0],
]),
[
[math.complex(1, 0), math.complex(0, 0)],
[math.complex(1, 0), math.complex(0, 0)],
]
)
)
assert.ok(
math.deepEqual(
math.ifft(
math.matrix([
[2, 2],
[0, 0],
])
),
math.matrix([
[math.complex(1, 0), math.complex(0, 0)],
[math.complex(1, 0), math.complex(0, 0)],
])
)
)
}
}
/*
Math types examples: Type results after multiplying 'MathTypes' with matrices
*/
{
const math = create(all, {})
const abc: MathArray = [1, 2, 3, 4]
const bcd: MathArray = [
[1, 2, 3, 4],
[2, 3, 4, 5],
[4, 5, 6, 7],
[5, 6, 7, 8],
]
const Mbcd = math.matrix(bcd)
const Mabc = math.matrix(abc)
// Number
const _r1 = math.multiply(1, 2)
// Unit
const a = math.unit(45, 'cm') // 450 mm
const b = math.unit(45, 'cm') // 450 mm
const _r2 = math.multiply(a, b)
// 1D JS Array
const r3 = math.multiply(abc, bcd)
const _r31 = r3[1] // By default least promised valid syntax
// 2D JS Array
const r12 = math.multiply(bcd, bcd)
// Example to sort ambiguity between multidimensional & singledimensional arrays
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const multiDimensional = (x: any): x is any[][] => x.length && x[0].length
if (multiDimensional(r12)) {
const _r1211 = r12[1][1]
}
const _r121 = r12[1] // Valid syntax
// Matrix: matrix * vector
const r7 = math.multiply(Mabc, bcd)
r7.toArray() // Matrix-es have toArray function
// Matrix
const _r8 = math.multiply(Mabc, 4)
// Matrix
const _r11 = math.multiply(4, Mabc)
// Matrix of units
const _r9 = math.multiply(Mabc, a)
const _r10 = math.multiply(a, Mabc)
// Matrix
const _r6 = math.multiply(abc, Mbcd)
// 2D JS Array
const _r5 = math.multiply(bcd, abc)
// Number
const _r4 = math.multiply(abc, math.transpose(abc))
}
/*
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 })
math.createUnit('customUnit', math.unit(0.5, 'm'))
// 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: MathNode = math.parse('x^2 + x/4 + 3*y')
const filtered: MathNode[] = node.filter(
(node: MathNode) => node.type === 'SymbolNode' && node.name === 'x'
)
const _arr: string[] = filtered.map((node: MathNode) => node.toString())
// Traverse an expression tree
const node1: MathNode = math.parse('3 * x + 2')
node1.traverse((node: MathNode, _path: string, _parent: 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: MathArray = math.ceil(math.tau, [2, 3])
assert.deepStrictEqual(numCeiled, [6.29, 6.284])
const bigCeiled: 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: MathArray = math.fix(math.tau, [2, 3])
assert.deepStrictEqual(numFixed, [6.28, 6.283])
const bigFixed: 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: MathArray = math.floor(math.tau, [2, 3])
assert.deepStrictEqual(numFloored, [6.28, 6.283])
const bigFloored: 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: MathArray = math.round(math.tau, [2, 3])
assert.deepStrictEqual(numRounded, [6.28, 6.283])
const bigRounded: 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)
}
/*
Clone examples
*/
{
const math = create(all, {})
expectTypeOf(
new math.OperatorNode('/', 'divide', [
new math.ConstantNode(3),
new math.SymbolNode('x'),
])
).toMatchTypeOf<OperatorNode<'/', 'divide', (ConstantNode | SymbolNode)[]>>()
expectTypeOf(new math.ConstantNode(1).clone()).toMatchTypeOf<ConstantNode>()
expectTypeOf(
new math.OperatorNode('*', 'multiply', [
new math.ConstantNode(3),
new math.SymbolNode('x'),
]).clone()
).toMatchTypeOf<
OperatorNode<'*', 'multiply', (ConstantNode | SymbolNode)[]>
>()
expectTypeOf(
new math.ConstantNode(1).cloneDeep()
).toMatchTypeOf<ConstantNode>()
expectTypeOf(
new math.OperatorNode('+', 'unaryPlus', [
new math.ConstantNode(3),
new math.SymbolNode('x'),
]).cloneDeep()
).toMatchTypeOf<
OperatorNode<'+', 'unaryPlus', (ConstantNode | SymbolNode)[]>
>()
expectTypeOf(
math.clone(new math.ConstantNode(1))
).toMatchTypeOf<ConstantNode>()
}
/*
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
const x: unknown = undefined
if (math.isNumber(x)) {
expectTypeOf(x).toMatchTypeOf<number>()
}
if (math.isBigNumber(x)) {
expectTypeOf(x).toMatchTypeOf<BigNumber>()
}
if (math.isComplex(x)) {
expectTypeOf(x).toMatchTypeOf<Complex>()
}
if (math.isFraction(x)) {
expectTypeOf(x).toMatchTypeOf<Fraction>()
}
if (math.isUnit(x)) {
expectTypeOf(x).toMatchTypeOf<Unit>()
}
if (math.isString(x)) {
expectTypeOf(x).toMatchTypeOf<string>()
}
if (math.isArray(x)) {
expectTypeOf(x).toMatchTypeOf<unknown[]>()
}
if (math.isMatrix(x)) {
expectTypeOf(x).toMatchTypeOf<Matrix>()
}
if (math.isDenseMatrix(x)) {
expectTypeOf(x).toMatchTypeOf<Matrix>()
}
if (math.isSparseMatrix(x)) {
expectTypeOf(x).toMatchTypeOf<Matrix>()
}
if (math.isIndex(x)) {
expectTypeOf(x).toMatchTypeOf<Index>()
}
if (math.isBoolean(x)) {
expectTypeOf(x).toMatchTypeOf<boolean>()
}
if (math.isHelp(x)) {
expectTypeOf(x).toMatchTypeOf<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<AccessorNode>()
}
if (math.isArrayNode(x)) {
expectTypeOf(x).toMatchTypeOf<ArrayNode>()
}
if (math.isAssignmentNode(x)) {
expectTypeOf(x).toMatchTypeOf<AssignmentNode>()
}
if (math.isBlockNode(x)) {
expectTypeOf(x).toMatchTypeOf<BlockNode>()
}
if (math.isConditionalNode(x)) {
expectTypeOf(x).toMatchTypeOf<ConditionalNode>()
}
if (math.isConstantNode(x)) {
expectTypeOf(x).toMatchTypeOf<ConstantNode>()
}
if (math.isFunctionAssignmentNode(x)) {
expectTypeOf(x).toMatchTypeOf<FunctionAssignmentNode>()
}
if (math.isFunctionNode(x)) {
expectTypeOf(x).toMatchTypeOf<FunctionNode>()
}
if (math.isIndexNode(x)) {
expectTypeOf(x).toMatchTypeOf<IndexNode>()
}
if (math.isNode(x)) {
expectTypeOf(x).toMatchTypeOf<MathNodeCommon>()
}
if (math.isNode(x)) {
expectTypeOf(x).toMatchTypeOf<MathNodeCommon>()
}
if (math.isObjectNode(x)) {
expectTypeOf(x).toMatchTypeOf<ObjectNode>()
}
if (math.isOperatorNode(x)) {
expectTypeOf(x).toMatchTypeOf<
OperatorNode<OperatorNodeOp, OperatorNodeFn, MathNode[]>
>()
}
if (math.isParenthesisNode(x)) {
expectTypeOf(x).toMatchTypeOf<ParenthesisNode>()
}
if (math.isRangeNode(x)) {
expectTypeOf(x).toMatchTypeOf<RangeNode>()
}
if (math.isSymbolNode(x)) {
expectTypeOf(x).toMatchTypeOf<SymbolNode>()
}
if (math.isChain(x)) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
expectTypeOf(x).toMatchTypeOf<MathJsChain<any>>()
}
}
/*
Probability function examples
*/
{
const math = create(all, {})
expectTypeOf(math.lgamma(1.5)).toMatchTypeOf<number>()
expectTypeOf(math.lgamma(math.complex(1.5, -1.5))).toMatchTypeOf<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('x + y')).toMatchTypeOf<MathNode>()
expectTypeOf(math.resolve(math.parse('x + y'))).toMatchTypeOf<MathNode>()
expectTypeOf(
math.resolve(math.parse('x + y'), { x: 0 })
).toMatchTypeOf<MathNode>()
expectTypeOf(math.resolve('x + y', { x: 0 })).toMatchTypeOf<MathNode>()
expectTypeOf(
math.resolve([math.parse('x + y'), 'x*x'], { x: 0 })
).toMatchTypeOf<MathNode[]>()
expectTypeOf(math.resolve(math.matrix(['x', 'y']))).toMatchTypeOf<Matrix>()
}