From 47c7166460a9809108fe6f3cd9b513401391a8bd Mon Sep 17 00:00:00 2001 From: Glen Whitney Date: Thu, 17 Mar 2022 09:53:21 -0700 Subject: [PATCH] chore: Prevent confusion with standard matrix functions. (#2465) * chore: Prevent consfusion with standard matrix functions. Prior to this commit, many functions operated elementwise on matrices even though in standard mathematical usage they have a different meaning on square matrices. Since the elementwise operation is easily recoverable using `math.map`, this commit removes the elementwise operation on arrays and matrices from these functions. Affected functions include all trigonometric functions, exp, log, gamma, square, sqrt, cube, and cbrt. Resolves #2440. * chore(typescript): Revise usages in light of changes sqrt() is now correctly typed as `number | Complex` and so must be explicitly cast to number when called on a positive and used where a Complex is disallowed; sqrt() no longer applies to matrices at all. * feat: Provide better error messages for v10 -> v11 transition Uses new `typed.onMismatch` handler so that matrix calls that used to work will suggest a replacement. --- src/core/function/typed.js | 20 ++ src/expression/transform/std.transform.js | 6 +- src/function/arithmetic/cbrt.js | 18 +- src/function/arithmetic/cube.js | 15 +- src/function/arithmetic/exp.js | 20 +- src/function/arithmetic/expm1.js | 20 +- src/function/arithmetic/log.js | 12 +- src/function/arithmetic/sqrt.js | 14 +- src/function/arithmetic/square.js | 16 +- src/function/matrix/sqrtm.js | 6 +- src/function/probability/gamma.js | 12 +- src/function/probability/kldivergence.js | 6 +- src/function/statistics/std.js | 13 +- src/function/trigonometry/acos.js | 12 +- src/function/trigonometry/acosh.js | 9 +- src/function/trigonometry/acot.js | 12 +- src/function/trigonometry/acoth.js | 12 +- src/function/trigonometry/acsc.js | 12 +- src/function/trigonometry/acsch.js | 12 +- src/function/trigonometry/asec.js | 12 +- src/function/trigonometry/asech.js | 12 +- src/function/trigonometry/asin.js | 13 +- src/function/trigonometry/asinh.js | 13 +- src/function/trigonometry/atan.js | 13 +- src/function/trigonometry/atanh.js | 13 +- src/function/trigonometry/cos.js | 12 +- src/function/trigonometry/cosh.js | 12 +- src/function/trigonometry/cot.js | 8 +- src/function/trigonometry/coth.js | 12 +- src/function/trigonometry/csc.js | 12 +- src/function/trigonometry/csch.js | 12 +- src/function/trigonometry/sec.js | 12 +- src/function/trigonometry/sech.js | 12 +- src/function/trigonometry/sin.js | 13 +- src/function/trigonometry/sinh.js | 13 +- src/function/trigonometry/tan.js | 13 +- src/function/trigonometry/tanh.js | 13 +- src/type/matrix/DenseMatrix.js | 11 +- src/type/matrix/SparseMatrix.js | 4 + .../treeShaking/treeShaking.test.js | 1 + .../function/algebra/derivative.test.js | 2 +- .../function/algebra/simplify.test.js | 2 +- .../function/arithmetic/cbrt.test.js | 10 +- .../function/arithmetic/cube.test.js | 12 +- .../function/arithmetic/exp.test.js | 14 +- .../function/arithmetic/expm1.test.js | 15 +- .../function/arithmetic/log.test.js | 9 +- .../function/arithmetic/sqrt.test.js | 9 +- .../function/arithmetic/square.test.js | 9 +- .../function/probability/gamma.test.js | 10 +- .../function/trigonometry/acos.test.js | 7 +- .../function/trigonometry/acosh.test.js | 8 +- .../function/trigonometry/acot.test.js | 8 +- .../function/trigonometry/acoth.test.js | 8 +- .../function/trigonometry/acsc.test.js | 8 +- .../function/trigonometry/acsch.test.js | 8 +- .../function/trigonometry/asec.test.js | 8 +- .../function/trigonometry/asech.test.js | 8 +- .../function/trigonometry/asin.test.js | 8 +- .../function/trigonometry/asinh.test.js | 8 +- .../function/trigonometry/atan.test.js | 8 +- .../function/trigonometry/atanh.test.js | 8 +- .../function/trigonometry/cos.test.js | 10 +- .../function/trigonometry/cosh.test.js | 10 +- .../function/trigonometry/cot.test.js | 10 +- .../function/trigonometry/coth.test.js | 10 +- .../function/trigonometry/csc.test.js | 10 +- .../function/trigonometry/csch.test.js | 10 +- .../function/trigonometry/sec.test.js | 10 +- .../function/trigonometry/sech.test.js | 10 +- .../function/trigonometry/sin.test.js | 10 +- .../function/trigonometry/sinh.test.js | 10 +- .../function/trigonometry/tan.test.js | 10 +- .../function/trigonometry/tanh.test.js | 10 +- types/index.d.ts | 174 ++++++------------ types/index.ts | 11 +- 76 files changed, 440 insertions(+), 535 deletions(-) diff --git a/src/core/function/typed.js b/src/core/function/typed.js index 70d8518c2a..ef410f3ea5 100644 --- a/src/core/function/typed.js +++ b/src/core/function/typed.js @@ -45,6 +45,7 @@ import { isBlockNode, isBoolean, isChain, + isCollection, isComplex, isConditionalNode, isConstantNode, @@ -332,6 +333,25 @@ export const createTyped = /* #__PURE__ */ factory('typed', dependencies, functi } ] + // Provide a suggestion on how to call a function elementwise + // This was added primarily as guidance for the v10 -> v11 transition, + // and could potentially be removed in the future if it no longer seems + // to be helpful. + typed.onMismatch = (name, args, signatures) => { + const usualError = typed.createError(name, args, signatures) + if (['wrongType', 'mismatch'].includes(usualError.data.category) && + args.length === 1 && isCollection(args[0]) && + // check if the function can be unary: + signatures.some(sig => !sig.params.includes(','))) { + const err = new TypeError( + `Function '${name}' doesn't apply to matrices. To call it ` + + `elementwise on a matrix 'M', try 'map(M, ${name})'.`) + err.data = usualError.data + throw err + } + throw usualError + } + return typed }) diff --git a/src/expression/transform/std.transform.js b/src/expression/transform/std.transform.js index 4f2988c09f..6c92efdad4 100644 --- a/src/expression/transform/std.transform.js +++ b/src/expression/transform/std.transform.js @@ -4,7 +4,7 @@ import { errorTransform } from './utils/errorTransform.js' import { lastDimToZeroBase } from './utils/lastDimToZeroBase.js' const name = 'std' -const dependencies = ['typed', 'sqrt', 'variance'] +const dependencies = ['typed', 'map', 'sqrt', 'variance'] /** * Attach a transform function to math.std @@ -13,8 +13,8 @@ const dependencies = ['typed', 'sqrt', 'variance'] * This transform changed the `dim` parameter of function std * from one-based to zero based */ -export const createStdTransform = /* #__PURE__ */ factory(name, dependencies, ({ typed, sqrt, variance }) => { - const std = createStd({ typed, sqrt, variance }) +export const createStdTransform = /* #__PURE__ */ factory(name, dependencies, ({ typed, map, sqrt, variance }) => { + const std = createStd({ typed, map, sqrt, variance }) return typed('std', { '...any': function (args) { diff --git a/src/function/arithmetic/cbrt.js b/src/function/arithmetic/cbrt.js index 1d90caa8cf..ae71eca054 100644 --- a/src/function/arithmetic/cbrt.js +++ b/src/function/arithmetic/cbrt.js @@ -1,6 +1,5 @@ import { factory } from '../../utils/factory.js' import { isBigNumber, isComplex, isFraction } from '../../utils/is.js' -import { deepMap } from '../../utils/collection.js' import { cbrtNumber } from '../../plain/number/index.js' const name = 'cbrt' @@ -19,7 +18,9 @@ export const createCbrt = /* #__PURE__ */ factory(name, dependencies, ({ config, /** * Calculate the cubic root of a value. * - * For matrices, the function is evaluated element wise. + * To avoid confusion with the matrix cube root, this function does not + * apply to matrices. For a matrix, to take the cube root elementwise, + * see the examples. * * Syntax: * @@ -32,7 +33,7 @@ export const createCbrt = /* #__PURE__ */ factory(name, dependencies, ({ config, * math.cube(3) // returns 27 * math.cbrt(-64) // returns -4 * math.cbrt(math.unit('27 m^3')) // returns Unit 3 m - * math.cbrt([27, 64, 125]) // returns [3, 4, 5] + * math.map([27, 64, 125], x => math.cbrt(x)) // returns [3, 4, 5] * * const x = math.complex('8i') * math.cbrt(x) // returns Complex 1.7320508075689 + i @@ -46,13 +47,13 @@ export const createCbrt = /* #__PURE__ */ factory(name, dependencies, ({ config, * * square, sqrt, cube * - * @param {number | BigNumber | Complex | Unit | Array | Matrix} x + * @param {number | BigNumber | Complex | Unit} x * Value for which to calculate the cubic root. * @param {boolean} [allRoots] Optional, false by default. Only applicable * when `x` is a number or complex number. If true, all complex * roots are returned, if false (default) the principal root is * returned. - * @return {number | BigNumber | Complex | Unit | Array | Matrix} + * @return {number | BigNumber | Complex | Unit} * Returns the cubic root of `x` */ return typed(name, { @@ -68,12 +69,7 @@ export const createCbrt = /* #__PURE__ */ factory(name, dependencies, ({ config, return x.cbrt() }, - Unit: _cbrtUnit, - - 'Array | Matrix': function (x) { - // deep map collection, skip zeros since cbrt(0) = 0 - return deepMap(x, this, true) - } + Unit: _cbrtUnit }) /** diff --git a/src/function/arithmetic/cube.js b/src/function/arithmetic/cube.js index 22814a78a9..87ddbe1c98 100644 --- a/src/function/arithmetic/cube.js +++ b/src/function/arithmetic/cube.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' import { cubeNumber } from '../../plain/number/index.js' const name = 'cube' @@ -8,7 +7,8 @@ const dependencies = ['typed'] export const createCube = /* #__PURE__ */ factory(name, dependencies, ({ typed }) => { /** * Compute the cube of a value, `x * x * x`. - * For matrices, the function is evaluated element wise. + * To avoid confusion with `pow(M,3)`, this function does not apply to matrices. + * If you wish to cube every entry of a matrix, see the examples. * * Syntax: * @@ -21,14 +21,14 @@ export const createCube = /* #__PURE__ */ factory(name, dependencies, ({ typed } * math.cube(4) // returns number 64 * 4 * 4 * 4 // returns number 64 * - * math.cube([1, 2, 3, 4]) // returns Array [1, 8, 27, 64] + * math.map([1, 2, 3, 4], math.cube) // returns Array [1, 8, 27, 64] * * See also: * * multiply, square, pow, cbrt * - * @param {number | BigNumber | Fraction | Complex | Array | Matrix | Unit} x Number for which to calculate the cube - * @return {number | BigNumber | Fraction | Complex | Array | Matrix | Unit} Cube of x + * @param {number | BigNumber | Fraction | Complex | Unit} x Number for which to calculate the cube + * @return {number | BigNumber | Fraction | Complex | Unit} Cube of x */ return typed(name, { number: cubeNumber, @@ -45,11 +45,6 @@ export const createCube = /* #__PURE__ */ factory(name, dependencies, ({ typed } return x.pow(3) // Is faster than mul()mul()mul() }, - 'Array | Matrix': function (x) { - // deep map collection, skip zeros since cube(0) = 0 - return deepMap(x, this, true) - }, - Unit: function (x) { return x.pow(3) } diff --git a/src/function/arithmetic/exp.js b/src/function/arithmetic/exp.js index 606c885f1e..4f9daccff0 100644 --- a/src/function/arithmetic/exp.js +++ b/src/function/arithmetic/exp.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' import { expNumber } from '../../plain/number/index.js' const name = 'exp' @@ -7,8 +6,10 @@ const dependencies = ['typed'] export const createExp = /* #__PURE__ */ factory(name, dependencies, ({ typed }) => { /** - * Calculate the exponent of a value. - * For matrices, the function is evaluated element wise. + * Calculate the exponential of a value. + * For matrices, if you want the matrix exponential of square matrix, use + * the `expm` function; if you want to take the exponential of each element, + * see the examples. * * Syntax: * @@ -20,7 +21,7 @@ export const createExp = /* #__PURE__ */ factory(name, dependencies, ({ typed }) * math.pow(math.e, 2) // returns number 7.3890560989306495 * math.log(math.exp(2)) // returns number 2 * - * math.exp([1, 2, 3]) + * math.map([1, 2, 3], math.exp) * // returns Array [ * // 2.718281828459045, * // 7.3890560989306495, @@ -29,10 +30,10 @@ export const createExp = /* #__PURE__ */ factory(name, dependencies, ({ typed }) * * See also: * - * expm1, log, pow + * expm1, expm, log, pow * - * @param {number | BigNumber | Complex | Array | Matrix} x A number or matrix to exponentiate - * @return {number | BigNumber | Complex | Array | Matrix} Exponent of `x` + * @param {number | BigNumber | Complex} x A number to exponentiate + * @return {number | BigNumber | Complex} Exponential of `x` */ return typed(name, { number: expNumber, @@ -43,11 +44,6 @@ export const createExp = /* #__PURE__ */ factory(name, dependencies, ({ typed }) BigNumber: function (x) { return x.exp() - }, - - 'Array | Matrix': function (x) { - // TODO: exp(sparse) should return a dense matrix since exp(0)==1 - return deepMap(x, this) } }) }) diff --git a/src/function/arithmetic/expm1.js b/src/function/arithmetic/expm1.js index 37845015f7..93e1556f31 100644 --- a/src/function/arithmetic/expm1.js +++ b/src/function/arithmetic/expm1.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' import { expm1Number } from '../../plain/number/index.js' const name = 'expm1' @@ -8,7 +7,10 @@ const dependencies = ['typed', 'Complex'] export const createExpm1 = /* #__PURE__ */ factory(name, dependencies, ({ typed, Complex }) => { /** * Calculate the value of subtracting 1 from the exponential value. - * For matrices, the function is evaluated element wise. + * This function is more accurate than `math.exp(x)-1` when `x` is near 0 + * To avoid ambiguity with the matrix exponential `expm`, this function + * does not operate on matrices; if you wish to apply it elementwise, see + * the examples. * * Syntax: * @@ -18,9 +20,11 @@ export const createExpm1 = /* #__PURE__ */ factory(name, dependencies, ({ typed, * * math.expm1(2) // returns number 6.38905609893065 * math.pow(math.e, 2) - 1 // returns number 6.3890560989306495 + * math.expm1(1e-8) // returns number 1.0000000050000001e-8 + * math.exp(1e-8) - 1 // returns number 9.9999999392253e-9 * math.log(math.expm1(2) + 1) // returns number 2 * - * math.expm1([1, 2, 3]) + * math.map([1, 2, 3], math.expm1) * // returns Array [ * // 1.718281828459045, * // 6.3890560989306495, @@ -29,10 +33,10 @@ export const createExpm1 = /* #__PURE__ */ factory(name, dependencies, ({ typed, * * See also: * - * exp, log, pow + * exp, expm, log, pow * - * @param {number | BigNumber | Complex | Array | Matrix} x A number or matrix to apply expm1 - * @return {number | BigNumber | Complex | Array | Matrix} Exponent of `x` + * @param {number | BigNumber | Complex} x A number or matrix to apply expm1 + * @return {number | BigNumber | Complex} Exponential of `x`, minus one */ return typed(name, { number: expm1Number, @@ -47,10 +51,6 @@ export const createExpm1 = /* #__PURE__ */ factory(name, dependencies, ({ typed, BigNumber: function (x) { return x.exp().minus(1) - }, - - 'Array | Matrix': function (x) { - return deepMap(x, this) } }) }) diff --git a/src/function/arithmetic/log.js b/src/function/arithmetic/log.js index ad7b54ea36..e16b7efb55 100644 --- a/src/function/arithmetic/log.js +++ b/src/function/arithmetic/log.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' import { logNumber } from '../../plain/number/index.js' const name = 'log' @@ -9,7 +8,8 @@ export const createLog = /* #__PURE__ */ factory(name, dependencies, ({ typed, c /** * Calculate the logarithm of a value. * - * For matrices, the function is evaluated element wise. + * To avoid confusion with the matrix logarithm, this function does not + * apply to matrices. * * Syntax: * @@ -32,12 +32,12 @@ export const createLog = /* #__PURE__ */ factory(name, dependencies, ({ typed, c * * exp, log2, log10, log1p * - * @param {number | BigNumber | Complex | Array | Matrix} x + * @param {number | BigNumber | Complex} x * Value for which to calculate the logarithm. * @param {number | BigNumber | Complex} [base=e] * Optional base for the logarithm. If not provided, the natural * logarithm of `x` is calculated. - * @return {number | BigNumber | Complex | Array | Matrix} + * @return {number | BigNumber | Complex} * Returns the logarithm of `x` */ return typed(name, { @@ -63,10 +63,6 @@ export const createLog = /* #__PURE__ */ factory(name, dependencies, ({ typed, c } }, - 'Array | Matrix': function (x) { - return deepMap(x, this) - }, - 'any, any': function (x, base) { // calculate logarithm for a specified base, log(x, base) return divideScalar(this(x), this(base)) diff --git a/src/function/arithmetic/sqrt.js b/src/function/arithmetic/sqrt.js index 6d3b9a34ec..8174dd72e3 100644 --- a/src/function/arithmetic/sqrt.js +++ b/src/function/arithmetic/sqrt.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' const name = 'sqrt' const dependencies = ['config', 'typed', 'Complex'] @@ -8,7 +7,9 @@ export const createSqrt = /* #__PURE__ */ factory(name, dependencies, ({ config, /** * Calculate the square root of a value. * - * For matrices, the function is evaluated element wise. + * For matrices, if you want the matrix square root of a square matrix, + * use the `sqrtm` function. If you wish to apply `sqrt` elementwise to + * a matrix M, use `math.map(M, math.sqrt)`. * * Syntax: * @@ -24,9 +25,9 @@ export const createSqrt = /* #__PURE__ */ factory(name, dependencies, ({ config, * * square, multiply, cube, cbrt, sqrtm * - * @param {number | BigNumber | Complex | Array | Matrix | Unit} x + * @param {number | BigNumber | Complex | Unit} x * Value for which to calculate the square root. - * @return {number | BigNumber | Complex | Array | Matrix | Unit} + * @return {number | BigNumber | Complex | Unit} * Returns the square root of `x` */ return typed('sqrt', { @@ -45,11 +46,6 @@ export const createSqrt = /* #__PURE__ */ factory(name, dependencies, ({ config, } }, - 'Array | Matrix': function (x) { - // deep map collection, skip zeros since sqrt(0) = 0 - return deepMap(x, this, true) - }, - Unit: function (x) { // Someday will work for complex units when they are implemented return x.pow(0.5) diff --git a/src/function/arithmetic/square.js b/src/function/arithmetic/square.js index c9e9adde8e..5162f7fac6 100644 --- a/src/function/arithmetic/square.js +++ b/src/function/arithmetic/square.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' import { squareNumber } from '../../plain/number/index.js' const name = 'square' @@ -8,7 +7,9 @@ const dependencies = ['typed'] export const createSquare = /* #__PURE__ */ factory(name, dependencies, ({ typed }) => { /** * Compute the square of a value, `x * x`. - * For matrices, the function is evaluated element wise. + * To avoid confusion with multiplying a square matrix by itself, + * this function does not apply to matrices. If you wish to square + * every element of a matrix, see the examples. * * Syntax: * @@ -21,15 +22,15 @@ export const createSquare = /* #__PURE__ */ factory(name, dependencies, ({ typed * math.pow(3, 2) // returns number 9 * math.multiply(3, 3) // returns number 9 * - * math.square([1, 2, 3, 4]) // returns Array [1, 4, 9, 16] + * math.map([1, 2, 3, 4], math.square) // returns Array [1, 4, 9, 16] * * See also: * * multiply, cube, sqrt, pow * - * @param {number | BigNumber | Fraction | Complex | Array | Matrix | Unit} x + * @param {number | BigNumber | Fraction | Complex | Unit} x * Number for which to calculate the square - * @return {number | BigNumber | Fraction | Complex | Array | Matrix | Unit} + * @return {number | BigNumber | Fraction | Complex | Unit} * Squared value */ return typed(name, { @@ -47,11 +48,6 @@ export const createSquare = /* #__PURE__ */ factory(name, dependencies, ({ typed return x.mul(x) }, - 'Array | Matrix': function (x) { - // deep map collection, skip zeros since square(0) = 0 - return deepMap(x, this, true) - }, - Unit: function (x) { return x.pow(2) } diff --git a/src/function/matrix/sqrtm.js b/src/function/matrix/sqrtm.js index 3df014b8bb..e216d976b0 100644 --- a/src/function/matrix/sqrtm.js +++ b/src/function/matrix/sqrtm.js @@ -4,9 +4,9 @@ import { arraySize } from '../../utils/array.js' import { factory } from '../../utils/factory.js' const name = 'sqrtm' -const dependencies = ['typed', 'abs', 'add', 'multiply', 'sqrt', 'subtract', 'inv', 'size', 'max', 'identity'] +const dependencies = ['typed', 'abs', 'add', 'multiply', 'map', 'sqrt', 'subtract', 'inv', 'size', 'max', 'identity'] -export const createSqrtm = /* #__PURE__ */ factory(name, dependencies, ({ typed, abs, add, multiply, sqrt, subtract, inv, size, max, identity }) => { +export const createSqrtm = /* #__PURE__ */ factory(name, dependencies, ({ typed, abs, add, multiply, map, sqrt, subtract, inv, size, max, identity }) => { const _maxIterations = 1e3 const _tolerance = 1e-6 @@ -69,7 +69,7 @@ export const createSqrtm = /* #__PURE__ */ factory(name, dependencies, ({ typed, case 1: // Single element Array | Matrix if (size[0] === 1) { - return sqrt(A) + return map(A, sqrt) } else { throw new RangeError('Matrix must be square ' + '(size: ' + format(size) + ')') diff --git a/src/function/probability/gamma.js b/src/function/probability/gamma.js index 614914fb60..eb64dbcaee 100644 --- a/src/function/probability/gamma.js +++ b/src/function/probability/gamma.js @@ -1,4 +1,3 @@ -import { deepMap } from '../../utils/collection.js' import { factory } from '../../utils/factory.js' import { gammaG, gammaNumber, gammaP } from '../../plain/number/index.js' @@ -10,7 +9,8 @@ export const createGamma = /* #__PURE__ */ factory(name, dependencies, ({ typed, * Compute the gamma function of a value using Lanczos approximation for * small values, and an extended Stirling approximation for large values. * - * For matrices, the function is evaluated element wise. + * To avoid confusion with the matrix Gamma function, this function does + * not apply to matrices. * * Syntax: * @@ -26,8 +26,8 @@ export const createGamma = /* #__PURE__ */ factory(name, dependencies, ({ typed, * * combinations, factorial, permutations * - * @param {number | Array | Matrix} n A real or complex number - * @return {number | Array | Matrix} The gamma of `n` + * @param {number | BigNumber | Complex} n A real or complex number + * @return {number | BigNumber | Complex} The gamma of `n` */ return typed(name, { @@ -88,10 +88,6 @@ export const createGamma = /* #__PURE__ */ factory(name, dependencies, ({ typed, } throw new Error('Integer BigNumber expected') - }, - - 'Array | Matrix': function (n) { - return deepMap(n, this) } }) diff --git a/src/function/probability/kldivergence.js b/src/function/probability/kldivergence.js index 7eae4d683b..a6882a97ea 100644 --- a/src/function/probability/kldivergence.js +++ b/src/function/probability/kldivergence.js @@ -1,9 +1,9 @@ import { factory } from '../../utils/factory.js' const name = 'kldivergence' -const dependencies = ['typed', 'matrix', 'divide', 'sum', 'multiply', 'dotDivide', 'log', 'isNumeric'] +const dependencies = ['typed', 'matrix', 'divide', 'sum', 'multiply', 'map', 'dotDivide', 'log', 'isNumeric'] -export const createKldivergence = /* #__PURE__ */ factory(name, dependencies, ({ typed, matrix, divide, sum, multiply, dotDivide, log, isNumeric }) => { +export const createKldivergence = /* #__PURE__ */ factory(name, dependencies, ({ typed, matrix, divide, sum, multiply, map, dotDivide, log, isNumeric }) => { /** * Calculate the Kullback-Leibler (KL) divergence between two distributions * @@ -67,7 +67,7 @@ export const createKldivergence = /* #__PURE__ */ factory(name, dependencies, ({ const qnorm = divide(q, sum(q)) const pnorm = divide(p, sum(p)) - const result = sum(multiply(qnorm, log(dotDivide(qnorm, pnorm)))) + const result = sum(multiply(qnorm, map(dotDivide(qnorm, pnorm), x => log(x)))) if (isNumeric(result)) { return result } else { diff --git a/src/function/statistics/std.js b/src/function/statistics/std.js index f19d282665..7f6d33ba12 100644 --- a/src/function/statistics/std.js +++ b/src/function/statistics/std.js @@ -1,9 +1,9 @@ import { factory } from '../../utils/factory.js' - +import { isCollection } from '../../utils/is.js' const name = 'std' -const dependencies = ['typed', 'sqrt', 'variance'] +const dependencies = ['typed', 'map', 'sqrt', 'variance'] -export const createStd = /* #__PURE__ */ factory(name, dependencies, ({ typed, sqrt, variance }) => { +export const createStd = /* #__PURE__ */ factory(name, dependencies, ({ typed, map, sqrt, variance }) => { /** * Compute the standard deviation of a matrix or a list with values. * The standard deviations is defined as the square root of the variance: @@ -81,7 +81,12 @@ export const createStd = /* #__PURE__ */ factory(name, dependencies, ({ typed, s } try { - return sqrt(variance.apply(null, arguments)) + const v = variance.apply(null, arguments) + if (isCollection(v)) { + return map(v, sqrt) + } else { + return sqrt(v) + } } catch (err) { if (err instanceof TypeError && err.message.indexOf(' variance') !== -1) { throw new TypeError(err.message.replace(' variance', ' std')) diff --git a/src/function/trigonometry/acos.js b/src/function/trigonometry/acos.js index 1882d91048..19b3f8ce5a 100644 --- a/src/function/trigonometry/acos.js +++ b/src/function/trigonometry/acos.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' const name = 'acos' const dependencies = ['typed', 'config', 'Complex'] @@ -8,7 +7,8 @@ export const createAcos = /* #__PURE__ */ factory(name, dependencies, ({ typed, /** * Calculate the inverse cosine of a value. * - * For matrices, the function is evaluated element wise. + * To avoid confusion with the matrix arccosine, this function does not + * apply to matrices. * * Syntax: * @@ -25,8 +25,8 @@ export const createAcos = /* #__PURE__ */ factory(name, dependencies, ({ typed, * * cos, atan, asin * - * @param {number | BigNumber | Complex | Array | Matrix} x Function input - * @return {number | BigNumber | Complex | Array | Matrix} The arc cosine of x + * @param {number | BigNumber | Complex} x Function input + * @return {number | BigNumber | Complex} The arc cosine of x */ return typed(name, { number: function (x) { @@ -43,10 +43,6 @@ export const createAcos = /* #__PURE__ */ factory(name, dependencies, ({ typed, BigNumber: function (x) { return x.acos() - }, - - 'Array | Matrix': function (x) { - return deepMap(x, this) } }) }) diff --git a/src/function/trigonometry/acosh.js b/src/function/trigonometry/acosh.js index 7fbe1d1280..7340d911cd 100644 --- a/src/function/trigonometry/acosh.js +++ b/src/function/trigonometry/acosh.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' import { acoshNumber } from '../../plain/number/index.js' const name = 'acosh' @@ -24,8 +23,8 @@ export const createAcosh = /* #__PURE__ */ factory(name, dependencies, ({ typed, * * cosh, asinh, atanh * - * @param {number | Complex | Unit | Array | Matrix} x Function input - * @return {number | Complex | Array | Matrix} Hyperbolic arccosine of x + * @param {number | BigNumber | Complex} x Function input + * @return {number | BigNumber | Complex} Hyperbolic arccosine of x */ return typed(name, { number: function (x) { @@ -44,10 +43,6 @@ export const createAcosh = /* #__PURE__ */ factory(name, dependencies, ({ typed, BigNumber: function (x) { return x.acosh() - }, - - 'Array | Matrix': function (x) { - return deepMap(x, this) } }) }) diff --git a/src/function/trigonometry/acot.js b/src/function/trigonometry/acot.js index 07dd3166c1..20d51c1068 100644 --- a/src/function/trigonometry/acot.js +++ b/src/function/trigonometry/acot.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' import { acotNumber } from '../../plain/number/index.js' const name = 'acot' @@ -9,7 +8,8 @@ export const createAcot = /* #__PURE__ */ factory(name, dependencies, ({ typed, /** * Calculate the inverse cotangent of a value, defined as `acot(x) = atan(1/x)`. * - * For matrices, the function is evaluated element wise. + * To avoid confusion with the matrix arccotanget, this function does not + * apply to matrices. * * Syntax: * @@ -26,8 +26,8 @@ export const createAcot = /* #__PURE__ */ factory(name, dependencies, ({ typed, * * cot, atan * - * @param {number | Complex | Array | Matrix} x Function input - * @return {number | Complex | Array | Matrix} The arc cotangent of x + * @param {number | BigNumber| Complex} x Function input + * @return {number | BigNumber| Complex} The arc cotangent of x */ return typed(name, { number: acotNumber, @@ -38,10 +38,6 @@ export const createAcot = /* #__PURE__ */ factory(name, dependencies, ({ typed, BigNumber: function (x) { return new BigNumber(1).div(x).atan() - }, - - 'Array | Matrix': function (x) { - return deepMap(x, this) } }) }) diff --git a/src/function/trigonometry/acoth.js b/src/function/trigonometry/acoth.js index 96ec9ac188..d339dbb499 100644 --- a/src/function/trigonometry/acoth.js +++ b/src/function/trigonometry/acoth.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' import { acothNumber } from '../../plain/number/index.js' const name = 'acoth' @@ -10,7 +9,8 @@ export const createAcoth = /* #__PURE__ */ factory(name, dependencies, ({ typed, * Calculate the hyperbolic arccotangent of a value, * defined as `acoth(x) = atanh(1/x) = (ln((x+1)/x) + ln(x/(x-1))) / 2`. * - * For matrices, the function is evaluated element wise. + * To avoid confusion with the matrix hyperbolic arccotangent, this + * function does not apply to matrices. * * Syntax: * @@ -24,8 +24,8 @@ export const createAcoth = /* #__PURE__ */ factory(name, dependencies, ({ typed, * * acsch, asech * - * @param {number | Complex | Array | Matrix} x Function input - * @return {number | Complex | Array | Matrix} Hyperbolic arccotangent of x + * @param {number | BigNumber | Complex} x Function input + * @return {number | BigNumber | Complex} Hyperbolic arccotangent of x */ return typed(name, { number: function (x) { @@ -41,10 +41,6 @@ export const createAcoth = /* #__PURE__ */ factory(name, dependencies, ({ typed, BigNumber: function (x) { return new BigNumber(1).div(x).atanh() - }, - - 'Array | Matrix': function (x) { - return deepMap(x, this) } }) }) diff --git a/src/function/trigonometry/acsc.js b/src/function/trigonometry/acsc.js index 620c44cbd8..a4de3f3fca 100644 --- a/src/function/trigonometry/acsc.js +++ b/src/function/trigonometry/acsc.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' import { acscNumber } from '../../plain/number/index.js' const name = 'acsc' @@ -9,7 +8,8 @@ export const createAcsc = /* #__PURE__ */ factory(name, dependencies, ({ typed, /** * Calculate the inverse cosecant of a value, defined as `acsc(x) = asin(1/x)`. * - * For matrices, the function is evaluated element wise. + * To avoid confusion with the matrix arccosecant, this function does not + * apply to matrices. * * Syntax: * @@ -26,8 +26,8 @@ export const createAcsc = /* #__PURE__ */ factory(name, dependencies, ({ typed, * * csc, asin, asec * - * @param {number | Complex | Array | Matrix} x Function input - * @return {number | Complex | Array | Matrix} The arc cosecant of x + * @param {number | BigNumber | Complex} x Function input + * @return {number | BigNumber | Complex} The arc cosecant of x */ return typed(name, { number: function (x) { @@ -43,10 +43,6 @@ export const createAcsc = /* #__PURE__ */ factory(name, dependencies, ({ typed, BigNumber: function (x) { return new BigNumber(1).div(x).asin() - }, - - 'Array | Matrix': function (x) { - return deepMap(x, this) } }) }) diff --git a/src/function/trigonometry/acsch.js b/src/function/trigonometry/acsch.js index ff7c3d0232..e287f3c890 100644 --- a/src/function/trigonometry/acsch.js +++ b/src/function/trigonometry/acsch.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' import { acschNumber } from '../../plain/number/index.js' const name = 'acsch' @@ -10,7 +9,8 @@ export const createAcsch = /* #__PURE__ */ factory(name, dependencies, ({ typed, * Calculate the hyperbolic arccosecant of a value, * defined as `acsch(x) = asinh(1/x) = ln(1/x + sqrt(1/x^2 + 1))`. * - * For matrices, the function is evaluated element wise. + * To avoid confusion with the matrix hyperbolic arccosecant, this function + * does not apply to matrices. * * Syntax: * @@ -24,8 +24,8 @@ export const createAcsch = /* #__PURE__ */ factory(name, dependencies, ({ typed, * * asech, acoth * - * @param {number | Complex | Array | Matrix} x Function input - * @return {number | Complex | Array | Matrix} Hyperbolic arccosecant of x + * @param {number | BigNumber | Complex} x Function input + * @return {number | BigNumber | Complex} Hyperbolic arccosecant of x */ return typed(name, { number: acschNumber, @@ -36,10 +36,6 @@ export const createAcsch = /* #__PURE__ */ factory(name, dependencies, ({ typed, BigNumber: function (x) { return new BigNumber(1).div(x).asinh() - }, - - 'Array | Matrix': function (x) { - return deepMap(x, this) } }) }) diff --git a/src/function/trigonometry/asec.js b/src/function/trigonometry/asec.js index 451094a234..228988f5be 100644 --- a/src/function/trigonometry/asec.js +++ b/src/function/trigonometry/asec.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' import { asecNumber } from '../../plain/number/index.js' const name = 'asec' @@ -9,7 +8,8 @@ export const createAsec = /* #__PURE__ */ factory(name, dependencies, ({ typed, /** * Calculate the inverse secant of a value. Defined as `asec(x) = acos(1/x)`. * - * For matrices, the function is evaluated element wise. + * To avoid confusion with the matrix arcsecant, this function does not + * apply to matrices. * * Syntax: * @@ -26,8 +26,8 @@ export const createAsec = /* #__PURE__ */ factory(name, dependencies, ({ typed, * * acos, acot, acsc * - * @param {number | Complex | Array | Matrix} x Function input - * @return {number | Complex | Array | Matrix} The arc secant of x + * @param {number | BigNumber | Complex} x Function input + * @return {number | BigNumber | Complex} The arc secant of x */ return typed(name, { number: function (x) { @@ -43,10 +43,6 @@ export const createAsec = /* #__PURE__ */ factory(name, dependencies, ({ typed, BigNumber: function (x) { return new BigNumber(1).div(x).acos() - }, - - 'Array | Matrix': function (x) { - return deepMap(x, this) } }) }) diff --git a/src/function/trigonometry/asech.js b/src/function/trigonometry/asech.js index 7576f952e4..9688adf370 100644 --- a/src/function/trigonometry/asech.js +++ b/src/function/trigonometry/asech.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' import { asechNumber } from '../../plain/number/index.js' const name = 'asech' @@ -10,7 +9,8 @@ export const createAsech = /* #__PURE__ */ factory(name, dependencies, ({ typed, * Calculate the hyperbolic arcsecant of a value, * defined as `asech(x) = acosh(1/x) = ln(sqrt(1/x^2 - 1) + 1/x)`. * - * For matrices, the function is evaluated element wise. + * To avoid confusion with the matrix hyperbolic arcsecant, this function + * does not apply to matrices. * * Syntax: * @@ -24,8 +24,8 @@ export const createAsech = /* #__PURE__ */ factory(name, dependencies, ({ typed, * * acsch, acoth * - * @param {number | Complex | Array | Matrix} x Function input - * @return {number | Complex | Array | Matrix} Hyperbolic arcsecant of x + * @param {number | BigNumber | Complex} x Function input + * @return {number | BigNumber | Complex} Hyperbolic arcsecant of x */ return typed(name, { number: function (x) { @@ -48,10 +48,6 @@ export const createAsech = /* #__PURE__ */ factory(name, dependencies, ({ typed, BigNumber: function (x) { return new BigNumber(1).div(x).acosh() - }, - - 'Array | Matrix': function (x) { - return deepMap(x, this) } }) }) diff --git a/src/function/trigonometry/asin.js b/src/function/trigonometry/asin.js index 5958096ace..ef26802880 100644 --- a/src/function/trigonometry/asin.js +++ b/src/function/trigonometry/asin.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' const name = 'asin' const dependencies = ['typed', 'config', 'Complex'] @@ -8,7 +7,8 @@ export const createAsin = /* #__PURE__ */ factory(name, dependencies, ({ typed, /** * Calculate the inverse sine of a value. * - * For matrices, the function is evaluated element wise. + * To avoid confusion with the matric arcsine, this function does not apply + * to matrices. * * Syntax: * @@ -25,8 +25,8 @@ export const createAsin = /* #__PURE__ */ factory(name, dependencies, ({ typed, * * sin, atan, acos * - * @param {number | BigNumber | Complex | Array | Matrix} x Function input - * @return {number | BigNumber | Complex | Array | Matrix} The arc sine of x + * @param {number | BigNumber | Complex} x Function input + * @return {number | BigNumber | Complex} The arc sine of x */ return typed(name, { number: function (x) { @@ -43,11 +43,6 @@ export const createAsin = /* #__PURE__ */ factory(name, dependencies, ({ typed, BigNumber: function (x) { return x.asin() - }, - - 'Array | Matrix': function (x) { - // deep map collection, skip zeros since asin(0) = 0 - return deepMap(x, this, true) } }) }) diff --git a/src/function/trigonometry/asinh.js b/src/function/trigonometry/asinh.js index 3cb41cc891..665a65deb7 100644 --- a/src/function/trigonometry/asinh.js +++ b/src/function/trigonometry/asinh.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' import { asinhNumber } from '../../plain/number/index.js' const name = 'asinh' @@ -10,7 +9,8 @@ export const createAsinh = /* #__PURE__ */ factory(name, dependencies, ({ typed * Calculate the hyperbolic arcsine of a value, * defined as `asinh(x) = ln(x + sqrt(x^2 + 1))`. * - * For matrices, the function is evaluated element wise. + * To avoid confusion with the matrix hyperbolic arcsine, this function + * does not apply to matrices. * * Syntax: * @@ -24,8 +24,8 @@ export const createAsinh = /* #__PURE__ */ factory(name, dependencies, ({ typed * * acosh, atanh * - * @param {number | Complex | Array | Matrix} x Function input - * @return {number | Complex | Array | Matrix} Hyperbolic arcsine of x + * @param {number | BigNumber | Complex} x Function input + * @return {number | BigNumber | Complex} Hyperbolic arcsine of x */ return typed('asinh', { number: asinhNumber, @@ -36,11 +36,6 @@ export const createAsinh = /* #__PURE__ */ factory(name, dependencies, ({ typed BigNumber: function (x) { return x.asinh() - }, - - 'Array | Matrix': function (x) { - // deep map collection, skip zeros since asinh(0) = 0 - return deepMap(x, this, true) } }) }) diff --git a/src/function/trigonometry/atan.js b/src/function/trigonometry/atan.js index 27954b67a1..02ac3b6f9f 100644 --- a/src/function/trigonometry/atan.js +++ b/src/function/trigonometry/atan.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' const name = 'atan' const dependencies = ['typed'] @@ -8,7 +7,8 @@ export const createAtan = /* #__PURE__ */ factory(name, dependencies, ({ typed } /** * Calculate the inverse tangent of a value. * - * For matrices, the function is evaluated element wise. + * To avoid confusion with matrix arctangent, this function does not apply + * to matrices. * * Syntax: * @@ -25,8 +25,8 @@ export const createAtan = /* #__PURE__ */ factory(name, dependencies, ({ typed } * * tan, asin, acos * - * @param {number | BigNumber | Complex | Array | Matrix} x Function input - * @return {number | BigNumber | Complex | Array | Matrix} The arc tangent of x + * @param {number | BigNumber | Complex} x Function input + * @return {number | BigNumber | Complex} The arc tangent of x */ return typed('atan', { number: function (x) { @@ -39,11 +39,6 @@ export const createAtan = /* #__PURE__ */ factory(name, dependencies, ({ typed } BigNumber: function (x) { return x.atan() - }, - - 'Array | Matrix': function (x) { - // deep map collection, skip zeros since atan(0) = 0 - return deepMap(x, this, true) } }) }) diff --git a/src/function/trigonometry/atanh.js b/src/function/trigonometry/atanh.js index b4b9c4cfee..f9eda776f1 100644 --- a/src/function/trigonometry/atanh.js +++ b/src/function/trigonometry/atanh.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' import { atanhNumber } from '../../plain/number/index.js' const name = 'atanh' @@ -10,7 +9,8 @@ export const createAtanh = /* #__PURE__ */ factory(name, dependencies, ({ typed, * Calculate the hyperbolic arctangent of a value, * defined as `atanh(x) = ln((1 + x)/(1 - x)) / 2`. * - * For matrices, the function is evaluated element wise. + * To avoid confusion with the matrix hyperbolic arctangent, this function + * does not apply to matrices. * * Syntax: * @@ -24,8 +24,8 @@ export const createAtanh = /* #__PURE__ */ factory(name, dependencies, ({ typed, * * acosh, asinh * - * @param {number | Complex | Array | Matrix} x Function input - * @return {number | Complex | Array | Matrix} Hyperbolic arctangent of x + * @param {number | BigNumber | Complex} x Function input + * @return {number | BigNumber | Complex} Hyperbolic arctangent of x */ return typed(name, { number: function (x) { @@ -41,11 +41,6 @@ export const createAtanh = /* #__PURE__ */ factory(name, dependencies, ({ typed, BigNumber: function (x) { return x.atanh() - }, - - 'Array | Matrix': function (x) { - // deep map collection, skip zeros since atanh(0) = 0 - return deepMap(x, this, true) } }) }) diff --git a/src/function/trigonometry/cos.js b/src/function/trigonometry/cos.js index 4f30a5c2a0..30ca27f8b1 100644 --- a/src/function/trigonometry/cos.js +++ b/src/function/trigonometry/cos.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' const name = 'cos' const dependencies = ['typed'] @@ -8,7 +7,8 @@ export const createCos = /* #__PURE__ */ factory(name, dependencies, ({ typed }) /** * Calculate the cosine of a value. * - * For matrices, the function is evaluated element wise. + * To avoid confusion with the matrix cosine, this function does not + * apply to matrices. * * Syntax: * @@ -28,8 +28,8 @@ export const createCos = /* #__PURE__ */ factory(name, dependencies, ({ typed }) * * cos, tan * - * @param {number | BigNumber | Complex | Unit | Array | Matrix} x Function input - * @return {number | BigNumber | Complex | Array | Matrix} Cosine of x + * @param {number | BigNumber | Complex | Unit} x Function input + * @return {number | BigNumber | Complex} Cosine of x */ return typed(name, { number: Math.cos, @@ -47,10 +47,6 @@ export const createCos = /* #__PURE__ */ factory(name, dependencies, ({ typed }) throw new TypeError('Unit in function cos is no angle') } return this(x.value) - }, - - 'Array | Matrix': function (x) { - return deepMap(x, this) } }) }) diff --git a/src/function/trigonometry/cosh.js b/src/function/trigonometry/cosh.js index 3bcd921b93..dfc40de33a 100644 --- a/src/function/trigonometry/cosh.js +++ b/src/function/trigonometry/cosh.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' import { cosh as coshNumber } from '../../utils/number.js' const name = 'cosh' @@ -10,7 +9,8 @@ export const createCosh = /* #__PURE__ */ factory(name, dependencies, ({ typed } * Calculate the hyperbolic cosine of a value, * defined as `cosh(x) = 1/2 * (exp(x) + exp(-x))`. * - * For matrices, the function is evaluated element wise. + * To avoid confusion with the matrix hyperbolic cosine, this function does + * not apply to matrices. * * Syntax: * @@ -24,8 +24,8 @@ export const createCosh = /* #__PURE__ */ factory(name, dependencies, ({ typed } * * sinh, tanh * - * @param {number | BigNumber | Complex | Unit | Array | Matrix} x Function input - * @return {number | BigNumber | Complex | Array | Matrix} Hyperbolic cosine of x + * @param {number | BigNumber | Complex | Unit} x Function input + * @return {number | BigNumber | Complex} Hyperbolic cosine of x */ return typed(name, { number: coshNumber, @@ -43,10 +43,6 @@ export const createCosh = /* #__PURE__ */ factory(name, dependencies, ({ typed } throw new TypeError('Unit in function cosh is no angle') } return this(x.value) - }, - - 'Array | Matrix': function (x) { - return deepMap(x, this) } }) }) diff --git a/src/function/trigonometry/cot.js b/src/function/trigonometry/cot.js index 64f544a953..0132cf5eab 100644 --- a/src/function/trigonometry/cot.js +++ b/src/function/trigonometry/cot.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' import { cotNumber } from '../../plain/number/index.js' const name = 'cot' @@ -9,7 +8,8 @@ export const createCot = /* #__PURE__ */ factory(name, dependencies, ({ typed, B /** * Calculate the cotangent of a value. Defined as `cot(x) = 1 / tan(x)`. * - * For matrices, the function is evaluated element wise. + * To avoid confusion with the matrix cotangent, this function does not + * apply to matrices. * * Syntax: * @@ -43,10 +43,6 @@ export const createCot = /* #__PURE__ */ factory(name, dependencies, ({ typed, B throw new TypeError('Unit in function cot is no angle') } return this(x.value) - }, - - 'Array | Matrix': function (x) { - return deepMap(x, this) } }) }) diff --git a/src/function/trigonometry/coth.js b/src/function/trigonometry/coth.js index 68b9b9bc3a..2194e6cae0 100644 --- a/src/function/trigonometry/coth.js +++ b/src/function/trigonometry/coth.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' import { cothNumber } from '../../plain/number/index.js' const name = 'coth' @@ -10,7 +9,8 @@ export const createCoth = /* #__PURE__ */ factory(name, dependencies, ({ typed, * Calculate the hyperbolic cotangent of a value, * defined as `coth(x) = 1 / tanh(x)`. * - * For matrices, the function is evaluated element wise. + * To avoid confusion with the matrix hyperbolic cotangent, this function + * does not apply to matrices. * * Syntax: * @@ -26,8 +26,8 @@ export const createCoth = /* #__PURE__ */ factory(name, dependencies, ({ typed, * * sinh, tanh, cosh * - * @param {number | Complex | Unit | Array | Matrix} x Function input - * @return {number | Complex | Array | Matrix} Hyperbolic cotangent of x + * @param {number | BigNumber | Complex | Unit} x Function input + * @return {number | BigNumber | Complex} Hyperbolic cotangent of x */ return typed(name, { number: cothNumber, @@ -45,10 +45,6 @@ export const createCoth = /* #__PURE__ */ factory(name, dependencies, ({ typed, throw new TypeError('Unit in function coth is no angle') } return this(x.value) - }, - - 'Array | Matrix': function (x) { - return deepMap(x, this) } }) }) diff --git a/src/function/trigonometry/csc.js b/src/function/trigonometry/csc.js index b29da96870..b88c11b8ec 100644 --- a/src/function/trigonometry/csc.js +++ b/src/function/trigonometry/csc.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' import { cscNumber } from '../../plain/number/index.js' const name = 'csc' @@ -9,7 +8,8 @@ export const createCsc = /* #__PURE__ */ factory(name, dependencies, ({ typed, B /** * Calculate the cosecant of a value, defined as `csc(x) = 1/sin(x)`. * - * For matrices, the function is evaluated element wise. + * To avoid confusion with the matrix cosecant, this function does not + * apply to matrices. * * Syntax: * @@ -24,8 +24,8 @@ export const createCsc = /* #__PURE__ */ factory(name, dependencies, ({ typed, B * * sin, sec, cot * - * @param {number | Complex | Unit | Array | Matrix} x Function input - * @return {number | Complex | Array | Matrix} Cosecant of x + * @param {number | BigNumber | Complex | Unit} x Function input + * @return {number | BigNumber | Complex} Cosecant of x */ return typed(name, { number: cscNumber, @@ -43,10 +43,6 @@ export const createCsc = /* #__PURE__ */ factory(name, dependencies, ({ typed, B throw new TypeError('Unit in function csc is no angle') } return this(x.value) - }, - - 'Array | Matrix': function (x) { - return deepMap(x, this) } }) }) diff --git a/src/function/trigonometry/csch.js b/src/function/trigonometry/csch.js index f13c33faf6..970c171f76 100644 --- a/src/function/trigonometry/csch.js +++ b/src/function/trigonometry/csch.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' import { cschNumber } from '../../plain/number/index.js' const name = 'csch' @@ -10,7 +9,8 @@ export const createCsch = /* #__PURE__ */ factory(name, dependencies, ({ typed, * Calculate the hyperbolic cosecant of a value, * defined as `csch(x) = 1 / sinh(x)`. * - * For matrices, the function is evaluated element wise. + * To avoid confusion with the matrix hyperbolic cosecant, this function + * does not apply to matrices. * * Syntax: * @@ -26,8 +26,8 @@ export const createCsch = /* #__PURE__ */ factory(name, dependencies, ({ typed, * * sinh, sech, coth * - * @param {number | Complex | Unit | Array | Matrix} x Function input - * @return {number | Complex | Array | Matrix} Hyperbolic cosecant of x + * @param {number | BigNumber | Complex | Unit} x Function input + * @return {number | BigNumber | Complex} Hyperbolic cosecant of x */ return typed(name, { number: cschNumber, @@ -45,10 +45,6 @@ export const createCsch = /* #__PURE__ */ factory(name, dependencies, ({ typed, throw new TypeError('Unit in function csch is no angle') } return this(x.value) - }, - - 'Array | Matrix': function (x) { - return deepMap(x, this) } }) }) diff --git a/src/function/trigonometry/sec.js b/src/function/trigonometry/sec.js index d501854574..a59c63badd 100644 --- a/src/function/trigonometry/sec.js +++ b/src/function/trigonometry/sec.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' import { secNumber } from '../../plain/number/index.js' const name = 'sec' @@ -9,7 +8,8 @@ export const createSec = /* #__PURE__ */ factory(name, dependencies, ({ typed, B /** * Calculate the secant of a value, defined as `sec(x) = 1/cos(x)`. * - * For matrices, the function is evaluated element wise. + * To avoid confusion with the matrix secant, this function does not + * apply to matrices. * * Syntax: * @@ -24,8 +24,8 @@ export const createSec = /* #__PURE__ */ factory(name, dependencies, ({ typed, B * * cos, csc, cot * - * @param {number | Complex | Unit | Array | Matrix} x Function input - * @return {number | Complex | Array | Matrix} Secant of x + * @param {number | BigNumber | Complex | Unit} x Function input + * @return {number | BigNumber | Complex} Secant of x */ return typed(name, { number: secNumber, @@ -43,10 +43,6 @@ export const createSec = /* #__PURE__ */ factory(name, dependencies, ({ typed, B throw new TypeError('Unit in function sec is no angle') } return this(x.value) - }, - - 'Array | Matrix': function (x) { - return deepMap(x, this) } }) }) diff --git a/src/function/trigonometry/sech.js b/src/function/trigonometry/sech.js index 49f4105566..c2b8274430 100644 --- a/src/function/trigonometry/sech.js +++ b/src/function/trigonometry/sech.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' import { sechNumber } from '../../plain/number/index.js' const name = 'sech' @@ -10,7 +9,8 @@ export const createSech = /* #__PURE__ */ factory(name, dependencies, ({ typed, * Calculate the hyperbolic secant of a value, * defined as `sech(x) = 1 / cosh(x)`. * - * For matrices, the function is evaluated element wise. + * To avoid confusion with the matrix hyperbolic secant, this function does + * not apply to matrices. * * Syntax: * @@ -26,8 +26,8 @@ export const createSech = /* #__PURE__ */ factory(name, dependencies, ({ typed, * * cosh, csch, coth * - * @param {number | Complex | Unit | Array | Matrix} x Function input - * @return {number | Complex | Array | Matrix} Hyperbolic secant of x + * @param {number | BigNumber | Complex | Unit} x Function input + * @return {number | BigNumber | Complex} Hyperbolic secant of x */ return typed(name, { number: sechNumber, @@ -45,10 +45,6 @@ export const createSech = /* #__PURE__ */ factory(name, dependencies, ({ typed, throw new TypeError('Unit in function sech is no angle') } return this(x.value) - }, - - 'Array | Matrix': function (x) { - return deepMap(x, this) } }) }) diff --git a/src/function/trigonometry/sin.js b/src/function/trigonometry/sin.js index a4efde3f8c..dbc0e9c32f 100644 --- a/src/function/trigonometry/sin.js +++ b/src/function/trigonometry/sin.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' const name = 'sin' const dependencies = ['typed'] @@ -8,7 +7,8 @@ export const createSin = /* #__PURE__ */ factory(name, dependencies, ({ typed }) /** * Calculate the sine of a value. * - * For matrices, the function is evaluated element wise. + * To avoid confusion with the matrix sine, this function does not apply + * to matrices. * * Syntax: * @@ -28,8 +28,8 @@ export const createSin = /* #__PURE__ */ factory(name, dependencies, ({ typed }) * * cos, tan * - * @param {number | BigNumber | Complex | Unit | Array | Matrix} x Function input - * @return {number | BigNumber | Complex | Array | Matrix} Sine of x + * @param {number | BigNumber | Complex | Unit} x Function input + * @return {number | BigNumber | Complex} Sine of x */ return typed(name, { number: Math.sin, @@ -47,11 +47,6 @@ export const createSin = /* #__PURE__ */ factory(name, dependencies, ({ typed }) throw new TypeError('Unit in function sin is no angle') } return this(x.value) - }, - - 'Array | Matrix': function (x) { - // deep map collection, skip zeros since sin(0) = 0 - return deepMap(x, this, true) } }) }) diff --git a/src/function/trigonometry/sinh.js b/src/function/trigonometry/sinh.js index db2652f2eb..305e5a5ea8 100644 --- a/src/function/trigonometry/sinh.js +++ b/src/function/trigonometry/sinh.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' import { sinhNumber } from '../../plain/number/index.js' const name = 'sinh' @@ -10,7 +9,8 @@ export const createSinh = /* #__PURE__ */ factory(name, dependencies, ({ typed } * Calculate the hyperbolic sine of a value, * defined as `sinh(x) = 1/2 * (exp(x) - exp(-x))`. * - * For matrices, the function is evaluated element wise. + * To avoid confusion with the matrix hyperbolic sine, this function does + * not apply to matrices. * * Syntax: * @@ -24,8 +24,8 @@ export const createSinh = /* #__PURE__ */ factory(name, dependencies, ({ typed } * * cosh, tanh * - * @param {number | BigNumber | Complex | Unit | Array | Matrix} x Function input - * @return {number | BigNumber | Complex | Array | Matrix} Hyperbolic sine of x + * @param {number | BigNumber | Complex | Unit} x Function input + * @return {number | BigNumber | Complex} Hyperbolic sine of x */ return typed(name, { number: sinhNumber, @@ -43,11 +43,6 @@ export const createSinh = /* #__PURE__ */ factory(name, dependencies, ({ typed } throw new TypeError('Unit in function sinh is no angle') } return this(x.value) - }, - - 'Array | Matrix': function (x) { - // deep map collection, skip zeros since sinh(0) = 0 - return deepMap(x, this, true) } }) }) diff --git a/src/function/trigonometry/tan.js b/src/function/trigonometry/tan.js index aa1bc9e2d4..7bc485c641 100644 --- a/src/function/trigonometry/tan.js +++ b/src/function/trigonometry/tan.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' const name = 'tan' const dependencies = ['typed'] @@ -8,7 +7,8 @@ export const createTan = /* #__PURE__ */ factory(name, dependencies, ({ typed }) /** * Calculate the tangent of a value. `tan(x)` is equal to `sin(x) / cos(x)`. * - * For matrices, the function is evaluated element wise. + * To avoid confusion with the matrix tangent, this function does not apply + * to matrices. * * Syntax: * @@ -25,8 +25,8 @@ export const createTan = /* #__PURE__ */ factory(name, dependencies, ({ typed }) * * atan, sin, cos * - * @param {number | BigNumber | Complex | Unit | Array | Matrix} x Function input - * @return {number | BigNumber | Complex | Array | Matrix} Tangent of x + * @param {number | BigNumber | Complex | Unit} x Function input + * @return {number | BigNumber | Complex} Tangent of x */ return typed(name, { number: Math.tan, @@ -44,11 +44,6 @@ export const createTan = /* #__PURE__ */ factory(name, dependencies, ({ typed }) throw new TypeError('Unit in function tan is no angle') } return this(x.value) - }, - - 'Array | Matrix': function (x) { - // deep map collection, skip zeros since tan(0) = 0 - return deepMap(x, this, true) } }) }) diff --git a/src/function/trigonometry/tanh.js b/src/function/trigonometry/tanh.js index 6b51a9e96c..d7e242f45a 100644 --- a/src/function/trigonometry/tanh.js +++ b/src/function/trigonometry/tanh.js @@ -1,5 +1,4 @@ import { factory } from '../../utils/factory.js' -import { deepMap } from '../../utils/collection.js' import { tanh as _tanh } from '../../utils/number.js' const name = 'tanh' @@ -10,7 +9,8 @@ export const createTanh = /* #__PURE__ */ factory(name, dependencies, ({ typed } * Calculate the hyperbolic tangent of a value, * defined as `tanh(x) = (exp(2 * x) - 1) / (exp(2 * x) + 1)`. * - * For matrices, the function is evaluated element wise. + * To avoid confusion with matrix hyperbolic tangent, this function does + * not apply to matrices. * * Syntax: * @@ -27,8 +27,8 @@ export const createTanh = /* #__PURE__ */ factory(name, dependencies, ({ typed } * * sinh, cosh, coth * - * @param {number | BigNumber | Complex | Unit | Array | Matrix} x Function input - * @return {number | BigNumber | Complex | Array | Matrix} Hyperbolic tangent of x + * @param {number | BigNumber | Complex | Unit} x Function input + * @return {number | BigNumber | Complex} Hyperbolic tangent of x */ return typed('tanh', { number: _tanh, @@ -46,11 +46,6 @@ export const createTanh = /* #__PURE__ */ factory(name, dependencies, ({ typed } throw new TypeError('Unit in function tanh is no angle') } return this(x.value) - }, - - 'Array | Matrix': function (x) { - // deep map collection, skip zeros since tanh(0) = 0 - return deepMap(x, this, true) } }) }) diff --git a/src/type/matrix/DenseMatrix.js b/src/type/matrix/DenseMatrix.js index 80fb03abe2..5bd9b7b021 100644 --- a/src/type/matrix/DenseMatrix.js +++ b/src/type/matrix/DenseMatrix.js @@ -5,6 +5,7 @@ import { isInteger } from '../../utils/number.js' import { clone, deepStrictEqual } from '../../utils/object.js' import { DimensionError } from '../../error/DimensionError.js' import { factory } from '../../utils/factory.js' +import { maxArgumentCount } from '../../utils/function.js' const name = 'DenseMatrix' const dependencies = [ @@ -535,13 +536,21 @@ export const createDenseMatrixClass = /* #__PURE__ */ factory(name, dependencies DenseMatrix.prototype.map = function (callback) { // matrix instance const me = this + const args = maxArgumentCount(callback) const recurse = function (value, index) { if (isArray(value)) { return value.map(function (child, i) { return recurse(child, index.concat(i)) }) } else { - return callback(value, index, me) + // invoke the callback function with the right number of arguments + if (args === 1) { + return callback(value) + } else if (args === 2) { + return callback(value, index) + } else { // 3 or -1 + return callback(value, index, me) + } } } diff --git a/src/type/matrix/SparseMatrix.js b/src/type/matrix/SparseMatrix.js index 0a9ed203eb..6caff64542 100644 --- a/src/type/matrix/SparseMatrix.js +++ b/src/type/matrix/SparseMatrix.js @@ -5,6 +5,7 @@ import { clone, deepStrictEqual } from '../../utils/object.js' import { arraySize, getArrayDataType, processSizesWildcard, unsqueeze, validateIndex } from '../../utils/array.js' import { factory } from '../../utils/factory.js' import { DimensionError } from '../../error/DimensionError.js' +import { maxArgumentCount } from '../../utils/function.js' const name = 'SparseMatrix' const dependencies = [ @@ -849,8 +850,11 @@ export const createSparseMatrixClass = /* #__PURE__ */ factory(name, dependencie const rows = this._size[0] const columns = this._size[1] // invoke callback + const args = maxArgumentCount(callback) const invoke = function (v, i, j) { // invoke callback + if (args === 1) return callback(v) + if (args === 2) return callback(v, [i, j]) return callback(v, [i, j], me) } // invoke _map diff --git a/test/node-tests/treeShaking/treeShaking.test.js b/test/node-tests/treeShaking/treeShaking.test.js index 874935cd0c..92a947d6aa 100644 --- a/test/node-tests/treeShaking/treeShaking.test.js +++ b/test/node-tests/treeShaking/treeShaking.test.js @@ -66,6 +66,7 @@ describe('tree shaking', function () { assert.strictEqual(info.assets[0].name, bundleName) const size = info.assets[0].size const maxSize = 120000 + const maxSize = 111000 assert(size < maxSize, 'bundled size must be small enough ' + '(actual size: ' + size + ' bytes, max size: ' + maxSize + ' bytes)') diff --git a/test/unit-tests/function/algebra/derivative.test.js b/test/unit-tests/function/algebra/derivative.test.js index e029d3ce81..9075a21771 100644 --- a/test/unit-tests/function/algebra/derivative.test.js +++ b/test/unit-tests/function/algebra/derivative.test.js @@ -245,7 +245,7 @@ describe('derivative', function () { it('should have controlled behavior on arguments errors', function () { assert.throws(function () { derivative('sqrt()', 'x') - }, /TypeError: Too few arguments in function sqrt \(expected: number or Complex or BigNumber or Unit or Array or Matrix or Fraction or string or boolean, index: 0\)/) + }, /TypeError: Too few arguments in function sqrt \(expected: number or Complex or BigNumber or Unit or Fraction or string or boolean, index: 0\)/) assert.throws(function () { derivative('sqrt(12, 2x)', 'x') }, /TypeError: Too many arguments in function sqrt \(expected: 1, actual: 2\)/) diff --git a/test/unit-tests/function/algebra/simplify.test.js b/test/unit-tests/function/algebra/simplify.test.js index 8a7440aaed..6250677465 100644 --- a/test/unit-tests/function/algebra/simplify.test.js +++ b/test/unit-tests/function/algebra/simplify.test.js @@ -147,7 +147,7 @@ describe('simplify', function () { simplifyAndCompare('zeros(2,1)', '[0;0]') simplifyAndCompare('ones(3)', '[1,1,1]') simplifyAndCompare('identity(2)', '[1,0;0,1]') - simplifyAndCompare('sqrt([1,4,9])', '[1,2,3]') + simplifyAndCompare('floor([1.1,4.4,9.9])', '[1,4,9]') simplifyAndCompare('det([2,1;-1,3])', '7') simplifyAndCompare("[1,2;3,4]'", '[1,3;2,4]') }) diff --git a/test/unit-tests/function/arithmetic/cbrt.test.js b/test/unit-tests/function/arithmetic/cbrt.test.js index 87e9668df6..06c0e0af89 100644 --- a/test/unit-tests/function/arithmetic/cbrt.test.js +++ b/test/unit-tests/function/arithmetic/cbrt.test.js @@ -111,10 +111,12 @@ describe('cbrt', function () { }) }) - it('should return the cubic root of each element of a matrix', function () { - assert.deepStrictEqual(cbrt([8, 27, 64, 125]), [2, 3, 4, 5]) - assert.deepStrictEqual(cbrt([[8, 27], [64, 125]]), [[2, 3], [4, 5]]) - assert.deepStrictEqual(cbrt(math.matrix([[8, 27], [64, 125]])), math.matrix([[2, 3], [4, 5]])) + it('should not operate on a matrix', function () { + assert.throws(() => cbrt([8, 27, 64, 125]), TypeError) + assert.throws(() => cbrt(math.matrix([8, 27])), TypeError) + assert.deepStrictEqual(math.map([8, 27, 64, 125], x => cbrt(x)), [2, 3, 4, 5]) + assert.deepStrictEqual(math.map([[8, 27], [64, 125]], x => cbrt(x)), [[2, 3], [4, 5]]) + assert.deepStrictEqual(math.map(math.matrix([[8, 27], [64, 125]]), x => cbrt(x)), math.matrix([[2, 3], [4, 5]])) }) it('should throw an error in case of invalid number of arguments', function () { diff --git a/test/unit-tests/function/arithmetic/cube.test.js b/test/unit-tests/function/arithmetic/cube.test.js index 10f2fd695a..e93ba1a30e 100644 --- a/test/unit-tests/function/arithmetic/cube.test.js +++ b/test/unit-tests/function/arithmetic/cube.test.js @@ -57,12 +57,12 @@ describe('cube', function () { assert.throws(function () { cube(null) }, /TypeError: Unexpected type of argument/) }) - it('should cube each element in a matrix, array or range', function () { - // array, matrix, range - // arrays are evaluated element wise - assert.deepStrictEqual(cube([2, 3, 4, 5]), [8, 27, 64, 125]) - assert.deepStrictEqual(cube(matrix([2, 3, 4, 5])), matrix([8, 27, 64, 125])) - assert.deepStrictEqual(cube(matrix([[1, 2], [3, 4]])), matrix([[1, 8], [27, 64]])) + it('should not operate on a matrix, array or range', function () { + assert.throws(() => cube([2, 3, 4, 5]), TypeError) + assert.throws(() => cube(matrix([2, 3, 4, 5])), TypeError) + assert.deepStrictEqual(math.map([2, 3, 4, 5], cube), [8, 27, 64, 125]) + assert.deepStrictEqual(math.map(matrix([2, 3, 4, 5]), cube), matrix([8, 27, 64, 125])) + assert.deepStrictEqual(math.map(matrix([[1, 2], [3, 4]]), cube), matrix([[1, 8], [27, 64]])) }) it('should LaTeX cube', function () { diff --git a/test/unit-tests/function/arithmetic/exp.test.js b/test/unit-tests/function/arithmetic/exp.test.js index 1e4faccb4e..b48de4b0a5 100644 --- a/test/unit-tests/function/arithmetic/exp.test.js +++ b/test/unit-tests/function/arithmetic/exp.test.js @@ -71,15 +71,17 @@ describe('exp', function () { assert.throws(function () { exp('text') }) }) - it('should exponentiate matrices, arrays and ranges correctly', function () { + it('should not operate on matrices, arrays and ranges', function () { // array - approx.deepEqual(exp([0, 1, 2, 3]), [1, 2.71828182845905, 7.38905609893065, 20.0855369231877]) - approx.deepEqual(exp([[0, 1], [2, 3]]), [[1, 2.71828182845905], [7.38905609893065, 20.0855369231877]]) + assert.throws(() => exp([0, 1, 2, 3]), /Function 'exp' doesn't apply/) + approx.deepEqual(math.map([0, 1, 2, 3], exp), [1, 2.71828182845905, 7.38905609893065, 20.0855369231877]) + approx.deepEqual(math.map([[0, 1], [2, 3]], exp), [[1, 2.71828182845905], [7.38905609893065, 20.0855369231877]]) // dense matrix - approx.deepEqual(exp(matrix([0, 1, 2, 3])), matrix([1, 2.71828182845905, 7.38905609893065, 20.0855369231877])) - approx.deepEqual(exp(matrix([[0, 1], [2, 3]])), matrix([[1, 2.71828182845905], [7.38905609893065, 20.0855369231877]])) + assert.throws(() => exp(matrix([0, 1, 2, 3])), TypeError) + approx.deepEqual(math.map(matrix([0, 1, 2, 3]), exp), matrix([1, 2.71828182845905, 7.38905609893065, 20.0855369231877])) + approx.deepEqual(math.map(matrix([[0, 1], [2, 3]]), exp), matrix([[1, 2.71828182845905], [7.38905609893065, 20.0855369231877]])) // sparse matrix, TODO: it should return a dense matrix - approx.deepEqual(exp(sparse([[0, 1], [2, 3]])), sparse([[1, 2.71828182845905], [7.38905609893065, 20.0855369231877]])) + approx.deepEqual(math.map(sparse([[0, 1], [2, 3]]), exp), sparse([[1, 2.71828182845905], [7.38905609893065, 20.0855369231877]])) }) it('should LaTeX exp', function () { diff --git a/test/unit-tests/function/arithmetic/expm1.test.js b/test/unit-tests/function/arithmetic/expm1.test.js index 702dabac84..ab6b975d6b 100644 --- a/test/unit-tests/function/arithmetic/expm1.test.js +++ b/test/unit-tests/function/arithmetic/expm1.test.js @@ -74,14 +74,17 @@ describe('expm1', function () { assert.throws(function () { expm1('text') }) }) - it('should exponentiate matrices, arrays and ranges correctly', function () { + it('should not operate on matrices, arrays and ranges', function () { // array - approx.deepEqual(expm1([0, 1, 2, 3]), [0, 1.71828182845905, 6.38905609893065, 19.0855369231877]) - approx.deepEqual(expm1([[0, 1], [2, 3]]), [[0, 1.71828182845905], [6.38905609893065, 19.0855369231877]]) + assert.throws(() => expm1([0, 1, 2, 3]), /Function 'expm1' doesn't apply to matrices/) + approx.deepEqual(math.map([0, 1, 2, 3], expm1), [0, 1.71828182845905, 6.38905609893065, 19.0855369231877]) + approx.deepEqual(math.map([[0, 1], [2, 3]], expm1), [[0, 1.71828182845905], [6.38905609893065, 19.0855369231877]]) // dense matrix - approx.deepEqual(expm1(matrix([0, 1, 2, 3])), matrix([0, 1.71828182845905, 6.38905609893065, 19.0855369231877])) - approx.deepEqual(expm1(matrix([[0, 1], [2, 3]])), matrix([[0, 1.71828182845905], [6.38905609893065, 19.0855369231877]])) - approx.deepEqual(expm1(sparse([[0, 1], [2, 3]])), sparse([[0, 1.71828182845905], [6.38905609893065, 19.0855369231877]])) + assert.throws(() => expm1(matrix([0, 1, 2, 3])), TypeError) + approx.deepEqual(math.map(matrix([0, 1, 2, 3]), expm1), matrix([0, 1.71828182845905, 6.38905609893065, 19.0855369231877])) + approx.deepEqual(math.map(matrix([[0, 1], [2, 3]]), expm1), matrix([[0, 1.71828182845905], [6.38905609893065, 19.0855369231877]])) + // sparse matrix + approx.deepEqual(math.map(sparse([[0, 1], [2, 3]]), expm1), sparse([[0, 1.71828182845905], [6.38905609893065, 19.0855369231877]])) }) it('should LaTeX expm1', function () { diff --git a/test/unit-tests/function/arithmetic/log.test.js b/test/unit-tests/function/arithmetic/log.test.js index 975f66aa3d..9219501e78 100644 --- a/test/unit-tests/function/arithmetic/log.test.js +++ b/test/unit-tests/function/arithmetic/log.test.js @@ -112,11 +112,12 @@ describe('log', function () { assert.throws(function () { log('text') }) }) - it('should return the log of each element of a matrix', function () { + it('should not operate on a matrix', function () { const res = [0, 0.693147180559945, 1.098612288668110, 1.386294361119891] - approx.deepEqual(log([1, 2, 3, 4]), res) - approx.deepEqual(log(matrix([1, 2, 3, 4])), matrix(res)) - approx.deepEqual(log(matrix([[1, 2], [3, 4]])), + assert.throws(() => log([1, 2, 3, 4]), TypeError) + approx.deepEqual(math.map([1, 2, 3, 4], x => log(x)), res) + approx.deepEqual(math.map(matrix([1, 2, 3, 4]), x => log(x)), matrix(res)) + approx.deepEqual(math.map(matrix([[1, 2], [3, 4]]), x => log(x)), matrix([[0, 0.693147180559945], [1.098612288668110, 1.386294361119891]])) }) diff --git a/test/unit-tests/function/arithmetic/sqrt.test.js b/test/unit-tests/function/arithmetic/sqrt.test.js index 6d206693aa..c6e3ba0e18 100644 --- a/test/unit-tests/function/arithmetic/sqrt.test.js +++ b/test/unit-tests/function/arithmetic/sqrt.test.js @@ -80,10 +80,11 @@ describe('sqrt', function () { }) }) - it('should return the square root of each element of a matrix', function () { - assert.deepStrictEqual(sqrt([4, 9, 16, 25]), [2, 3, 4, 5]) - assert.deepStrictEqual(sqrt([[4, 9], [16, 25]]), [[2, 3], [4, 5]]) - assert.deepStrictEqual(sqrt(math.matrix([[4, 9], [16, 25]])), math.matrix([[2, 3], [4, 5]])) + it('should not operate on a matrix', function () { + assert.throws(() => sqrt([4, 9, 16, 25]), TypeError) + assert.deepStrictEqual(math.map([4, 9, 16, 25], sqrt), [2, 3, 4, 5]) + assert.deepStrictEqual(math.map([[4, 9], [16, 25]], sqrt), [[2, 3], [4, 5]]) + assert.deepStrictEqual(math.map(math.matrix([[4, 9], [16, 25]]), sqrt), math.matrix([[2, 3], [4, 5]])) }) it('should throw an error in case of invalid number of arguments', function () { diff --git a/test/unit-tests/function/arithmetic/square.test.js b/test/unit-tests/function/arithmetic/square.test.js index 6340b2c6fb..f3b34c50fb 100644 --- a/test/unit-tests/function/arithmetic/square.test.js +++ b/test/unit-tests/function/arithmetic/square.test.js @@ -57,10 +57,11 @@ describe('square', function () { assert.throws(function () { square('text') }) }) - it('should return the square of each element in a matrix', function () { - assert.deepStrictEqual(square([2, 3, 4, 5]), [4, 9, 16, 25]) - assert.deepStrictEqual(square(matrix([2, 3, 4, 5])), matrix([4, 9, 16, 25])) - assert.deepStrictEqual(square(matrix([[1, 2], [3, 4]])), matrix([[1, 4], [9, 16]])) + it('should not operate on a matrix', function () { + assert.throws(() => square([2, 3, 4, 5]), TypeError) + assert.deepStrictEqual(math.map([2, 3, 4, 5], square), [4, 9, 16, 25]) + assert.deepStrictEqual(math.map(matrix([2, 3, 4, 5]), square), matrix([4, 9, 16, 25])) + assert.deepStrictEqual(math.map(matrix([[1, 2], [3, 4]]), square), matrix([[1, 4], [9, 16]])) }) it('should LaTeX square', function () { diff --git a/test/unit-tests/function/probability/gamma.test.js b/test/unit-tests/function/probability/gamma.test.js index 6c3c74a0a4..239ed8a78e 100644 --- a/test/unit-tests/function/probability/gamma.test.js +++ b/test/unit-tests/function/probability/gamma.test.js @@ -145,12 +145,14 @@ describe('gamma', function () { assert.strictEqual(gamma(false), Infinity) }) - it('should calculate the gamma of each element in a matrix', function () { - assert.deepStrictEqual(gamma(math.matrix([0, 1, 2, 3, 4, 5])), math.matrix([Infinity, 1, 1, 2, 6, 24])) + it('should not operate on a matrix', function () { + assert.throws(() => gamma(math.matrix([0, 1, 2, 3, 4, 5])), /Function 'gamma' doesn't apply to matrices/) + assert.deepStrictEqual(math.map(math.matrix([0, 1, 2, 3, 4, 5]), gamma), math.matrix([Infinity, 1, 1, 2, 6, 24])) }) - it('should calculate the gamma of each element in an array', function () { - assert.deepStrictEqual(gamma([0, 1, 2, 3, 4, 5]), [Infinity, 1, 1, 2, 6, 24]) + it('should not operate on an array', function () { + assert.throws(() => gamma([0, 1, 2, 3, 4, 5]), TypeError) + assert.deepStrictEqual(math.map([0, 1, 2, 3, 4, 5], gamma), [Infinity, 1, 1, 2, 6, 24]) }) it('should throw en error if called with invalid number of arguments', function () { diff --git a/test/unit-tests/function/trigonometry/acos.test.js b/test/unit-tests/function/trigonometry/acos.test.js index d1e79fced3..422cb7974e 100644 --- a/test/unit-tests/function/trigonometry/acos.test.js +++ b/test/unit-tests/function/trigonometry/acos.test.js @@ -93,12 +93,13 @@ describe('acos', function () { assert.throws(function () { acos('string') }) }) - it('should calculate the arccos element-wise for arrays and matrices', function () { + it('should not operate on arrays and matrices', function () { + assert.throws(() => acos([1, 2, 3]), TypeError) // note: the results of acos(2) and acos(3) differs in octave // the next tests are verified with mathematica const acos123 = [0, complex(0, 1.316957896924817), complex(0, 1.762747174039086)] - approx.deepEqual(acos([1, 2, 3]), acos123) - approx.deepEqual(acos(matrix([1, 2, 3])), matrix(acos123)) + approx.deepEqual(math.map([1, 2, 3], acos), acos123) + approx.deepEqual(math.map(matrix([1, 2, 3]), acos), matrix(acos123)) }) it('should throw an error in case of invalid number of arguments', function () { diff --git a/test/unit-tests/function/trigonometry/acosh.test.js b/test/unit-tests/function/trigonometry/acosh.test.js index 48df0e807b..6fc4fa5d42 100644 --- a/test/unit-tests/function/trigonometry/acosh.test.js +++ b/test/unit-tests/function/trigonometry/acosh.test.js @@ -95,10 +95,12 @@ describe('acosh', function () { assert.throws(function () { acosh('string') }) }) - it('should calculate the arccos element-wise for arrays and matrices', function () { + it('should not operate on arrays and matrices', function () { + assert.throws(() => acosh([1, 2, 3]), TypeError) + assert.throws(() => acosh(matrix([1, 2, 3])), TypeError) const acosh123 = [0, 1.3169578969248167, 1.7627471740390860504] - approx.deepEqual(acosh([1, 2, 3]), acosh123) - approx.deepEqual(acosh(matrix([1, 2, 3])), matrix(acosh123)) + approx.deepEqual(math.map([1, 2, 3], acosh), acosh123) + approx.deepEqual(math.map(matrix([1, 2, 3]), acosh), matrix(acosh123)) }) it('should throw an error in case of invalid number of arguments', function () { diff --git a/test/unit-tests/function/trigonometry/acot.test.js b/test/unit-tests/function/trigonometry/acot.test.js index 1ab2ffdb58..7656fd5c74 100644 --- a/test/unit-tests/function/trigonometry/acot.test.js +++ b/test/unit-tests/function/trigonometry/acot.test.js @@ -97,11 +97,13 @@ describe('acot', function () { assert.throws(function () { acot('string') }) }) - it('should calculate the arccot element-wise for arrays and matrices', function () { + it('should not operate on arrays and matrices', function () { + assert.throws(() => acot([1, 2, 3]), TypeError) + assert.throws(() => acot(matrix([1, 2, 3])), TypeError) // matrix, array, range const acot123 = [pi / 4, 0.4636476090008, 0.3217505543966] - approx.deepEqual(acot([1, 2, 3]), acot123) - approx.deepEqual(acot(matrix([1, 2, 3])), matrix(acot123)) + approx.deepEqual(math.map([1, 2, 3], acot), acot123) + approx.deepEqual(math.map(matrix([1, 2, 3]), acot), matrix(acot123)) }) it('should throw an error in case of invalid number of arguments', function () { diff --git a/test/unit-tests/function/trigonometry/acoth.test.js b/test/unit-tests/function/trigonometry/acoth.test.js index cf3adea646..35e290b5af 100644 --- a/test/unit-tests/function/trigonometry/acoth.test.js +++ b/test/unit-tests/function/trigonometry/acoth.test.js @@ -98,10 +98,12 @@ describe('acoth', function () { assert.throws(function () { acoth('string') }) }) - it('should calculate the arccot element-wise for arrays and matrices', function () { + it('should not operate on arrays and matrices', function () { + assert.throws(() => acoth([1, 2, 3]), TypeError) + assert.throws(() => acoth(matrix([1, 2, 3])), TypeError) const acoth123 = [Infinity, 0.54930614433405, 0.34657359027997] - approx.deepEqual(acoth([1, 2, 3]), acoth123) - approx.deepEqual(acoth(matrix([1, 2, 3])), matrix(acoth123)) + approx.deepEqual(math.map([1, 2, 3], acoth), acoth123) + approx.deepEqual(math.map(matrix([1, 2, 3]), acoth), matrix(acoth123)) }) it('should throw an error in case of invalid number of arguments', function () { diff --git a/test/unit-tests/function/trigonometry/acsc.test.js b/test/unit-tests/function/trigonometry/acsc.test.js index 1196fea346..0ee7f105f6 100644 --- a/test/unit-tests/function/trigonometry/acsc.test.js +++ b/test/unit-tests/function/trigonometry/acsc.test.js @@ -122,10 +122,12 @@ describe('acsc', function () { assert.throws(function () { acsc('string') }) }) - it('should calculate the arccsc element-wise for arrays and matrices', function () { + it('should not operate on arrays and matrices', function () { + assert.throws(() => acsc([1, 2, 3]), TypeError) + assert.throws(() => acsc(matrix([1, 2, 3])), TypeError) const acsc123 = [pi / 2, pi / 6, 0.339836909454] - approx.deepEqual(acsc([1, 2, 3]), acsc123) - approx.deepEqual(acsc(matrix([1, 2, 3])), matrix(acsc123)) + approx.deepEqual(math.map([1, 2, 3], acsc), acsc123) + approx.deepEqual(math.map(matrix([1, 2, 3]), acsc), matrix(acsc123)) }) it('should throw an error in case of invalid number of arguments', function () { diff --git a/test/unit-tests/function/trigonometry/acsch.test.js b/test/unit-tests/function/trigonometry/acsch.test.js index 906ba938c2..507a4ce3fb 100644 --- a/test/unit-tests/function/trigonometry/acsch.test.js +++ b/test/unit-tests/function/trigonometry/acsch.test.js @@ -79,10 +79,12 @@ describe('acsch', function () { assert.throws(function () { acsch('string') }) }) - it('should calculate the arccsc element-wise for arrays and matrices', function () { + it('should not operate on arrays and matrices', function () { + assert.throws(() => acsch([1, 2, 3]), TypeError) + assert.throws(() => acsch(matrix([1, 2, 3])), TypeError) const acsch123 = [0.881373587019543025, 0.481211825059603447, 0.32745015023725844] - approx.deepEqual(acsch([1, 2, 3]), acsch123) - approx.deepEqual(acsch(matrix([1, 2, 3])), matrix(acsch123)) + approx.deepEqual(math.map([1, 2, 3], acsch), acsch123) + approx.deepEqual(math.map(matrix([1, 2, 3]), acsch), matrix(acsch123)) }) it('should throw an error in case of invalid number of arguments', function () { diff --git a/test/unit-tests/function/trigonometry/asec.test.js b/test/unit-tests/function/trigonometry/asec.test.js index defdf33ab5..660d4242bc 100644 --- a/test/unit-tests/function/trigonometry/asec.test.js +++ b/test/unit-tests/function/trigonometry/asec.test.js @@ -103,10 +103,12 @@ describe('asec', function () { assert.throws(function () { asec('string') }) }) - it('should calculate the arcsec element-wise for arrays and matrices', function () { + it('should not operate on arrays and matrices', function () { + assert.throws(() => asec([1, 2, 3]), TypeError) + assert.throws(() => asec(matrix([1, 2, 3])), TypeError) const asec123 = [0, pi / 3, 1.23095941734077468] - approx.deepEqual(asec([1, 2, 3]), asec123) - approx.deepEqual(asec(matrix([1, 2, 3])), matrix(asec123)) + approx.deepEqual(math.map([1, 2, 3], asec), asec123) + approx.deepEqual(math.map(matrix([1, 2, 3]), asec), matrix(asec123)) }) it('should throw an error in case of invalid number of arguments', function () { diff --git a/test/unit-tests/function/trigonometry/asech.test.js b/test/unit-tests/function/trigonometry/asech.test.js index 76a9fe82db..8192160f44 100644 --- a/test/unit-tests/function/trigonometry/asech.test.js +++ b/test/unit-tests/function/trigonometry/asech.test.js @@ -99,10 +99,12 @@ describe('asech', function () { assert.throws(function () { asech('string') }) }) - it('should calculate the arcsec element-wise for arrays and matrices', function () { + it('should not operate on arrays and matrices', function () { + assert.throws(() => asech([0, 1]), TypeError) + assert.throws(() => asech(matrix([0, 1])), TypeError) const asech01 = [Infinity, 0] - assert.deepStrictEqual(asech([0, 1]), asech01) - assert.deepStrictEqual(asech(matrix([0, 1])), matrix(asech01)) + assert.deepStrictEqual(math.map([0, 1], asech), asech01) + assert.deepStrictEqual(math.map(matrix([0, 1]), asech), matrix(asech01)) }) it('should throw an error in case of invalid number of arguments', function () { diff --git a/test/unit-tests/function/trigonometry/asin.test.js b/test/unit-tests/function/trigonometry/asin.test.js index 2d6b54c218..84f0bdae47 100644 --- a/test/unit-tests/function/trigonometry/asin.test.js +++ b/test/unit-tests/function/trigonometry/asin.test.js @@ -116,15 +116,17 @@ describe('asin', function () { assert.throws(function () { asin('string') }) }) - it('should calculate the arcsin element-wise for arrays and matrices', function () { + it('should not operate on arrays and matrices', function () { + assert.throws(() => asin([1, 2, 3]), TypeError) + assert.throws(() => asin(matrix([1, 2, 3])), TypeError) // note: the results of asin(2) and asin(3) differs in octave // the next tests are verified with mathematica const asin123 = [ 1.57079632679490, complex(1.57079632679490, -1.31695789692482), complex(1.57079632679490, -1.76274717403909)] - approx.deepEqual(asin([1, 2, 3]), asin123) - approx.deepEqual(asin(matrix([1, 2, 3])), matrix(asin123)) + approx.deepEqual(math.map([1, 2, 3], asin), asin123) + approx.deepEqual(math.map(matrix([1, 2, 3]), asin), matrix(asin123)) }) it('should throw an error in case of invalid number of arguments', function () { diff --git a/test/unit-tests/function/trigonometry/asinh.test.js b/test/unit-tests/function/trigonometry/asinh.test.js index fd0a3a0c23..bf0b13ecec 100644 --- a/test/unit-tests/function/trigonometry/asinh.test.js +++ b/test/unit-tests/function/trigonometry/asinh.test.js @@ -80,10 +80,12 @@ describe('asinh', function () { assert.throws(function () { asinh('string') }) }) - it('should calculate the arcsin element-wise for arrays and matrices', function () { + it('should not operate on arrays and matrices', function () { + assert.throws(() => asinh([1, 2, 3]), TypeError) + assert.throws(() => asinh(matrix([1, 2, 3])), TypeError) const asinh123 = [0.881373587019543025, 1.4436354751788103, 1.8184464592320668] - approx.deepEqual(asinh([1, 2, 3]), asinh123) - approx.deepEqual(asinh(matrix([1, 2, 3])), matrix(asinh123)) + approx.deepEqual(math.map([1, 2, 3], asinh), asinh123) + approx.deepEqual(math.map(matrix([1, 2, 3]), asinh), matrix(asinh123)) }) it('should throw an error in case of invalid number of arguments', function () { diff --git a/test/unit-tests/function/trigonometry/atan.test.js b/test/unit-tests/function/trigonometry/atan.test.js index c64135aead..3e1d94b199 100644 --- a/test/unit-tests/function/trigonometry/atan.test.js +++ b/test/unit-tests/function/trigonometry/atan.test.js @@ -92,11 +92,13 @@ describe('atan', function () { assert.throws(function () { atan('string') }) }) - it('should calculate the arctan element-wise for arrays and matrices', function () { + it('should not operate on arrays and matrices', function () { + assert.throws(() => atan([1, 2, 3]), TypeError) + assert.throws(() => atan(matrix([1, 2, 3])), TypeError) // matrix, array, range const atan123 = [0.785398163397448, 1.107148717794090, 1.249045772398254] - approx.deepEqual(atan([1, 2, 3]), atan123) - approx.deepEqual(atan(matrix([1, 2, 3])), matrix(atan123)) + approx.deepEqual(math.map([1, 2, 3], atan), atan123) + approx.deepEqual(math.map(matrix([1, 2, 3]), atan), matrix(atan123)) }) it('should throw an error in case of invalid number of arguments', function () { diff --git a/test/unit-tests/function/trigonometry/atanh.test.js b/test/unit-tests/function/trigonometry/atanh.test.js index b4442eadde..2cd308b694 100644 --- a/test/unit-tests/function/trigonometry/atanh.test.js +++ b/test/unit-tests/function/trigonometry/atanh.test.js @@ -97,10 +97,12 @@ describe('atanh', function () { assert.throws(function () { atanh('string') }) }) - it('should calculate the arctan element-wise for arrays and matrices', function () { + it('should not operate on arrays and matrices', function () { + assert.throws(() => atanh([-1, 0, 1]), TypeError) + assert.throws(() => atanh(matrix([-1, 0, 1])), TypeError) const atanh101 = [-Infinity, 0, Infinity] - assert.deepStrictEqual(atanh([-1, 0, 1]), atanh101) - assert.deepStrictEqual(atanh(matrix([-1, 0, 1])), matrix(atanh101)) + assert.deepStrictEqual(math.map([-1, 0, 1], atanh), atanh101) + assert.deepStrictEqual(math.map(matrix([-1, 0, 1]), atanh), matrix(atanh101)) }) it('should throw an error in case of invalid number of arguments', function () { diff --git a/test/unit-tests/function/trigonometry/cos.test.js b/test/unit-tests/function/trigonometry/cos.test.js index 8d75cb73f8..896e79911b 100644 --- a/test/unit-tests/function/trigonometry/cos.test.js +++ b/test/unit-tests/function/trigonometry/cos.test.js @@ -101,12 +101,14 @@ describe('cos', function () { const cos123 = [0.540302305868140, -0.41614683654714, -0.989992496600445] - it('should return the cos of each element of a matrix', function () { - approx.deepEqual(cos(matrix([1, 2, 3])), matrix(cos123)) + it('should not operate on a matrix', function () { + assert.throws(() => cos(matrix([1, 2, 3])), TypeError) + approx.deepEqual(math.map(matrix([1, 2, 3]), cos), matrix(cos123)) }) - it('should return the cos of each element of an array', function () { - approx.deepEqual(cos([1, 2, 3]), cos123) + it('should not operate on an array', function () { + assert.throws(() => cos([1, 2, 3]), TypeError) + approx.deepEqual(math.map([1, 2, 3], cos), cos123) }) it('should throw an error in case of invalid number of arguments', function () { diff --git a/test/unit-tests/function/trigonometry/cosh.test.js b/test/unit-tests/function/trigonometry/cosh.test.js index 3c53fffe98..5b6370a695 100644 --- a/test/unit-tests/function/trigonometry/cosh.test.js +++ b/test/unit-tests/function/trigonometry/cosh.test.js @@ -72,12 +72,14 @@ describe('cosh', function () { const cosh123 = [1.5430806348152, 3.7621956910836, 10.067661995778] - it('should return the cosh of each element of an array', function () { - approx.deepEqual(cosh([1, 2, 3]), cosh123) + it('should not operate on an array', function () { + assert.throws(() => cosh([1, 2, 3]), TypeError) + approx.deepEqual(math.map([1, 2, 3], cosh), cosh123) }) - it('should return the cosh of each element of a matrix', function () { - approx.deepEqual(cosh(matrix([1, 2, 3])), matrix(cosh123)) + it('should not operate on a matrix', function () { + assert.throws(() => cosh(matrix([1, 2, 3])), TypeError) + approx.deepEqual(math.map(matrix([1, 2, 3]), cosh), matrix(cosh123)) }) it('should throw an error in case of invalid number of arguments', function () { diff --git a/test/unit-tests/function/trigonometry/cot.test.js b/test/unit-tests/function/trigonometry/cot.test.js index ed347e355c..32317966aa 100644 --- a/test/unit-tests/function/trigonometry/cot.test.js +++ b/test/unit-tests/function/trigonometry/cot.test.js @@ -78,12 +78,14 @@ describe('cot', function () { const cot123 = [0.642092615934331, -0.457657554360286, -7.015252551434534] - it('should return the cotan of each element of an array', function () { - approx.deepEqual(cot([1, 2, 3]), cot123) + it('should not operate on an array', function () { + assert.throws(() => cot([1, 2, 3]), TypeError) + approx.deepEqual(math.map([1, 2, 3], cot), cot123) }) - it('should return the cotan of each element of a matrix', function () { - approx.deepEqual(cot(matrix([1, 2, 3])), matrix(cot123)) + it('should not operate on a matrix', function () { + assert.throws(() => cot(matrix([1, 2, 3])), TypeError) + approx.deepEqual(math.map(matrix([1, 2, 3]), cot), matrix(cot123)) }) it('should throw an error in case of invalid number of arguments', function () { diff --git a/test/unit-tests/function/trigonometry/coth.test.js b/test/unit-tests/function/trigonometry/coth.test.js index 7b8e887101..eaa78000da 100644 --- a/test/unit-tests/function/trigonometry/coth.test.js +++ b/test/unit-tests/function/trigonometry/coth.test.js @@ -61,12 +61,14 @@ describe('coth', function () { const coth123 = [1.3130352854993, 1.0373147207275, 1.0049698233137] - it('should return the coth of each element of an array', function () { - approx.deepEqual(coth([1, 2, 3]), coth123) + it('should not operate on an array', function () { + assert.throws(() => coth([1, 2, 3]), TypeError) + approx.deepEqual(math.map([1, 2, 3], coth), coth123) }) - it('should return the coth of each element of a matrix', function () { - approx.deepEqual(coth(matrix([1, 2, 3])), matrix(coth123)) + it('should not operate on a matrix', function () { + assert.throws(() => coth(matrix([1, 2, 3])), TypeError) + approx.deepEqual(math.map(matrix([1, 2, 3]), coth), matrix(coth123)) }) it('should throw an error in case of invalid number of arguments', function () { diff --git a/test/unit-tests/function/trigonometry/csc.test.js b/test/unit-tests/function/trigonometry/csc.test.js index a5e3dbafb1..02ebaeace0 100644 --- a/test/unit-tests/function/trigonometry/csc.test.js +++ b/test/unit-tests/function/trigonometry/csc.test.js @@ -73,12 +73,14 @@ describe('csc', function () { const csc123 = [1.18839510577812, 1.09975017029462, 7.08616739573719] - it('should return the cosecant of each element of an array', function () { - approx.deepEqual(csc([1, 2, 3]), csc123) + it('should not operate on an array', function () { + assert.throws(() => csc([1, 2, 3]), TypeError) + approx.deepEqual(math.map([1, 2, 3], csc), csc123) }) - it('should return the cosecant of each element of a matrix', function () { - approx.deepEqual(csc(matrix([1, 2, 3])), matrix(csc123)) + it('should not operate on a matrix', function () { + assert.throws(() => csc(matrix([1, 2, 3])), TypeError) + approx.deepEqual(math.map(matrix([1, 2, 3]), csc), matrix(csc123)) }) it('should throw an error in case of invalid number of arguments', function () { diff --git a/test/unit-tests/function/trigonometry/csch.test.js b/test/unit-tests/function/trigonometry/csch.test.js index 170e787c8f..a75ec4fb5a 100644 --- a/test/unit-tests/function/trigonometry/csch.test.js +++ b/test/unit-tests/function/trigonometry/csch.test.js @@ -64,12 +64,14 @@ describe('csch', function () { const csch123 = [0.85091812823932, 0.27572056477178, 0.099821569668823] - it('should return the csch of each element of an array', function () { - approx.deepEqual(csch([1, 2, 3]), csch123) + it('should not operate on an array', function () { + assert.throws(() => csch([1, 2, 3]), TypeError) + approx.deepEqual(math.map([1, 2, 3], csch), csch123) }) - it('should return the csch of each element of a matrix', function () { - approx.deepEqual(csch(matrix([1, 2, 3])), matrix(csch123)) + it('should not operate on a matrix', function () { + assert.throws(() => csch(matrix([1, 2, 3])), TypeError) + approx.deepEqual(math.map(matrix([1, 2, 3]), csch), matrix(csch123)) }) it('should throw an error in case of invalid number of arguments', function () { diff --git a/test/unit-tests/function/trigonometry/sec.test.js b/test/unit-tests/function/trigonometry/sec.test.js index 79b70c1efc..b8e49fa55c 100644 --- a/test/unit-tests/function/trigonometry/sec.test.js +++ b/test/unit-tests/function/trigonometry/sec.test.js @@ -89,12 +89,14 @@ describe('sec', function () { const sec123 = [1.85081571768093, -2.40299796172238, -1.01010866590799] - it('should return the secant of each element of an array', function () { - approx.deepEqual(sec([1, 2, 3]), sec123) + it('should not operate on an array', function () { + assert.throws(() => sec([1, 2, 3]), TypeError) + approx.deepEqual(math.map([1, 2, 3], sec), sec123) }) - it('should return the secant of each element of a matrix', function () { - approx.deepEqual(sec(matrix([1, 2, 3])), matrix(sec123)) + it('should not operate on a matrix', function () { + assert.throws(() => sec(matrix([1, 2, 3])), TypeError) + approx.deepEqual(math.map(matrix([1, 2, 3]), sec), matrix(sec123)) }) it('should throw an error in case of invalid number of arguments', function () { diff --git a/test/unit-tests/function/trigonometry/sech.test.js b/test/unit-tests/function/trigonometry/sech.test.js index fe25a1e9ec..4f5c885fd7 100644 --- a/test/unit-tests/function/trigonometry/sech.test.js +++ b/test/unit-tests/function/trigonometry/sech.test.js @@ -62,12 +62,14 @@ describe('sech', function () { const sech123 = [0.64805427366389, 0.26580222883408, 0.099327927419433] - it('should return the sech of each element of an array', function () { - approx.deepEqual(sech([1, 2, 3]), sech123) + it('should not operate on an array', function () { + assert.throws(() => sech([1, 2, 3]), TypeError) + approx.deepEqual(math.map([1, 2, 3], sech), sech123) }) - it('should return the sech of each element of a matrix', function () { - approx.deepEqual(sech(matrix([1, 2, 3])), matrix(sech123)) + it('should not operate on a matrix', function () { + assert.throws(() => sech(matrix([1, 2, 3])), TypeError) + approx.deepEqual(math.map(matrix([1, 2, 3]), sech), matrix(sech123)) }) it('should throw an error in case of invalid number of arguments', function () { diff --git a/test/unit-tests/function/trigonometry/sin.test.js b/test/unit-tests/function/trigonometry/sin.test.js index cf402b0b81..50e577043f 100644 --- a/test/unit-tests/function/trigonometry/sin.test.js +++ b/test/unit-tests/function/trigonometry/sin.test.js @@ -104,12 +104,14 @@ describe('sin', function () { const sin123 = [0.84147098480789, 0.909297426825682, 0.141120008059867] - it('should return the sin of each element of an array', function () { - approx.deepEqual(sin([1, 2, 3]), sin123, EPSILON) + it('should not operate on an array', function () { + assert.throws(() => sin([1, 2, 3]), TypeError) + approx.deepEqual(math.map([1, 2, 3], sin), sin123, EPSILON) }) - it('should return the sin of each element of a matrix', function () { - approx.deepEqual(sin(matrix([1, 2, 3])), matrix(sin123), EPSILON) + it('should not operate on a matrix', function () { + assert.throws(() => sin(matrix([1, 2, 3])), TypeError) + approx.deepEqual(math.map(matrix([1, 2, 3]), sin), matrix(sin123), EPSILON) }) it('should throw an error in case of invalid number of arguments', function () { diff --git a/test/unit-tests/function/trigonometry/sinh.test.js b/test/unit-tests/function/trigonometry/sinh.test.js index b0871b721f..a16b463410 100644 --- a/test/unit-tests/function/trigonometry/sinh.test.js +++ b/test/unit-tests/function/trigonometry/sinh.test.js @@ -96,12 +96,14 @@ describe('sinh', function () { const sinh123 = [1.1752011936438014, 3.626860407847, 10.01787492741] - it('should return the sinh of each element of an array', function () { - approx.deepEqual(sinh([1, 2, 3]), sinh123, EPSILON) + it('should not operate on an array', function () { + assert.throws(() => sinh([1, 2, 3]), TypeError) + approx.deepEqual(math.map([1, 2, 3], sinh), sinh123, EPSILON) }) - it('should return the sinh of each element of a matrix', function () { - approx.deepEqual(sinh(matrix([1, 2, 3])), matrix(sinh123), EPSILON) + it('should not operate on a matrix', function () { + assert.throws(() => sinh(matrix([1, 2, 3])), TypeError) + approx.deepEqual(math.map(matrix([1, 2, 3]), sinh), matrix(sinh123), EPSILON) }) it('should throw an error in case of invalid number of arguments', function () { diff --git a/test/unit-tests/function/trigonometry/tan.test.js b/test/unit-tests/function/trigonometry/tan.test.js index 2b675d9446..e83bc40564 100644 --- a/test/unit-tests/function/trigonometry/tan.test.js +++ b/test/unit-tests/function/trigonometry/tan.test.js @@ -73,12 +73,14 @@ describe('tan', function () { const tan123 = [1.557407724654902, -2.185039863261519, -0.142546543074278] - it('should return the tan of each element of an array', function () { - approx.deepEqual(tan([1, 2, 3]), tan123) + it('should not operate on an array', function () { + assert.throws(() => tan([1, 2, 3]), TypeError) + approx.deepEqual(math.map([1, 2, 3], tan), tan123) }) - it('should return the tan of each element of a matrix', function () { - approx.deepEqual(tan(matrix([1, 2, 3])), matrix(tan123)) + it('should not operate on a matrix', function () { + assert.throws(() => tan(matrix([1, 2, 3])), TypeError) + approx.deepEqual(math.map(matrix([1, 2, 3]), tan), matrix(tan123)) }) it('should throw an error in case of invalid number of arguments', function () { diff --git a/test/unit-tests/function/trigonometry/tanh.test.js b/test/unit-tests/function/trigonometry/tanh.test.js index 0f42f3cd7b..0bcf84683d 100644 --- a/test/unit-tests/function/trigonometry/tanh.test.js +++ b/test/unit-tests/function/trigonometry/tanh.test.js @@ -72,12 +72,14 @@ describe('tanh', function () { const tanh123 = [0.76159415595576, 0.96402758007582, 0.99505475368673] - it('should return the tanh of each element of an array', function () { - approx.deepEqual(tanh([1, 2, 3]), tanh123) + it('should not operate on an array', function () { + assert.throws(() => tanh([1, 2, 3]), TypeError) + approx.deepEqual(math.map([1, 2, 3], tanh), tanh123) }) - it('should return the tanh of each element of a matrix', function () { - approx.deepEqual(tanh(matrix([1, 2, 3])), matrix(tanh123)) + it('should not operate on a matrix', function () { + assert.throws(() => tanh(matrix([1, 2, 3])), TypeError) + approx.deepEqual(math.map(matrix([1, 2, 3]), tanh), matrix(tanh123)) }) it('should throw an error in case of invalid number of arguments', function () { diff --git a/types/index.d.ts b/types/index.d.ts index 660f0e44bd..92ac8150bd 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -884,8 +884,7 @@ declare namespace math { add(x: MathType, y: MathType): MathType /** - * Calculate the cubic root of a value. For matrices, the function is - * evaluated element wise. + * Calculate the cubic root of a value. * @param x Value for which to calculate the cubic root. * @param allRoots Optional, false by default. Only applicable when x is * a number or complex number. If true, all complex roots are returned, @@ -894,10 +893,8 @@ declare namespace math { */ cbrt(x: number, allRoots?: boolean): number cbrt(x: BigNumber, allRoots?: boolean): BigNumber - cbrt(x: Fraction, allRoots?: boolean): Fraction + cbrt(x: Fraction, allroots?: boolean): Fraction cbrt(x: Complex, allRoots?: boolean): Complex - cbrt(x: MathArray, allRoots?: boolean): MathArray - cbrt(x: Matrix, allRoots?: boolean): Matrix cbrt(x: Unit, allRoots?: boolean): Unit // Rounding functions, grouped for similarity, even though it breaks @@ -1073,14 +1070,13 @@ declare namespace math { lcm(a: Matrix, b: Matrix): Matrix /** - * Calculate the logarithm of a value. For matrices, the function is - * evaluated element wise. + * Calculate the logarithm of a value. * @param x Value for which to calculate the logarithm. * @param base Optional base for the logarithm. If not provided, the * natural logarithm of x is calculated. Default value: e. * @returns Returns the logarithm of x */ - log( + log( x: T, base?: number | BigNumber | Complex ): NoLiteralType @@ -1199,21 +1195,19 @@ declare namespace math { sign(x: Unit): Unit /** - * Calculate the square root of a value. For matrices, the function is - * evaluated element wise. + * Calculate the square root of a value. For matrices, use either + * sqrtm for the matrix square root, or map(M, sqrt) to take the + * square root element wise. * @param x Value for which to calculate the square root * @returns Returns the square root of x */ - sqrt(x: number): number + sqrt(x: number): number | Complex sqrt(x: BigNumber): BigNumber sqrt(x: Complex): Complex - sqrt(x: MathArray): MathArray - sqrt(x: Matrix): Matrix sqrt(x: Unit): Unit /** - * Compute the square of a value, x * x. For matrices, the function is - * evaluated element wise. + * Compute the square of a value, x * x. * @param x Number for which to calculate the square * @returns Squared value */ @@ -1221,8 +1215,6 @@ declare namespace math { square(x: BigNumber): BigNumber square(x: Fraction): Fraction square(x: Complex): Complex - square(x: MathArray): MathArray - square(x: Matrix): Matrix square(x: Unit): Unit /** @@ -2004,13 +1996,11 @@ declare namespace math { /** * Compute the gamma function of a value using Lanczos approximation for * small values, and an extended Stirling approximation for large - * values. For matrices, the function is evaluated element wise. + * values. * @param n A real or complex number * @returns The gamma of n */ - gamma( - n: T - ): NoLiteralType + gamma(n: T): NoLiteralType /** * Calculate the Kullback-Leibler (KL) divergence between two @@ -2681,133 +2671,108 @@ declare namespace math { ************************************************************************/ /** - * Calculate the inverse cosine of a value. For matrices, the function - * is evaluated element wise. + * Calculate the inverse cosine of a value. * @param x Function input * @returns The arc cosine of x */ - acos(x: number): number + acos(x: number): number | Complex acos(x: BigNumber): BigNumber acos(x: Complex): Complex - acos(x: MathArray): MathArray - acos(x: Matrix): Matrix /** * Calculate the hyperbolic arccos of a value, defined as acosh(x) = - * ln(sqrt(x^2 - 1) + x). For matrices, the function is evaluated - * element wise. + * ln(sqrt(x^2 - 1) + x). * @param x Function input * @returns The hyperbolic arccosine of x */ - acosh(x: number): number + acosh(x: number): number | Complex acosh(x: BigNumber): BigNumber acosh(x: Complex): Complex - acosh(x: MathArray): MathArray - acosh(x: Matrix): Matrix /** - * Calculate the inverse cotangent of a value. For matrices, the - * function is evaluated element wise. + * Calculate the inverse cotangent of a value. * @param x Function input * @returns The arc cotangent of x */ acot(x: number): number acot(x: BigNumber): BigNumber - acot(x: MathArray): MathArray - acot(x: Matrix): Matrix + acot(x: Complex): Complex /** * Calculate the hyperbolic arccotangent of a value, defined as acoth(x) - * = (ln((x+1)/x) + ln(x/(x-1))) / 2. For matrices, the function is - * evaluated element wise. + * = (ln((x+1)/x) + ln(x/(x-1))) / 2. * @param x Function input * @returns The hyperbolic arccotangent of x */ acoth(x: number): number acoth(x: BigNumber): BigNumber - acoth(x: MathArray): MathArray - acoth(x: Matrix): Matrix + acoth(x: Complex): Complex /** - * Calculate the inverse cosecant of a value. For matrices, the function - * is evaluated element wise. + * Calculate the inverse cosecant of a value. * @param x Function input * @returns The arc cosecant of x */ - acsc(x: number): number + acsc(x: number): number | Complex acsc(x: BigNumber): BigNumber - acsc(x: MathArray): MathArray - acsc(x: Matrix): Matrix + acsc(x: Complex): Complex /** * Calculate the hyperbolic arccosecant of a value, defined as acsch(x) - * = ln(1/x + sqrt(1/x^2 + 1)). For matrices, the function is evaluated - * element wise. + * = ln(1/x + sqrt(1/x^2 + 1)). * @param x Function input * @returns The hyperbolic arccosecant of x */ acsch(x: number): number acsch(x: BigNumber): BigNumber - acsch(x: MathArray): MathArray - acsch(x: Matrix): Matrix + acsch(x: Complex): Complex /** - * Calculate the inverse secant of a value. For matrices, the function - * is evaluated element wise. + * Calculate the inverse secant of a value. * @param x Function input * @returns The arc secant of x */ - asec(x: number): number + asec(x: number): number | Complex asec(x: BigNumber): BigNumber - asec(x: MathArray): MathArray - asec(x: Matrix): Matrix + asec(x: Complex): Complex /** * Calculate the hyperbolic arcsecant of a value, defined as asech(x) = - * ln(sqrt(1/x^2 - 1) + 1/x). For matrices, the function is evaluated - * element wise. + * ln(sqrt(1/x^2 - 1) + 1/x). * @param x Function input * @returns The hyperbolic arcsecant of x */ - asech(x: number): number + asech(x: number): number | Complex asech(x: BigNumber): BigNumber - asech(x: MathArray): MathArray - asech(x: Matrix): Matrix + asech(x: Complex): Complex /** - * Calculate the inverse sine of a value. For matrices, the function is - * evaluated element wise. + * Calculate the inverse sine of a value. * @param x Function input * @returns The arc sine of x */ - asin(x: number): number + asin(x: number): number | Complex asin(x: BigNumber): BigNumber asin(x: Complex): Complex - asin(x: MathArray): MathArray - asin(x: Matrix): Matrix /** * Calculate the hyperbolic arcsine of a value, defined as asinh(x) = - * ln(x + sqrt(x^2 + 1)). For matrices, the function is evaluated - * element wise. + * ln(x + sqrt(x^2 + 1)). * @param x Function input * @returns The hyperbolic arcsine of x */ asinh(x: number): number asinh(x: BigNumber): BigNumber - asinh(x: MathArray): MathArray - asinh(x: Matrix): Matrix + asinh(x: Complex): Complex /** - * Calculate the inverse tangent of a value. For matrices, the function - * is evaluated element wise. + * Calculate the inverse tangent of a value. * @param x Function input * @returns The arc tangent of x */ atan(x: number): number atan(x: BigNumber): BigNumber - atan(x: MathArray): MathArray - atan(x: Matrix): Matrix + atan(x: Complex): Complex /** * Calculate the inverse tangent function with two arguments, y/x. By @@ -2821,156 +2786,127 @@ declare namespace math { /** * Calculate the hyperbolic arctangent of a value, defined as atanh(x) = - * ln((1 + x)/(1 - x)) / 2. For matrices, the function is evaluated - * element wise. + * ln((1 + x)/(1 - x)) / 2. * @param x Function input * @returns The hyperbolic arctangent of x */ - atanh(x: number): number + atanh(x: number): number | Complex atanh(x: BigNumber): BigNumber - atanh(x: MathArray): MathArray - atanh(x: Matrix): Matrix + atanh(x: Complex): Complex /** - * Calculate the cosine of a value. For matrices, the function is - * evaluated element wise. + * Calculate the cosine of a value. * @param x Function input * @returns The cosine of x */ cos(x: number | Unit): number cos(x: BigNumber): BigNumber cos(x: Complex): Complex - cos(x: MathArray): MathArray - cos(x: Matrix): Matrix /** * Calculate the hyperbolic cosine of a value, defined as cosh(x) = 1/2 - * * (exp(x) + exp(-x)). For matrices, the function is evaluated element - * wise. + * * (exp(x) + exp(-x)). * @param x Function input * @returns The hyperbolic cosine of x */ cosh(x: number | Unit): number cosh(x: BigNumber): BigNumber cosh(x: Complex): Complex - cosh(x: MathArray): MathArray - cosh(x: Matrix): Matrix /** * Calculate the cotangent of a value. cot(x) is defined as 1 / tan(x). - * For matrices, the function is evaluated element wise. * @param x Function input * @returns The cotangent of x */ cot(x: number | Unit): number + cot(x: BigNumber): BigNumber cot(x: Complex): Complex - cot(x: MathArray): MathArray - cot(x: Matrix): Matrix /** * Calculate the hyperbolic cotangent of a value, defined as coth(x) = 1 - * / tanh(x). For matrices, the function is evaluated element wise. + * / tanh(x). * @param x Function input * @returns The hyperbolic cotangent of x */ coth(x: number | Unit): number + coth(x: BigNumber): BigNumber coth(x: Complex): Complex - coth(x: MathArray): MathArray - coth(x: Matrix): Matrix /** - * Calculate the cosecant of a value, defined as csc(x) = 1/sin(x). For - * matrices, the function is evaluated element wise. + * Calculate the cosecant of a value, defined as csc(x) = 1/sin(x). * @param x Function input * @returns The cosecant hof x */ csc(x: number | Unit): number + csc(x: BigNumber): BigNumber csc(x: Complex): Complex - csc(x: MathArray): MathArray - csc(x: Matrix): Matrix /** * Calculate the hyperbolic cosecant of a value, defined as csch(x) = 1 - * / sinh(x). For matrices, the function is evaluated element wise. + * / sinh(x). * @param x Function input * @returns The hyperbolic cosecant of x */ csch(x: number | Unit): number + csch(x: BigNumber): BigNumber csch(x: Complex): Complex - csch(x: MathArray): MathArray - csch(x: Matrix): Matrix /** - * Calculate the secant of a value, defined as sec(x) = 1/cos(x). For - * matrices, the function is evaluated element wise. + * Calculate the secant of a value, defined as sec(x) = 1/cos(x). * @param x Function input * @returns The secant of x */ sec(x: number | Unit): number + sec(x: BigNumber): BigNumber sec(x: Complex): Complex - sec(x: MathArray): MathArray - sec(x: Matrix): Matrix /** * Calculate the hyperbolic secant of a value, defined as sech(x) = 1 / - * cosh(x). For matrices, the function is evaluated element wise. + * cosh(x). * @param x Function input * @returns The hyperbolic secant of x */ sech(x: number | Unit): number + sech(x: BigNumber): BigNumber sech(x: Complex): Complex - sech(x: MathArray): MathArray - sech(x: Matrix): Matrix /** - * Calculate the sine of a value. For matrices, the function is - * evaluated element wise. + * Calculate the sine of a value. * @param x Function input * @returns The sine of x */ sin(x: number | Unit): number sin(x: BigNumber): BigNumber sin(x: Complex): Complex - sin(x: MathArray): MathArray - sin(x: Matrix): Matrix /** * Calculate the hyperbolic sine of a value, defined as sinh(x) = 1/2 * - * (exp(x) - exp(-x)). For matrices, the function is evaluated element - * wise. + * (exp(x) - exp(-x)). * @param x Function input * @returns The hyperbolic sine of x */ sinh(x: number | Unit): number sinh(x: BigNumber): BigNumber sinh(x: Complex): Complex - sinh(x: MathArray): MathArray - sinh(x: Matrix): Matrix /** * Calculate the tangent of a value. tan(x) is equal to sin(x) / cos(x). - * For matrices, the function is evaluated element wise. * @param x Function input * @returns The tangent of x */ tan(x: number | Unit): number tan(x: BigNumber): BigNumber tan(x: Complex): Complex - tan(x: MathArray): MathArray - tan(x: Matrix): Matrix /** * Calculate the hyperbolic tangent of a value, defined as tanh(x) = - * (exp(2 * x) - 1) / (exp(2 * x) + 1). For matrices, the function is - * evaluated element wise. + * (exp(2 * x) - 1) / (exp(2 * x) + 1). * @param x Function input * @returns The hyperbolic tangent of x */ tanh(x: number | Unit): number tanh(x: BigNumber): BigNumber tanh(x: Complex): Complex - tanh(x: MathArray): MathArray - tanh(x: Matrix): Matrix /************************************************************************* * Unit functions diff --git a/types/index.ts b/types/index.ts index 96f3e47c62..f239dcbc97 100644 --- a/types/index.ts +++ b/types/index.ts @@ -209,8 +209,13 @@ Complex numbers examples // 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) + const p: math.PolarCoordinates = { + r: math.sqrt(2) as number, // must be real but a sqrt could be Complex + phi: math.pi / 4 + } + const c: math.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 @@ -337,7 +342,7 @@ Matrices examples const _clone: math.Matrix = a.clone() // perform operations with matrices - math.sqrt(a) + math.map(a, math.sqrt) math.factorial(a) // create and manipulate matrices. Arrays and Matrices can be used mixed.