From 9e2491e96fe09a9be36c5d4319c24136bb0e8e56 Mon Sep 17 00:00:00 2001 From: Timothy Lee Date: Fri, 5 May 2017 13:44:21 +0930 Subject: [PATCH 1/2] Fixed simplify to recognize named constants --- lib/function/algebra/simplify.js | 13 ++++++++----- test/function/algebra/simplify.test.js | 7 +++++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/lib/function/algebra/simplify.js b/lib/function/algebra/simplify.js index 1df6adc73..f14349636 100644 --- a/lib/function/algebra/simplify.js +++ b/lib/function/algebra/simplify.js @@ -531,16 +531,19 @@ function factory (type, config, load, typed) { return []; } } + else if (['true', 'false', 'e', 'pi'].indexOf(rule.name) >= 0) { + // built-in constant must match exactly + if(rule.name !== node.name) { + return []; + } + } else { throw new Error('Invalid symbol in rule: ' + rule.name); } } else if (rule instanceof ConstantNode) { - // Literal constant in our rule, so much match node exactly - if(rule.value === node.value) { - // The constants match - } - else { + // Literal constant must match exactly + if(rule.value !== node.value) { return []; } } diff --git a/test/function/algebra/simplify.test.js b/test/function/algebra/simplify.test.js index 94ea9d4a4..f25c3605d 100644 --- a/test/function/algebra/simplify.test.js +++ b/test/function/algebra/simplify.test.js @@ -54,6 +54,13 @@ describe('simplify', function() { simplifyAndCompare('foo(x)', 'foo(x)'); }); + it('should handle built-in constant symbols in rules', function() { + assert.equal(math.simplify('true', ['true -> 1']).toString(), '1'); + assert.equal(math.simplify('false', ['false -> 0']).toString(), '0'); + assert.equal(math.simplify('log(e)', ['log(e) -> 1']).toString(), '1'); + assert.equal(math.simplify('sin(pi * x)', ['sin(pi * n) -> 0']).toString(), '0'); + }); + it('should remove addition of 0', function() { simplifyAndCompare('x+0', 'x'); simplifyAndCompare('x-0', 'x'); From 158adc1861ce36d6545cb95346d546d0bfe26940 Mon Sep 17 00:00:00 2001 From: Timothy Lee Date: Mon, 8 May 2017 12:56:56 +0930 Subject: [PATCH 2/2] Added support for more constants in simplify --- lib/function/algebra/simplify.js | 44 +++++++++++++++++++++----- test/function/algebra/simplify.test.js | 19 ++++++++++- 2 files changed, 54 insertions(+), 9 deletions(-) diff --git a/lib/function/algebra/simplify.js b/lib/function/algebra/simplify.js index f14349636..81ab08822 100644 --- a/lib/function/algebra/simplify.js +++ b/lib/function/algebra/simplify.js @@ -1,7 +1,7 @@ 'use strict'; -function factory (type, config, load, typed) { +function factory (type, config, load, typed, math) { var parse = load(require('../../expression/parse')); var ConstantNode = load(require('../../expression/node/ConstantNode')); var FunctionNode = load(require('../../expression/node/FunctionNode')); @@ -114,6 +114,28 @@ function factory (type, config, load, typed) { }); } + // All constants that are allowed in rules + var SUPPORTED_CONSTANTS = { + true: true, + false: true, + e: true, + i: true, + Infinity: true, + LN2: true, + LN10: true, + LOG2E: true, + LOG10E: true, + NaN: true, + phi: true, + pi: true, + SQRT1_2: true, + SQRT2: true, + tau: true, + // null: false, + // uninitialized: false, + // version: false, + }; + // Array of strings, used to build the ruleSet. // Each l (left side) and r (right side) are parsed by // the expression parser into a node tree. @@ -495,7 +517,18 @@ function factory (type, config, load, typed) { if (rule.name.length === 0) { throw new Error('Symbol in rule has 0 length...!?'); } - if (rule.name[0] == 'n' || rule.name.substring(0,2) == '_p') { + + if (math.hasOwnProperty(rule.name)) { + if (!SUPPORTED_CONSTANTS[rule.name]) { + throw new Error('Built in constant: ' + rule.name + ' is not supported by simplify.'); + } + + // built-in constant must match exactly + if(rule.name !== node.name) { + return []; + } + } + else if (rule.name[0] == 'n' || rule.name.substring(0,2) == '_p') { // rule matches _anything_, so assign this node to the rule.name placeholder // Assign node to the rule.name placeholder. // Our parent will check for matches among placeholders. @@ -531,12 +564,6 @@ function factory (type, config, load, typed) { return []; } } - else if (['true', 'false', 'e', 'pi'].indexOf(rule.name) >= 0) { - // built-in constant must match exactly - if(rule.name !== node.name) { - return []; - } - } else { throw new Error('Invalid symbol in rule: ' + rule.name); } @@ -610,5 +637,6 @@ function factory (type, config, load, typed) { return simplify; } +exports.math = true; exports.name = 'simplify'; exports.factory = factory; diff --git a/test/function/algebra/simplify.test.js b/test/function/algebra/simplify.test.js index f25c3605d..742cf185f 100644 --- a/test/function/algebra/simplify.test.js +++ b/test/function/algebra/simplify.test.js @@ -54,11 +54,28 @@ describe('simplify', function() { simplifyAndCompare('foo(x)', 'foo(x)'); }); - it('should handle built-in constant symbols in rules', function() { + it('should handle valid built-in constant symbols in rules', function() { assert.equal(math.simplify('true', ['true -> 1']).toString(), '1'); assert.equal(math.simplify('false', ['false -> 0']).toString(), '0'); assert.equal(math.simplify('log(e)', ['log(e) -> 1']).toString(), '1'); assert.equal(math.simplify('sin(pi * x)', ['sin(pi * n) -> 0']).toString(), '0'); + assert.equal(math.simplify('i', ['i -> 1']).toString(), '1'); + assert.equal(math.simplify('Infinity', ['Infinity -> 1']).toString(), '1'); + assert.equal(math.simplify('LN2', ['LN2 -> 1']).toString(), '1'); + assert.equal(math.simplify('LN10', ['LN10 -> 1']).toString(), '1'); + assert.equal(math.simplify('LOG2E', ['LOG2E -> 1']).toString(), '1'); + assert.equal(math.simplify('LOG10E', ['LOG10E -> 1']).toString(), '1'); + assert.equal(math.simplify('NaN', ['NaN -> 1']).toString(), '1'); + assert.equal(math.simplify('phi', ['phi -> 1']).toString(), '1'); + assert.equal(math.simplify('SQRT1_2', ['SQRT1_2 -> 1']).toString(), '1'); + assert.equal(math.simplify('SQRT2', ['SQRT2 -> 1']).toString(), '1'); + assert.equal(math.simplify('tau', ['tau -> 1']).toString(), '1'); + }); + + it('should throw an error for invalid built-in constant symbols in rules', function() { + assert.throws(function(){ math.simplify('null', ['null -> 1']).toString(); }); + assert.throws(function(){ math.simplify('uninitialized', ['uninitialized -> 1']).toString(); }); + assert.throws(function(){ math.simplify('version', ['version -> 1']).toString(); }); }); it('should remove addition of 0', function() {