diff --git a/AUTHORS b/AUTHORS index 6c5e9274d7..a24654e85e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -233,5 +233,7 @@ BuildTools Anik Patel <74193405+Bobingstern@users.noreply.github.com> Vrushaket Chaudhari <82214275+vrushaket@users.noreply.github.com> Praise Nnamonu <110940850+praisennamonu1@users.noreply.github.com> +Vincent Tam +vrushaket # Generated by tools/update-authors.js diff --git a/examples/advanced/custom_evaluate_using_import.js b/examples/advanced/custom_evaluate_using_import.js index 4546e24f4b..34e5583b25 100644 --- a/examples/advanced/custom_evaluate_using_import.js +++ b/examples/advanced/custom_evaluate_using_import.js @@ -11,7 +11,7 @@ const divide = (a, b) => a / b // create a mathjs instance with hardly any functions // there are some functions created which are used internally by evaluate though, -// for example by the Unit class which has dependencies on addScalar, subtract, +// for example by the Unit class which has dependencies on addScalar, subtractScalar, // multiplyScalar, etc. const math = create(evaluateDependencies) diff --git a/src/factoriesAny.js b/src/factoriesAny.js index bfbac393f2..74ab542b7a 100644 --- a/src/factoriesAny.js +++ b/src/factoriesAny.js @@ -33,6 +33,7 @@ export { createUnaryPlus } from './function/arithmetic/unaryPlus.js' export { createAbs } from './function/arithmetic/abs.js' export { createApply } from './function/matrix/apply.js' export { createAddScalar } from './function/arithmetic/addScalar.js' +export { createSubtractScalar } from './function/arithmetic/subtractScalar.js' export { createCbrt } from './function/arithmetic/cbrt.js' export { createCeil } from './function/arithmetic/ceil.js' export { createCube } from './function/arithmetic/cube.js' diff --git a/src/factoriesNumber.js b/src/factoriesNumber.js index 988eb27e0e..3d2ee31ef8 100644 --- a/src/factoriesNumber.js +++ b/src/factoriesNumber.js @@ -101,6 +101,7 @@ export const createUnaryMinus = /* #__PURE__ */ createNumberFactory('unaryMinus' export const createUnaryPlus = /* #__PURE__ */ createNumberFactory('unaryPlus', unaryPlusNumber) export const createAbs = /* #__PURE__ */ createNumberFactory('abs', absNumber) export const createAddScalar = /* #__PURE__ */ createNumberFactory('addScalar', addNumber) +export const createSubtractScalar = /* #__PURE__ */ createNumberFactory('subtractScalar', subtractNumber) export const createCbrt = /* #__PURE__ */ createNumberFactory('cbrt', cbrtNumber) export { createCeilNumber as createCeil } from './function/arithmetic/ceil.js' export const createCube = /* #__PURE__ */ createNumberFactory('cube', cubeNumber) diff --git a/src/function/algebra/decomposition/lup.js b/src/function/algebra/decomposition/lup.js index d841aaffd5..29e3f01e20 100644 --- a/src/function/algebra/decomposition/lup.js +++ b/src/function/algebra/decomposition/lup.js @@ -9,7 +9,7 @@ const dependencies = [ 'addScalar', 'divideScalar', 'multiplyScalar', - 'subtract', + 'subtractScalar', 'larger', 'equalScalar', 'unaryMinus', @@ -26,7 +26,7 @@ export const createLup = /* #__PURE__ */ factory(name, dependencies, ( addScalar, divideScalar, multiplyScalar, - subtract, + subtractScalar, larger, equalScalar, unaryMinus, @@ -119,7 +119,7 @@ export const createLup = /* #__PURE__ */ factory(name, dependencies, ( // s = l[i, k] - data[k, j] s = addScalar(s, multiplyScalar(data[i][k], data[k][j])) } - data[i][j] = subtract(data[i][j], s) + data[i][j] = subtractScalar(data[i][j], s) } } // row with larger value in cvector, row >= j diff --git a/src/function/algebra/decomposition/qr.js b/src/function/algebra/decomposition/qr.js index 24916bbde8..f4baf62365 100644 --- a/src/function/algebra/decomposition/qr.js +++ b/src/function/algebra/decomposition/qr.js @@ -15,7 +15,7 @@ const dependencies = [ 'addScalar', 'divideScalar', 'multiplyScalar', - 'subtract', + 'subtractScalar', 'complex' ] @@ -34,7 +34,7 @@ export const createQr = /* #__PURE__ */ factory(name, dependencies, ( addScalar, divideScalar, multiplyScalar, - subtract, + subtractScalar, complex } ) => { @@ -159,7 +159,7 @@ export const createQr = /* #__PURE__ */ factory(name, dependencies, ( if (!isZero(alpha)) { // first element in vector u - const u1 = subtract(pivot, alpha) + const u1 = subtractScalar(pivot, alpha) // w = v * u1 / |u| (only elements k to (rows-1) are used) w[k] = 1 @@ -198,7 +198,7 @@ export const createQr = /* #__PURE__ */ factory(name, dependencies, ( for (i = k; i < rows; i++) { Rdata[i][j] = multiplyScalar( - subtract(Rdata[i][j], multiplyScalar(w[i], s)), + subtractScalar(Rdata[i][j], multiplyScalar(w[i], s)), conjSgn ) } @@ -223,7 +223,7 @@ export const createQr = /* #__PURE__ */ factory(name, dependencies, ( for (j = k; j < rows; ++j) { Qdata[i][j] = divideScalar( - subtract(Qdata[i][j], multiplyScalar(s, conj(w[j]))), + subtractScalar(Qdata[i][j], multiplyScalar(s, conj(w[j]))), conjSgn ) } diff --git a/src/function/algebra/solver/lsolve.js b/src/function/algebra/solver/lsolve.js index 07703966a9..49396d0959 100644 --- a/src/function/algebra/solver/lsolve.js +++ b/src/function/algebra/solver/lsolve.js @@ -7,12 +7,12 @@ const dependencies = [ 'matrix', 'divideScalar', 'multiplyScalar', - 'subtract', + 'subtractScalar', 'equalScalar', 'DenseMatrix' ] -export const createLsolve = /* #__PURE__ */ factory(name, dependencies, ({ typed, matrix, divideScalar, multiplyScalar, subtract, equalScalar, DenseMatrix }) => { +export const createLsolve = /* #__PURE__ */ factory(name, dependencies, ({ typed, matrix, divideScalar, multiplyScalar, subtractScalar, equalScalar, DenseMatrix }) => { const solveValidation = createSolveValidation({ DenseMatrix }) /** @@ -87,7 +87,7 @@ export const createLsolve = /* #__PURE__ */ factory(name, dependencies, ({ typed // loop rows for (let i = j + 1; i < rows; i++) { - bdata[i] = [subtract(bdata[i][0] || 0, multiplyScalar(xj, mdata[i][j]))] + bdata[i] = [subtractScalar(bdata[i][0] || 0, multiplyScalar(xj, mdata[i][j]))] } } else { // degenerate row, we can choose any value @@ -158,7 +158,7 @@ export const createLsolve = /* #__PURE__ */ factory(name, dependencies, ({ typed for (let k = 0, l = jIndices.length; k < l; k++) { const i = jIndices[k] - bdata[i] = [subtract(bdata[i][0] || 0, multiplyScalar(xj, jValues[k]))] + bdata[i] = [subtractScalar(bdata[i][0] || 0, multiplyScalar(xj, jValues[k]))] } x[j] = [xj] diff --git a/src/function/algebra/solver/lsolveAll.js b/src/function/algebra/solver/lsolveAll.js index a1aaed8dee..e956329695 100644 --- a/src/function/algebra/solver/lsolveAll.js +++ b/src/function/algebra/solver/lsolveAll.js @@ -7,12 +7,12 @@ const dependencies = [ 'matrix', 'divideScalar', 'multiplyScalar', - 'subtract', + 'subtractScalar', 'equalScalar', 'DenseMatrix' ] -export const createLsolveAll = /* #__PURE__ */ factory(name, dependencies, ({ typed, matrix, divideScalar, multiplyScalar, subtract, equalScalar, DenseMatrix }) => { +export const createLsolveAll = /* #__PURE__ */ factory(name, dependencies, ({ typed, matrix, divideScalar, multiplyScalar, subtractScalar, equalScalar, DenseMatrix }) => { const solveValidation = createSolveValidation({ DenseMatrix }) /** @@ -82,7 +82,7 @@ export const createLsolveAll = /* #__PURE__ */ factory(name, dependencies, ({ ty for (let j = i + 1; j < columns; j++) { // b[j] -= b[i] * M[j,i] - b[j] = subtract(b[j], multiplyScalar(b[i], M[j][i])) + b[j] = subtractScalar(b[j], multiplyScalar(b[i], M[j][i])) } } else if (!equalScalar(b[i], 0)) { // singular row, nonzero RHS @@ -103,7 +103,7 @@ export const createLsolveAll = /* #__PURE__ */ factory(name, dependencies, ({ ty bNew[i] = 1 for (let j = i + 1; j < columns; j++) { - bNew[j] = subtract(bNew[j], M[j][i]) + bNew[j] = subtractScalar(bNew[j], M[j][i]) } B.push(bNew) @@ -162,7 +162,7 @@ export const createLsolveAll = /* #__PURE__ */ factory(name, dependencies, ({ ty for (let j = 0, lastIndex = iIndices.length; j < lastIndex; j++) { const J = iIndices[j] - b[J] = subtract(b[J], multiplyScalar(b[i], iValues[j])) + b[J] = subtractScalar(b[J], multiplyScalar(b[i], iValues[j])) } } else if (!equalScalar(b[i], 0)) { // singular row, nonzero RHS @@ -184,7 +184,7 @@ export const createLsolveAll = /* #__PURE__ */ factory(name, dependencies, ({ ty for (let j = 0, lastIndex = iIndices.length; j < lastIndex; j++) { const J = iIndices[j] - bNew[J] = subtract(bNew[J], iValues[j]) + bNew[J] = subtractScalar(bNew[J], iValues[j]) } B.push(bNew) diff --git a/src/function/algebra/solver/usolve.js b/src/function/algebra/solver/usolve.js index c2c3577d74..cf5bf8b589 100644 --- a/src/function/algebra/solver/usolve.js +++ b/src/function/algebra/solver/usolve.js @@ -7,12 +7,12 @@ const dependencies = [ 'matrix', 'divideScalar', 'multiplyScalar', - 'subtract', + 'subtractScalar', 'equalScalar', 'DenseMatrix' ] -export const createUsolve = /* #__PURE__ */ factory(name, dependencies, ({ typed, matrix, divideScalar, multiplyScalar, subtract, equalScalar, DenseMatrix }) => { +export const createUsolve = /* #__PURE__ */ factory(name, dependencies, ({ typed, matrix, divideScalar, multiplyScalar, subtractScalar, equalScalar, DenseMatrix }) => { const solveValidation = createSolveValidation({ DenseMatrix }) /** @@ -90,7 +90,7 @@ export const createUsolve = /* #__PURE__ */ factory(name, dependencies, ({ typed // loop rows for (let i = j - 1; i >= 0; i--) { // update copy of b - bdata[i] = [subtract(bdata[i][0] || 0, multiplyScalar(xj, mdata[i][j]))] + bdata[i] = [subtractScalar(bdata[i][0] || 0, multiplyScalar(xj, mdata[i][j]))] } } else { // zero value at j @@ -162,7 +162,7 @@ export const createUsolve = /* #__PURE__ */ factory(name, dependencies, ({ typed for (let k = 0, lastIndex = jIndices.length; k < lastIndex; k++) { const i = jIndices[k] - bdata[i] = [subtract(bdata[i][0], multiplyScalar(xj, jValues[k]))] + bdata[i] = [subtractScalar(bdata[i][0], multiplyScalar(xj, jValues[k]))] } x[j] = [xj] diff --git a/src/function/algebra/solver/usolveAll.js b/src/function/algebra/solver/usolveAll.js index a646b8a021..2761afbefc 100644 --- a/src/function/algebra/solver/usolveAll.js +++ b/src/function/algebra/solver/usolveAll.js @@ -7,12 +7,12 @@ const dependencies = [ 'matrix', 'divideScalar', 'multiplyScalar', - 'subtract', + 'subtractScalar', 'equalScalar', 'DenseMatrix' ] -export const createUsolveAll = /* #__PURE__ */ factory(name, dependencies, ({ typed, matrix, divideScalar, multiplyScalar, subtract, equalScalar, DenseMatrix }) => { +export const createUsolveAll = /* #__PURE__ */ factory(name, dependencies, ({ typed, matrix, divideScalar, multiplyScalar, subtractScalar, equalScalar, DenseMatrix }) => { const solveValidation = createSolveValidation({ DenseMatrix }) /** @@ -82,7 +82,7 @@ export const createUsolveAll = /* #__PURE__ */ factory(name, dependencies, ({ ty for (let j = i - 1; j >= 0; j--) { // b[j] -= b[i] * M[j,i] - b[j] = subtract(b[j], multiplyScalar(b[i], M[j][i])) + b[j] = subtractScalar(b[j], multiplyScalar(b[i], M[j][i])) } } else if (!equalScalar(b[i], 0)) { // singular row, nonzero RHS @@ -103,7 +103,7 @@ export const createUsolveAll = /* #__PURE__ */ factory(name, dependencies, ({ ty bNew[i] = 1 for (let j = i - 1; j >= 0; j--) { - bNew[j] = subtract(bNew[j], M[j][i]) + bNew[j] = subtractScalar(bNew[j], M[j][i]) } B.push(bNew) @@ -163,7 +163,7 @@ export const createUsolveAll = /* #__PURE__ */ factory(name, dependencies, ({ ty // loop upper triangular for (let j = 0, lastIndex = iIndices.length; j < lastIndex; j++) { const J = iIndices[j] - b[J] = subtract(b[J], multiplyScalar(b[i], iValues[j])) + b[J] = subtractScalar(b[J], multiplyScalar(b[i], iValues[j])) } } else if (!equalScalar(b[i], 0)) { // singular row, nonzero RHS @@ -186,7 +186,7 @@ export const createUsolveAll = /* #__PURE__ */ factory(name, dependencies, ({ ty // loop upper triangular for (let j = 0, lastIndex = iIndices.length; j < lastIndex; j++) { const J = iIndices[j] - bNew[J] = subtract(bNew[J], iValues[j]) + bNew[J] = subtractScalar(bNew[J], iValues[j]) } B.push(bNew) diff --git a/src/function/arithmetic/subtract.js b/src/function/arithmetic/subtract.js index ed111e204e..4c7057888d 100644 --- a/src/function/arithmetic/subtract.js +++ b/src/function/arithmetic/subtract.js @@ -11,13 +11,13 @@ const dependencies = [ 'typed', 'matrix', 'equalScalar', - 'addScalar', + 'subtractScalar', 'unaryMinus', 'DenseMatrix', 'concat' ] -export const createSubtract = /* #__PURE__ */ factory(name, dependencies, ({ typed, matrix, equalScalar, addScalar, unaryMinus, DenseMatrix, concat }) => { +export const createSubtract = /* #__PURE__ */ factory(name, dependencies, ({ typed, matrix, equalScalar, subtractScalar, unaryMinus, DenseMatrix, concat }) => { // TODO: split function subtract in two: subtract and subtractScalar const matAlgo01xDSid = createMatAlgo01xDSid({ typed }) @@ -53,43 +53,17 @@ export const createSubtract = /* #__PURE__ */ factory(name, dependencies, ({ typ * * add * - * @param {number | BigNumber | Fraction | Complex | Unit | Array | Matrix} x - * Initial value - * @param {number | BigNumber | Fraction | Complex | Unit | Array | Matrix} y - * Value to subtract from `x` - * @return {number | BigNumber | Fraction | Complex | Unit | Array | Matrix} - * Subtraction of `x` and `y` + * @param {number | BigNumber | Fraction | Complex | Unit | Array | Matrix} x Initial value + * @param {number | BigNumber | Fraction | Complex | Unit | Array | Matrix} y Value to subtract from `x` + * @return {number | BigNumber | Fraction | Complex | Unit | Array | Matrix} Subtraction of `x` and `y` */ return typed( name, { - 'number, number': (x, y) => x - y, - 'Complex, Complex': (x, y) => x.sub(y), - 'BigNumber, BigNumber': (x, y) => x.minus(y), - 'Fraction, Fraction': (x, y) => x.sub(y), - - 'Unit, Unit': typed.referToSelf(self => (x, y) => { - if (x.value === null) { - throw new Error('Parameter x contains a unit with undefined value') - } - - if (y.value === null) { - throw new Error('Parameter y contains a unit with undefined value') - } - - if (!x.equalBase(y)) { - throw new Error('Units do not match') - } - - const res = x.clone() - res.value = - typed.find(self, [res.valueType(), y.valueType()])(res.value, y.value) - res.fixPrefix = false - - return res - }) + 'any, any': subtractScalar }, matrixAlgorithmSuite({ + elop: subtractScalar, SS: matAlgo05xSfSf, DS: matAlgo01xDSid, SD: matAlgo03xDSf, diff --git a/src/function/arithmetic/subtractScalar.js b/src/function/arithmetic/subtractScalar.js new file mode 100644 index 0000000000..ab54a5e3af --- /dev/null +++ b/src/function/arithmetic/subtractScalar.js @@ -0,0 +1,52 @@ +import { factory } from '../../utils/factory.js' +import { subtractNumber } from '../../plain/number/index.js' + +const name = 'subtractScalar' +const dependencies = ['typed'] + +export const createSubtractScalar = /* #__PURE__ */ factory(name, dependencies, ({ typed }) => { + /** + * Subtract two scalar values, `x - y`. + * This function is meant for internal use: it is used by the public function + * `subtract` + * + * This function does not support collections (Array or Matrix). + * + * @param {number | BigNumber | Fraction | Complex | Unit} x First value + * @param {number | BigNumber | Fraction | Complex} y Second value to be subtracted from `x` + * @return {number | BigNumber | Fraction | Complex | Unit} Difference of `x` and `y` + * @private + */ + return typed(name, { + + 'number, number': subtractNumber, + + 'Complex, Complex': function (x, y) { + return x.sub(y) + }, + + 'BigNumber, BigNumber': function (x, y) { + return x.minus(y) + }, + + 'Fraction, Fraction': function (x, y) { + return x.sub(y) + }, + + 'Unit, Unit': typed.referToSelf(self => (x, y) => { + if (x.value === null || x.value === undefined) { + throw new Error('Parameter x contains a unit with undefined value') + } + if (y.value === null || y.value === undefined) { + throw new Error('Parameter y contains a unit with undefined value') + } + if (!x.equalBase(y)) throw new Error('Units do not match') + + const res = x.clone() + res.value = + typed.find(self, [res.valueType(), y.valueType()])(res.value, y.value) + res.fixPrefix = false + return res + }) + }) +}) diff --git a/src/function/combinatorics/stirlingS2.js b/src/function/combinatorics/stirlingS2.js index 9939f074da..0591d4e94f 100644 --- a/src/function/combinatorics/stirlingS2.js +++ b/src/function/combinatorics/stirlingS2.js @@ -5,7 +5,7 @@ const name = 'stirlingS2' const dependencies = [ 'typed', 'addScalar', - 'subtract', + 'subtractScalar', 'multiplyScalar', 'divideScalar', 'pow', @@ -22,7 +22,7 @@ export const createStirlingS2 = /* #__PURE__ */ factory(name, dependencies, ( { typed, addScalar, - subtract, + subtractScalar, multiplyScalar, divideScalar, pow, diff --git a/src/function/geometry/distance.js b/src/function/geometry/distance.js index 40f0e9275e..a7fc149440 100644 --- a/src/function/geometry/distance.js +++ b/src/function/geometry/distance.js @@ -5,7 +5,7 @@ const name = 'distance' const dependencies = [ 'typed', 'addScalar', - 'subtract', + 'subtractScalar', 'divideScalar', 'multiplyScalar', 'deepEqual', @@ -13,7 +13,7 @@ const dependencies = [ 'abs' ] -export const createDistance = /* #__PURE__ */ factory(name, dependencies, ({ typed, addScalar, subtract, multiplyScalar, divideScalar, deepEqual, sqrt, abs }) => { +export const createDistance = /* #__PURE__ */ factory(name, dependencies, ({ typed, addScalar, subtractScalar, multiplyScalar, divideScalar, deepEqual, sqrt, abs }) => { /** * Calculates: * The eucledian distance between two points in N-dimensional spaces. @@ -73,9 +73,9 @@ export const createDistance = /* #__PURE__ */ factory(name, dependencies, ({ typ if (!_2d(y)) { throw new TypeError('Array with 2 numbers or BigNumbers expected for second argument') } if (!_2d(z)) { throw new TypeError('Array with 2 numbers or BigNumbers expected for third argument') } if (deepEqual(y, z)) { throw new TypeError('LinePoint1 should not be same with LinePoint2') } - const xCoeff = subtract(z[1], y[1]) - const yCoeff = subtract(y[0], z[0]) - const constant = subtract(multiplyScalar(z[0], y[1]), multiplyScalar(y[0], z[1])) + const xCoeff = subtractScalar(z[1], y[1]) + const yCoeff = subtractScalar(y[0], z[0]) + const constant = subtractScalar(multiplyScalar(z[0], y[1]), multiplyScalar(y[0], z[1])) return _distancePointLine2D(x[0], x[1], xCoeff, yCoeff, constant) } else { @@ -90,9 +90,9 @@ export const createDistance = /* #__PURE__ */ factory(name, dependencies, ({ typ if (deepEqual(_objectToArray(y), _objectToArray(z))) { throw new TypeError('LinePoint1 should not be same with LinePoint2') } if ('pointX' in x && 'pointY' in x && 'lineOnePtX' in y && 'lineOnePtY' in y && 'lineTwoPtX' in z && 'lineTwoPtY' in z) { - const xCoeff = subtract(z.lineTwoPtY, y.lineOnePtY) - const yCoeff = subtract(y.lineOnePtX, z.lineTwoPtX) - const constant = subtract(multiplyScalar(z.lineTwoPtX, y.lineOnePtY), multiplyScalar(y.lineOnePtX, z.lineTwoPtY)) + const xCoeff = subtractScalar(z.lineTwoPtY, y.lineOnePtY) + const yCoeff = subtractScalar(y.lineOnePtX, z.lineTwoPtX) + const constant = subtractScalar(multiplyScalar(z.lineTwoPtX, y.lineOnePtY), multiplyScalar(y.lineOnePtX, z.lineTwoPtY)) return _distancePointLine2D(x.pointX, x.pointY, xCoeff, yCoeff, constant) } else { throw new TypeError('Key names do not match') @@ -270,9 +270,9 @@ export const createDistance = /* #__PURE__ */ factory(name, dependencies, ({ typ } function _distancePointLine3D (x, y, z, x0, y0, z0, a, b, c) { - let num = [subtract(multiplyScalar(subtract(y0, y), c), multiplyScalar(subtract(z0, z), b)), - subtract(multiplyScalar(subtract(z0, z), a), multiplyScalar(subtract(x0, x), c)), - subtract(multiplyScalar(subtract(x0, x), b), multiplyScalar(subtract(y0, y), a))] + let num = [subtractScalar(multiplyScalar(subtractScalar(y0, y), c), multiplyScalar(subtractScalar(z0, z), b)), + subtractScalar(multiplyScalar(subtractScalar(z0, z), a), multiplyScalar(subtractScalar(x0, x), c)), + subtractScalar(multiplyScalar(subtractScalar(x0, x), b), multiplyScalar(subtractScalar(y0, y), a))] num = sqrt(addScalar(addScalar(multiplyScalar(num[0], num[0]), multiplyScalar(num[1], num[1])), multiplyScalar(num[2], num[2]))) const den = sqrt(addScalar(addScalar(multiplyScalar(a, a), multiplyScalar(b, b)), multiplyScalar(c, c))) return divideScalar(num, den) @@ -283,7 +283,7 @@ export const createDistance = /* #__PURE__ */ factory(name, dependencies, ({ typ let result = 0 let diff = 0 for (let i = 0; i < vectorSize; i++) { - diff = subtract(x[i], y[i]) + diff = subtractScalar(x[i], y[i]) result = addScalar(multiplyScalar(diff, diff), result) } return sqrt(result) diff --git a/src/function/matrix/det.js b/src/function/matrix/det.js index ec0d3039d1..8c2123fa6e 100644 --- a/src/function/matrix/det.js +++ b/src/function/matrix/det.js @@ -4,9 +4,9 @@ import { format } from '../../utils/string.js' import { factory } from '../../utils/factory.js' const name = 'det' -const dependencies = ['typed', 'matrix', 'subtract', 'multiply', 'divideScalar', 'isZero', 'unaryMinus'] +const dependencies = ['typed', 'matrix', 'subtractScalar', 'multiply', 'divideScalar', 'isZero', 'unaryMinus'] -export const createDet = /* #__PURE__ */ factory(name, dependencies, ({ typed, matrix, subtract, multiply, divideScalar, isZero, unaryMinus }) => { +export const createDet = /* #__PURE__ */ factory(name, dependencies, ({ typed, matrix, subtractScalar, multiply, divideScalar, isZero, unaryMinus }) => { /** * Calculate the determinant of a matrix. * @@ -103,7 +103,7 @@ export const createDet = /* #__PURE__ */ factory(name, dependencies, ({ typed, m } else if (rows === 2) { // this is a 2 x 2 matrix // the determinant of [a11,a12;a21,a22] is det = a11*a22-a21*a12 - return subtract( + return subtractScalar( multiply(matrix[0][0], matrix[1][1]), multiply(matrix[1][0], matrix[0][1]) ) @@ -133,7 +133,7 @@ export const createDet = /* #__PURE__ */ factory(name, dependencies, ({ typed, m for (let i = k + 1; i < rows; i++) { const i_ = rowIndices[i] for (let j = k + 1; j < rows; j++) { - matrix[i_][j] = divideScalar(subtract(multiply(matrix[i_][j], piv), multiply(matrix[i_][k], matrix[k_][j])), piv_) + matrix[i_][j] = divideScalar(subtractScalar(multiply(matrix[i_][j], piv), multiply(matrix[i_][k], matrix[k_][j])), piv_) } } } diff --git a/src/type/unit/Unit.js b/src/type/unit/Unit.js index 950e22b74f..9379460203 100644 --- a/src/type/unit/Unit.js +++ b/src/type/unit/Unit.js @@ -10,7 +10,7 @@ const dependencies = [ '?on', 'config', 'addScalar', - 'subtract', + 'subtractScalar', 'multiplyScalar', 'divideScalar', 'pow', @@ -30,7 +30,7 @@ export const createUnitClass = /* #__PURE__ */ factory(name, dependencies, ({ on, config, addScalar, - subtract, + subtractScalar, multiplyScalar, divideScalar, pow, @@ -790,7 +790,7 @@ export const createUnitClass = /* #__PURE__ */ factory(name, dependencies, ({ const unitValue = convert(ret.units[0].unit.value) const nominalOffset = convert(ret.units[0].unit.offset) const unitOffset = multiplyScalar(unitValue, nominalOffset) - ret.value = subtract(abs(addScalar(ret.value, unitOffset)), unitOffset) + ret.value = subtractScalar(abs(addScalar(ret.value, unitOffset)), unitOffset) } } @@ -842,7 +842,7 @@ export const createUnitClass = /* #__PURE__ */ factory(name, dependencies, ({ const otherNominalOffset = other.units[0].unit.offset const otherUnitOffset = multiplyScalar(otherUnitValue, otherNominalOffset) - other.value = addScalar(value, convert(subtract(thisUnitOffset, otherUnitOffset))) + other.value = addScalar(value, convert(subtractScalar(thisUnitOffset, otherUnitOffset))) } other.fixPrefix = true other.skipAutomaticSimplification = true @@ -1238,7 +1238,7 @@ export const createUnitClass = /* #__PURE__ */ factory(name, dependencies, ({ const y = new Unit(xFixed, parts[i].toString()) ret.push(y) - x = subtract(x, y) + x = subtractScalar(x, y) } // This little bit fixes a bug where the remainder should be 0 but is a little bit off. diff --git a/src/utils/snapshot.js b/src/utils/snapshot.js index 641efda755..d610013fc6 100644 --- a/src/utils/snapshot.js +++ b/src/utils/snapshot.js @@ -146,6 +146,7 @@ export function createSnapshotFromFactories (factories) { 'equalScalar', 'apply', 'addScalar', + 'subtractScalar', 'multiplyScalar', 'print', 'divideScalar', diff --git a/test/node-tests/browser.test.js b/test/node-tests/browser.test.js index f1b341139a..b5e6198490 100644 --- a/test/node-tests/browser.test.js +++ b/test/node-tests/browser.test.js @@ -76,7 +76,7 @@ describe('lib/browser', function () { 'compile', 'parse', 'parser', // TODO: add embedded docs for compile, parse, and parser? 'reviver', 'replacer', // TODO: add embedded docs for reviver and replacer? 'apply', // FIXME: apply is not supported right now because of security concerns - 'addScalar', 'divideScalar', 'multiplyScalar', 'equalScalar' + 'addScalar', 'subtractScalar', 'divideScalar', 'multiplyScalar', 'equalScalar' ] // test whether all functions are documented diff --git a/test/node-tests/doc.test.js b/test/node-tests/doc.test.js index bde7d3a524..a33b2f7c5e 100644 --- a/test/node-tests/doc.test.js +++ b/test/node-tests/doc.test.js @@ -141,7 +141,7 @@ function checkExpectation (want, got) { } const OKundocumented = new Set([ - 'addScalar', 'divideScalar', 'multiplyScalar', 'equalScalar', + 'addScalar', 'subtractScalar', 'divideScalar', 'multiplyScalar', 'equalScalar', 'docs', 'FibonacciHeap', 'IndexError', 'DimensionError', 'ArgumentsError' ]) diff --git a/test/unit-tests/function/arithmetic/subtractScalar.test.js b/test/unit-tests/function/arithmetic/subtractScalar.test.js new file mode 100644 index 0000000000..99d60df9da --- /dev/null +++ b/test/unit-tests/function/arithmetic/subtractScalar.test.js @@ -0,0 +1,156 @@ +// test subtractScalar +import assert from 'assert' + +import approx from '../../../../tools/approx.js' +import math from '../../../../src/defaultInstance.js' +import Decimal from 'decimal.js' +const { subtractScalar, BigNumber } = math + +describe('subtractScalar', function () { + it('should subtractScalar two numbers correctly', function () { + assert.deepStrictEqual(subtractScalar(4, 2), 2) + assert.deepStrictEqual(subtractScalar(4, -4), 8) + assert.deepStrictEqual(subtractScalar(-4, -4), 0) + assert.deepStrictEqual(subtractScalar(-4, 4), -8) + assert.deepStrictEqual(subtractScalar(2, 4), -2) + assert.deepStrictEqual(subtractScalar(3, 0), 3) + assert.deepStrictEqual(subtractScalar(0, 3), -3) + assert.deepStrictEqual(subtractScalar(0, 3), -3) + assert.deepStrictEqual(subtractScalar(0, 3), -3) + }) + + it('should subtractScalar booleans', function () { + assert.strictEqual(subtractScalar(true, true), 0) + assert.strictEqual(subtractScalar(true, false), 1) + assert.strictEqual(subtractScalar(false, true), -1) + assert.strictEqual(subtractScalar(false, false), 0) + }) + + it('should subtractScalar mixed numbers and booleans', function () { + assert.strictEqual(subtractScalar(2, true), 1) + assert.strictEqual(subtractScalar(2, false), 2) + assert.strictEqual(subtractScalar(true, 2), -1) + assert.strictEqual(subtractScalar(false, 2), -2) + }) + + it('should subtractScalar new BigNumbers', function () { + assert.deepStrictEqual(subtractScalar(new BigNumber(0.3), new BigNumber(0.2)), new BigNumber(0.1)) + assert.deepStrictEqual(subtractScalar(new BigNumber('2.3e5001'), new BigNumber('3e5000')), new BigNumber('2e5001')) + assert.deepStrictEqual(subtractScalar(new BigNumber('1e19'), new BigNumber('1')), new BigNumber('9999999999999999999')) + }) + + it('should subtractScalar mixed numbers and new BigNumbers', function () { + assert.deepStrictEqual(subtractScalar(new BigNumber(0.3), 0.2), new BigNumber(0.1)) + assert.deepStrictEqual(subtractScalar(0.3, new BigNumber(0.2)), new BigNumber(0.1)) + + assert.throws(function () { subtractScalar(1 / 3, new BigNumber(1).div(3)) }, /Cannot implicitly convert a number with >15 significant digits to BigNumber/) + assert.throws(function () { subtractScalar(new BigNumber(1).div(3), 1 / 3) }, /Cannot implicitly convert a number with >15 significant digits to BigNumber/) + }) + + it('should add Decimals', function () { + assert.deepStrictEqual(subtractScalar(Decimal(0.2), Decimal(0.1)), Decimal(0.1)) + assert.deepStrictEqual(subtractScalar(Decimal(0.3), 0.2), Decimal(0.1)) + assert.deepStrictEqual(subtractScalar(Decimal(0.1), new BigNumber(0.2)).toString(), '-0.1') + assert.deepStrictEqual(subtractScalar(new BigNumber(0.2), Decimal(0.1)).toString(), '0.1') + }) + + it('should subtractScalar mixed booleans and new BigNumbers', function () { + assert.deepStrictEqual(subtractScalar(new BigNumber(1.1), true), new BigNumber(0.1)) + assert.deepStrictEqual(subtractScalar(new BigNumber(1.1), false), new BigNumber(1.1)) + assert.deepStrictEqual(subtractScalar(false, new BigNumber(0.2)), new BigNumber(-0.2)) + assert.deepStrictEqual(subtractScalar(true, new BigNumber(0.2)), new BigNumber(0.8)) + }) + + it('should subtractScalar two complex numbers correctly', function () { + assert.deepStrictEqual(subtractScalar(math.complex(3, 2), math.complex(8, 4)), math.complex('-5 - 2i')) + assert.deepStrictEqual(subtractScalar(math.complex(6, 3), math.complex(-2, -2)), math.complex('8 + 5i')) + assert.deepStrictEqual(subtractScalar(math.complex(3, 4), 10), math.complex('-7 + 4i')) + assert.deepStrictEqual(subtractScalar(math.complex(3, 4), -2), math.complex('5 + 4i')) + assert.deepStrictEqual(subtractScalar(math.complex(-3, -4), 10), math.complex('-13 - 4i')) + assert.deepStrictEqual(subtractScalar(10, math.complex(3, 4)), math.complex('7 - 4i')) + assert.deepStrictEqual(subtractScalar(10, math.i), math.complex('10 - i')) + assert.deepStrictEqual(subtractScalar(0, math.i), math.complex('-i')) + assert.deepStrictEqual(subtractScalar(10, math.complex(0, 1)), math.complex('10 - i')) + }) + + it('should throw an error for mixed complex numbers and big numbers', function () { + assert.deepStrictEqual(subtractScalar(math.complex(3, 4), new BigNumber(10)), math.complex(-7, 4)) + assert.deepStrictEqual(subtractScalar(new BigNumber(10), math.complex(3, 4)), math.complex(7, -4)) + }) + + it('should subtractScalar two fractions', function () { + const a = math.fraction(1, 3) + assert.strictEqual(subtractScalar(a, math.fraction(1, 6)).toString(), '0.1(6)') + assert.strictEqual(a.toString(), '0.(3)') + + assert.strictEqual(subtractScalar(math.fraction(3, 5), math.fraction(1, 5)).toString(), '0.4') + assert.strictEqual(subtractScalar(math.fraction(1), math.fraction(1, 3)).toString(), '0.(6)') + }) + + it('should subtractScalar mixed fractions and numbers', function () { + assert.deepStrictEqual(subtractScalar(1, math.fraction(1, 3)), math.fraction(2, 3)) + assert.deepStrictEqual(subtractScalar(math.fraction(1, 3), 1), math.fraction(-2, 3)) + }) + + it('should subtractScalar two quantities of the same unit', function () { + approx.deepEqual(subtractScalar(math.unit(5, 'km'), math.unit(100, 'mile')), math.unit(-155.93, 'km')) + + assert.deepStrictEqual(subtractScalar(math.unit(new BigNumber(5), 'km'), math.unit(new BigNumber(2), 'km')), math.unit(new BigNumber(3), 'km')) + + assert.deepStrictEqual(subtractScalar(math.unit(math.complex(10, 10), 'K'), math.unit(math.complex(3, 4), 'K')), math.unit(math.complex(7, 6), 'K')) + assert.deepStrictEqual(subtractScalar(math.unit(math.complex(10, 10), 'K'), math.unit(3, 'K')), math.unit(math.complex(7, 10), 'K')) + }) + + it('should subtractScalar units even when they have offsets', function () { + let t = math.unit(20, 'degC') + assert.deepStrictEqual(subtractScalar(t, math.unit(1, 'degC')), math.unit(19, 'degC')) + t = math.unit(68, 'degF') + approx.deepEqual(subtractScalar(t, math.unit(2, 'degF')), math.unit(66, 'degF')) + approx.deepEqual(subtractScalar(t, math.unit(1, 'degC')), math.unit(66.2, 'degF')) + }) + + it('should throw an error if subtracting two quantities of different units', function () { + assert.throws(function () { + subtractScalar(math.unit(5, 'km'), math.unit(100, 'gram')) + }) + }) + + it('should throw an error when one of the two units has undefined value', function () { + assert.throws(function () { + subtractScalar(math.unit('km'), math.unit('5gram')) + }, /Parameter x contains a unit with undefined value/) + assert.throws(function () { + subtractScalar(math.unit('5 km'), math.unit('gram')) + }, /Parameter y contains a unit with undefined value/) + }) + + it('should throw an error if subtracting numbers from units', function () { + assert.throws(function () { subtractScalar(math.unit(5, 'km'), 2) }, TypeError) + assert.throws(function () { subtractScalar(2, math.unit(5, 'km')) }, TypeError) + }) + + it('should throw an error if subtracting numbers from units', function () { + assert.throws(function () { subtractScalar(math.unit(5, 'km'), new BigNumber(2)) }, TypeError) + assert.throws(function () { subtractScalar(new BigNumber(2), math.unit(5, 'km')) }, TypeError) + }) + + it('should throw an error when used with a string', function () { + assert.throws(function () { subtractScalar('hello ', 'world') }) + assert.throws(function () { subtractScalar('str', 123) }) + assert.throws(function () { subtractScalar(123, 'str') }) + }) + + it('should throw an error in case of invalid number of arguments', function () { + assert.throws(function () { subtractScalar(1) }, /TypeError: Too few arguments/) + assert.throws(function () { subtractScalar(1, 2, 3) }, /TypeError: Too many arguments/) + }) + + it('should throw an in case of wrong type of arguments', function () { + assert.throws(function () { subtractScalar(null, 2) }, /TypeError: Unexpected type of argument/) + }) + + it('should LaTeX subtractScalar', function () { + const expression = math.parse('subtractScalar(2,1)') + assert.strictEqual(expression.toTex(), '\\mathrm{subtractScalar}\\left(2,1\\right)') + }) +}) diff --git a/tools/docgenerator.js b/tools/docgenerator.js index 60b9650bc3..bcecb5246d 100644 --- a/tools/docgenerator.js +++ b/tools/docgenerator.js @@ -43,6 +43,7 @@ const SYNTAX = { const IGNORE_FUNCTIONS = { addScalar: true, + subtractScalar: true, divideScalar: true, multiplyScalar: true, equalScalar: true, diff --git a/types/index.d.ts b/types/index.d.ts index c14a05d3f9..c7f6facbb6 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -3514,6 +3514,7 @@ declare namespace math { absDependencies: FactoryFunctionMap applyDependencies: FactoryFunctionMap addScalarDependencies: FactoryFunctionMap + subtractScalarDependencies: FactoryFunctionMap cbrtDependencies: FactoryFunctionMap ceilDependencies: FactoryFunctionMap cubeDependencies: FactoryFunctionMap