Merge pull request #840 from tetslee/fix838

Fixed simplify to recognize named constants
This commit is contained in:
Jos de Jong 2017-05-09 20:12:28 +02:00 committed by GitHub
commit 71221b75df
2 changed files with 62 additions and 7 deletions

View File

@ -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'));
@ -125,6 +125,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.
@ -506,7 +528,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.
@ -547,11 +580,8 @@ function factory (type, config, load, typed) {
}
}
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 [];
}
}
@ -618,5 +648,6 @@ function factory (type, config, load, typed) {
return simplify;
}
exports.math = true;
exports.name = 'simplify';
exports.factory = factory;

View File

@ -83,6 +83,30 @@ describe('simplify', function() {
simplifyAndCompare('foo(x)', 'foo(x)');
});
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() {
simplifyAndCompare('x+0', 'x');
simplifyAndCompare('x-0', 'x');