Skip to content

Commit

Permalink
feat: implement subtractScalar (#3081, #2643)
Browse files Browse the repository at this point in the history
* added subtractScaler

* added subtractScaler missing entries

* added test cases for 2 or more parameters, test for subtractScalar instead fo subtract

* replaced subtract with subtractScalar whereever possible

---------

Co-authored-by: Jos de Jong <wjosdejong@gmail.com>
  • Loading branch information
vrushaket and josdejong committed Oct 25, 2023
1 parent d1c4a56 commit 8f8e506
Show file tree
Hide file tree
Showing 22 changed files with 276 additions and 87 deletions.
2 changes: 2 additions & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -233,5 +233,7 @@ BuildTools <anikpatel1322@gmail.com>
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 <VincentTam@users.noreply.github.com>
vrushaket <vrushu00@gmail.com>

# Generated by tools/update-authors.js
2 changes: 1 addition & 1 deletion examples/advanced/custom_evaluate_using_import.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
1 change: 1 addition & 0 deletions src/factoriesAny.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
1 change: 1 addition & 0 deletions src/factoriesNumber.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 3 additions & 3 deletions src/function/algebra/decomposition/lup.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const dependencies = [
'addScalar',
'divideScalar',
'multiplyScalar',
'subtract',
'subtractScalar',
'larger',
'equalScalar',
'unaryMinus',
Expand All @@ -26,7 +26,7 @@ export const createLup = /* #__PURE__ */ factory(name, dependencies, (
addScalar,
divideScalar,
multiplyScalar,
subtract,
subtractScalar,
larger,
equalScalar,
unaryMinus,
Expand Down Expand Up @@ -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
Expand Down
10 changes: 5 additions & 5 deletions src/function/algebra/decomposition/qr.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const dependencies = [
'addScalar',
'divideScalar',
'multiplyScalar',
'subtract',
'subtractScalar',
'complex'
]

Expand All @@ -34,7 +34,7 @@ export const createQr = /* #__PURE__ */ factory(name, dependencies, (
addScalar,
divideScalar,
multiplyScalar,
subtract,
subtractScalar,
complex
}
) => {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
)
}
Expand All @@ -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
)
}
Expand Down
8 changes: 4 additions & 4 deletions src/function/algebra/solver/lsolve.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 })

/**
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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]
Expand Down
12 changes: 6 additions & 6 deletions src/function/algebra/solver/lsolveAll.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 })

/**
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down
8 changes: 4 additions & 4 deletions src/function/algebra/solver/usolve.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 })

/**
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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]
Expand Down
12 changes: 6 additions & 6 deletions src/function/algebra/solver/usolveAll.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 })

/**
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down
40 changes: 7 additions & 33 deletions src/function/arithmetic/subtract.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 })
Expand Down Expand Up @@ -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,
Expand Down
52 changes: 52 additions & 0 deletions src/function/arithmetic/subtractScalar.js
Original file line number Diff line number Diff line change
@@ -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
})
})
})

0 comments on commit 8f8e506

Please sign in to comment.