Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/function/algebra/simplifyCore.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,11 @@ export const createSimplifyCore = /* #__PURE__ */ factory(name, dependencies, ({
nodeToSimplify.forEach(c => {
++childCount
if (childCount === 1) {
simpChild = _simplifyCore(c, options)
simpChild = c
}
})
if (childCount === 1) {
return simpChild
return _simplifyCore(simpChild, options)
}
}
let node = nodeToSimplify
Expand Down
40 changes: 40 additions & 0 deletions test/unit-tests/function/algebra/simplifyCore.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// test simplifyCore
import assert from 'assert'
import sinon from 'sinon'

import math from '../../../../src/defaultInstance.js'

Expand Down Expand Up @@ -54,6 +55,45 @@ describe('simplifyCore', function () {
testSimplifyCore('{a:x*1, b:y-0}', '{"a": x, "b": y}')
})

for (const { op, fn, constant, expected } of [
{ op: '+', fn: 'add', constant: 1, expected: 15 },
{ op: '*', fn: 'multiply', constant: 2, expected: 12288 }
]) {
it(`should visit the innermost ${fn} subtree only once`, function () {
const inner = new math.OperatorNode(op, fn, [
new math.SymbolNode('x'),
new math.ConstantNode(constant)
])
let node = inner
for (let depth = 1; depth < 12; depth++) {
node = new math.OperatorNode(op, fn, [
node, new math.ConstantNode(constant)
])
}
const original = node.toString()
const traversal = sinon.spy(inner, 'forEach')
try {
const simplified = math.simplifyCore(node)
// Count traversal work instead of depending on a timing threshold.
assert.strictEqual(traversal.callCount, 1)
assert.strictEqual(simplified.compile().evaluate({ x: 3 }), expected)
assert.strictEqual(node.toString(), original)
} finally {
traversal.restore()
}
})
}

it('should still simplify single-child wrappers and preserve context', function () {
const node = math.parse('+((x + 0) * 1)')
const original = node.toString()
assert.strictEqual(math.simplifyCore(node).toString(), 'x')
assert.strictEqual(node.toString(), original)
testSimplifyCore('+(5*x*3)', '5 * x * 3', {}, {
context: { multiply: { commutative: false } }
})
})

it('should not alter order of multiplication when noncommutative', function () {
testSimplifyCore('5*x*3', '5 * x * 3', {}, { context: { multiply: { commutative: false } } })
})
Expand Down