Skip to content

Commit

Permalink
Proof of concept of extending operator functions with support for nod…
Browse files Browse the repository at this point in the history
…es (see #1732)
  • Loading branch information
josdejong committed Feb 22, 2020
1 parent 3756b66 commit a981a16
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 4 deletions.
19 changes: 17 additions & 2 deletions src/core/function/typed.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,16 @@ const dependencies = [
'?BigNumber',
'?Complex',
'?DenseMatrix',
'?Fraction'
'?Fraction',
'?ConstantNode'
]

/**
* Factory function for creating a new typed instance
* @param {Object} dependencies Object with data types like Complex and BigNumber
* @returns {Function}
*/
export const createTyped = /* #__PURE__ */ factory('typed', dependencies, function createTyped ({ BigNumber, Complex, DenseMatrix, Fraction }) {
export const createTyped = /* #__PURE__ */ factory('typed', dependencies, function createTyped ({ BigNumber, Complex, DenseMatrix, Fraction, ConstantNode }) {
// TODO: typed-function must be able to silently ignore signatures with unknown data types

// get a new instance of typed-function
Expand Down Expand Up @@ -333,6 +334,16 @@ export const createTyped = /* #__PURE__ */ factory('typed', dependencies, functi
convert: function (matrix) {
return matrix.valueOf()
}
}, {
from: 'number',
to: 'Node',
convert: function (x) {
if (!ConstantNode) {
throwNoConstantNode()
}

return new ConstantNode(x)
}
}
]

Expand All @@ -354,3 +365,7 @@ function throwNoMatrix () {
function throwNoFraction (x) {
throw new Error(`Cannot convert value ${x} into a Fraction, no class 'Fraction' provided.`)
}

function throwNoConstantNode (x) {
throw new Error(`Cannot convert value ${x} into a ConstantNode, no class 'ConstantNode' provided.`)
}
8 changes: 6 additions & 2 deletions src/function/arithmetic/addScalar.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { factory } from '../../utils/factory'
import { addNumber } from '../../plain/number'

const name = 'addScalar'
const dependencies = ['typed']
const dependencies = ['typed', 'OperatorNode']

export const createAddScalar = /* #__PURE__ */ factory(name, dependencies, ({ typed }) => {
export const createAddScalar = /* #__PURE__ */ factory(name, dependencies, ({ typed, OperatorNode }) => {
/**
* Add two scalar values, `x + y`.
* This function is meant for internal use: it is used by the public function
Expand Down Expand Up @@ -42,6 +42,10 @@ export const createAddScalar = /* #__PURE__ */ factory(name, dependencies, ({ ty
res.value = addScalar(res.value, y.value)
res.fixPrefix = false
return res
},

'Node, Node': function (x, y) {
return new OperatorNode('+', name, [x, y])
}
})

Expand Down
11 changes: 11 additions & 0 deletions test/unit-tests/function/arithmetic/addScalar.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,17 @@ describe('addScalar', function () {
approx.deepEqual(add(math.unit(math.complex(-3, 2), 'g'), math.unit(math.complex(5, -6), 'g')).toString(), '(2 - 4i) g')
})

it('should parse two expression nodes', function () {
const a = new math.ConstantNode(2)
const b = new math.ConstantNode(3)
const expr = math.parse('4 * 5')

assert.deepStrictEqual(math.add(a, b), new math.OperatorNode('+', 'addScalar', [a, b]))
assert.deepStrictEqual(math.add(a, 3), new math.OperatorNode('+', 'addScalar', [a, b]))
assert.deepStrictEqual(math.add(2, b), new math.OperatorNode('+', 'addScalar', [a, b]))
assert.deepStrictEqual(math.add(2, expr), new math.OperatorNode('+', 'addScalar', [a, expr]))
})

it('should throw an error for two measures of different units', function () {
assert.throws(function () {
add(math.unit(5, 'km'), math.unit(100, 'gram'))
Expand Down

0 comments on commit a981a16

Please sign in to comment.