Intial Commit
This commit is contained in:
187
nodered/rootfs/data/node_modules/mathjs/test/expression/Help.test.js
generated
vendored
Normal file
187
nodered/rootfs/data/node_modules/mathjs/test/expression/Help.test.js
generated
vendored
Normal file
@@ -0,0 +1,187 @@
|
||||
// test Help
|
||||
var assert = require('assert');
|
||||
var math = require('../../index');
|
||||
var Help = math.type.Help;
|
||||
|
||||
describe('help', function() {
|
||||
var doc = {
|
||||
'name': 'add',
|
||||
'category': 'Operators',
|
||||
'syntax': [
|
||||
'x + y',
|
||||
'add(x, y)'
|
||||
],
|
||||
'description': 'Add two values.',
|
||||
'examples': [
|
||||
'a = 2.1 + 3.6',
|
||||
'a - 3.6'
|
||||
],
|
||||
'seealso': [
|
||||
'subtract'
|
||||
]
|
||||
};
|
||||
|
||||
it('should generate the help for a function', function() {
|
||||
var help = new Help(doc);
|
||||
|
||||
assert(help instanceof Help);
|
||||
assert.deepEqual(help.doc.name, 'add');
|
||||
assert.deepEqual(help.doc, doc);
|
||||
});
|
||||
|
||||
it('should throw an error when constructed without new operator', function() {
|
||||
assert.throws(function () {
|
||||
Help(math.expression.docs.sin);
|
||||
}, /Constructor must be called with the new operator/)
|
||||
});
|
||||
|
||||
it('should throw an error when constructed without doc argument', function() {
|
||||
assert.throws(function () {
|
||||
new Help();
|
||||
}, /Argument "doc" missing/)
|
||||
});
|
||||
|
||||
it('should have a property isHelp', function () {
|
||||
var a = new Help(doc);
|
||||
assert.strictEqual(a.isHelp, true);
|
||||
});
|
||||
|
||||
it('should have a property type', function () {
|
||||
var a = new Help(doc);
|
||||
assert.strictEqual(a.type, 'Help');
|
||||
});
|
||||
|
||||
it('should stringify a help', function() {
|
||||
var help = new Help(doc);
|
||||
assert.equal(help.toString(),
|
||||
'\nName: add\n' +
|
||||
'\n'+
|
||||
'Category: Operators\n' +
|
||||
'\n' +
|
||||
'Description:\n' +
|
||||
' Add two values.\n' +
|
||||
'\n' +
|
||||
'Syntax:\n' +
|
||||
' x + y\n' +
|
||||
' add(x, y)\n' +
|
||||
'\n' +
|
||||
'Examples:\n' +
|
||||
' a = 2.1 + 3.6\n' +
|
||||
' 5.7\n' +
|
||||
' a - 3.6\n' +
|
||||
' 2.1\n' +
|
||||
'\n' +
|
||||
'See also: subtract\n');
|
||||
});
|
||||
|
||||
it('should stringify a help with empty doc', function() {
|
||||
var help = new Help({});
|
||||
assert.equal(help.toString(), '\n');
|
||||
});
|
||||
|
||||
it('should stringify a doc with empty example', function() {
|
||||
var help = new Help({
|
||||
'name': 'add',
|
||||
'examples': [
|
||||
'2 + 3',
|
||||
''
|
||||
]
|
||||
});
|
||||
|
||||
assert.equal(help.toString(),
|
||||
'\nName: add\n' +
|
||||
'\n'+
|
||||
'Examples:\n' +
|
||||
' 2 + 3\n' +
|
||||
' 5\n' +
|
||||
' \n' +
|
||||
'\n');
|
||||
});
|
||||
|
||||
it('should stringify a doc with example throwing an error', function() {
|
||||
var help = new Help({
|
||||
'name': 'add',
|
||||
'examples': [
|
||||
'2 ^^ 3'
|
||||
]
|
||||
});
|
||||
|
||||
assert.equal(help.toString(),
|
||||
'\nName: add\n' +
|
||||
'\n'+
|
||||
'Examples:\n' +
|
||||
' 2 ^^ 3\n' +
|
||||
' SyntaxError: Value expected (char 4)\n' +
|
||||
'\n');
|
||||
});
|
||||
|
||||
it('should return string representation on valueOf', function() {
|
||||
var help = new Help({
|
||||
'name': 'add',
|
||||
'examples': [
|
||||
'2 ^^ 3'
|
||||
]
|
||||
});
|
||||
|
||||
assert.strictEqual(help.valueOf(),
|
||||
'\nName: add\n' +
|
||||
'\n'+
|
||||
'Examples:\n' +
|
||||
' 2 ^^ 3\n' +
|
||||
' SyntaxError: Value expected (char 4)\n' +
|
||||
'\n');
|
||||
});
|
||||
|
||||
it('should export doc to JSON', function() {
|
||||
var help = new Help(doc);
|
||||
var json = help.toJSON();
|
||||
assert.deepEqual(json, {
|
||||
'mathjs': 'Help',
|
||||
'name': 'add',
|
||||
'category': 'Operators',
|
||||
'syntax': [
|
||||
'x + y',
|
||||
'add(x, y)'
|
||||
],
|
||||
'description': 'Add two values.',
|
||||
'examples': [
|
||||
'a = 2.1 + 3.6',
|
||||
'a - 3.6'
|
||||
],
|
||||
'seealso': [
|
||||
'subtract'
|
||||
]
|
||||
});
|
||||
json.name = 'foo'; // this should not alter the original doc
|
||||
json.examples.push('2 + 3'); // this should not alter the original doc
|
||||
assert.equal(doc.name, 'add');
|
||||
assert.notEqual(json.examples.length, doc.examples.length);
|
||||
});
|
||||
|
||||
it('should instantiate Help from json using fromJSON', function() {
|
||||
var doc = {
|
||||
'name': 'add',
|
||||
'category': 'Operators',
|
||||
'syntax': [
|
||||
'x + y',
|
||||
'add(x, y)'
|
||||
],
|
||||
'description': 'Add two values.',
|
||||
'examples': [
|
||||
'a = 2.1 + 3.6',
|
||||
'a - 3.6'
|
||||
],
|
||||
'seealso': [
|
||||
'subtract'
|
||||
]
|
||||
};
|
||||
|
||||
var json = Object.create(doc);
|
||||
json['mathjs'] = 'Help';
|
||||
|
||||
var help = Help.fromJSON(json);
|
||||
assert(help instanceof Help);
|
||||
assert.deepEqual(doc, help.doc);
|
||||
});
|
||||
|
||||
});
|
||||
152
nodered/rootfs/data/node_modules/mathjs/test/expression/Parser.test.js
generated
vendored
Normal file
152
nodered/rootfs/data/node_modules/mathjs/test/expression/Parser.test.js
generated
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
// test parser
|
||||
|
||||
var assert = require('assert'),
|
||||
approx = require('../../tools/approx'),
|
||||
math = require('../../index'),
|
||||
Parser = math.expression.Parser;
|
||||
|
||||
describe('parser', function() {
|
||||
|
||||
it ('should create a parser', function () {
|
||||
var parser = new Parser();
|
||||
assert.ok(parser instanceof Parser);
|
||||
});
|
||||
|
||||
it('should have a property isParser', function () {
|
||||
var a = new Parser();
|
||||
assert.strictEqual(a.isParser, true);
|
||||
});
|
||||
|
||||
it('should have a property type', function () {
|
||||
var a = new Parser();
|
||||
assert.strictEqual(a.type, 'Parser');
|
||||
});
|
||||
|
||||
it ('should throw an error when using deprecated function parse', function () {
|
||||
var parser = new Parser();
|
||||
|
||||
assert.throws(function () {parser.parse('2 + 3');}, /is deprecated/);
|
||||
});
|
||||
|
||||
it ('should throw an error when using deprecated function compile', function () {
|
||||
var parser = new Parser();
|
||||
|
||||
assert.throws(function () {parser.compile('2 + 3');}, /is deprecated/);
|
||||
});
|
||||
|
||||
it ('should evaluate an expression', function () {
|
||||
var parser = new Parser();
|
||||
|
||||
var result = parser.eval('2 + 3');
|
||||
assert.equal(result, 5);
|
||||
});
|
||||
|
||||
it ('should get variables from the parsers namespace ', function () {
|
||||
var parser = new Parser();
|
||||
|
||||
parser.eval('a = 3');
|
||||
parser.eval('b = a + 2');
|
||||
assert.equal(parser.eval('a'), 3);
|
||||
assert.equal(parser.eval('b'), 5);
|
||||
assert.equal(parser.get('a'), 3);
|
||||
assert.equal(parser.get('b'), 5);
|
||||
});
|
||||
|
||||
it ('should get all variables from the parsers namespace ', function () {
|
||||
var parser = new Parser();
|
||||
|
||||
parser.eval('a = 3');
|
||||
parser.eval('b = a + 2');
|
||||
assert.deepEqual(parser.getAll(), {a: 3, b: 5});
|
||||
|
||||
parser.remove('a');
|
||||
assert.deepEqual(parser.getAll(), {b: 5});
|
||||
});
|
||||
|
||||
it ('should return null when getting a non existing variable', function () {
|
||||
var parser = new Parser();
|
||||
|
||||
assert.equal(parser.get('non_existing_variable'), null);
|
||||
});
|
||||
|
||||
it ('should set variables in the parsers namespace ', function () {
|
||||
var parser = new Parser();
|
||||
|
||||
assert.equal(parser.set('a', 3), 3);
|
||||
assert.equal(parser.eval('a'), 3);
|
||||
assert.equal(parser.eval('a + 2'), 5);
|
||||
|
||||
// adjust variable
|
||||
assert.equal(parser.eval('a = a + 2'), 5);
|
||||
assert.equal(parser.eval('a'), 5);
|
||||
assert.equal(parser.get('a'), 5);
|
||||
|
||||
assert.equal(parser.set('a', parser.get('a') - 4), 1);
|
||||
assert.equal(parser.eval('a'), 1);
|
||||
});
|
||||
|
||||
it ('should remove a variable from the parsers namespace ', function () {
|
||||
var parser = new Parser();
|
||||
|
||||
assert.equal(parser.set('qq', 3), 3);
|
||||
assert.equal(parser.eval('qq'), 3);
|
||||
assert.equal(parser.get('qq'), 3);
|
||||
|
||||
parser.remove('qq');
|
||||
assert.equal(parser.get('qq'), null);
|
||||
assert.throws(function () {parser.eval('qq')});
|
||||
|
||||
assert.equal(parser.eval('ww = 5'), 5);
|
||||
assert.equal(parser.get('ww'), 5);
|
||||
parser.remove('ww');
|
||||
assert.equal(parser.get('ww'), null);
|
||||
assert.throws(function () {parser.eval('ww')});
|
||||
});
|
||||
|
||||
it ('should clear the parsers namespace ', function () {
|
||||
var parser = new Parser();
|
||||
|
||||
assert.equal(parser.eval('xx = yy = zz = 5'), 5);
|
||||
|
||||
assert.equal(parser.set('pi', 'oops'), 'oops');
|
||||
|
||||
assert.equal(parser.get('xx'), 5);
|
||||
assert.equal(parser.get('yy'), 5);
|
||||
assert.equal(parser.get('zz'), 5);
|
||||
assert.equal(parser.get('pi'), 'oops');
|
||||
|
||||
assert.equal(parser.eval('xx'), 5);
|
||||
assert.equal(parser.eval('yy'), 5);
|
||||
assert.equal(parser.eval('zz'), 5);
|
||||
assert.equal(parser.eval('pi'), 'oops');
|
||||
|
||||
parser.clear();
|
||||
|
||||
assert.equal(parser.get('xx'), null);
|
||||
assert.equal(parser.get('yy'), null);
|
||||
assert.equal(parser.get('zz'), null);
|
||||
approx.equal(parser.get('pi'), null);
|
||||
|
||||
assert.throws(function () {parser.eval('xx')});
|
||||
assert.throws(function () {parser.eval('yy')});
|
||||
assert.throws(function () {parser.eval('zz')});
|
||||
assert.equal(parser.eval('pi'), Math.PI);
|
||||
|
||||
});
|
||||
|
||||
it ('should not clear inherited properties', function () {
|
||||
var parser = new Parser();
|
||||
|
||||
Object.prototype.foo = 'bar';
|
||||
|
||||
parser.clear();
|
||||
|
||||
assert.equal(parser.get('foo'), 'bar');
|
||||
|
||||
delete Object.prototype.foo;
|
||||
});
|
||||
|
||||
it ('should throw an exception when creating a parser without new', function () {
|
||||
assert.throws(function () {Parser()}, /Constructor must be called with the new operator/);
|
||||
});
|
||||
});
|
||||
37
nodered/rootfs/data/node_modules/mathjs/test/expression/function/compile.test.js
generated
vendored
Normal file
37
nodered/rootfs/data/node_modules/mathjs/test/expression/function/compile.test.js
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
// test compile
|
||||
var assert = require('assert');
|
||||
var math = require('../../../index');
|
||||
|
||||
describe('compile', function() {
|
||||
|
||||
it('should compile an expression', function() {
|
||||
var code = math.compile('(5+3)/4');
|
||||
assert.ok(code instanceof Object);
|
||||
assert.ok(code.eval instanceof Function);
|
||||
assert.equal(code.eval(), 2);
|
||||
});
|
||||
|
||||
it('should parse multiple expressions', function() {
|
||||
var codes = math.compile(['2+3', '4+5']);
|
||||
assert.ok(Array.isArray(codes));
|
||||
assert.equal(codes.length, 2);
|
||||
|
||||
assert.equal(codes[0].eval(), 5);
|
||||
assert.equal(codes[1].eval(), 9);
|
||||
});
|
||||
|
||||
it('should throw an error on wrong number of arguments', function() {
|
||||
assert.throws(function () {math.compile()}, /TypeError: Too few arguments/);
|
||||
assert.throws(function () {math.compile('2+3', '3+4')}, /TypeError: Too many arguments/);
|
||||
});
|
||||
|
||||
it('should throw an error on wrong type of argument', function() {
|
||||
assert.throws(function () {math.compile(math.complex(2, 3))}, TypeError);
|
||||
});
|
||||
|
||||
it('should LaTeX compile', function () {
|
||||
var expression = math.parse('compile(1)');
|
||||
assert.equal(expression.toTex(), '\\mathrm{compile}\\left(1\\right)');
|
||||
});
|
||||
|
||||
});
|
||||
79
nodered/rootfs/data/node_modules/mathjs/test/expression/function/eval.test.js
generated
vendored
Normal file
79
nodered/rootfs/data/node_modules/mathjs/test/expression/function/eval.test.js
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
// test eval
|
||||
var assert = require('assert');
|
||||
var approx = require('../../../tools/approx');
|
||||
var math = require('../../../index');
|
||||
var Complex = math.type.Complex;
|
||||
var Matrix = math.type.Matrix;
|
||||
var Unit = math.type.Unit;
|
||||
var ResultSet = math.type.ResultSet;
|
||||
|
||||
describe('eval', function() {
|
||||
|
||||
it('should evaluate expressions', function() {
|
||||
approx.equal(math.eval('(2+3)/4'), 1.25);
|
||||
assert.deepEqual(math.eval('sqrt(-4)'), new Complex(0, 2));
|
||||
});
|
||||
|
||||
it('should eval a list of expressions', function() {
|
||||
assert.deepEqual(math.eval(['1+2', '3+4', '5+6']), [3, 7, 11]);
|
||||
assert.deepEqual(math.eval(['a=3', 'b=4', 'a*b']), [3, 4, 12]);
|
||||
assert.deepEqual(math.eval(math.matrix(['a=3', 'b=4', 'a*b'])), math.matrix([3, 4, 12]));
|
||||
assert.deepEqual(math.eval(['a=3', 'b=4', 'a*b']), [3, 4, 12]);
|
||||
});
|
||||
|
||||
it('should eval a series of expressions', function() {
|
||||
assert.deepEqual(math.eval('a=3\nb=4\na*b'), new ResultSet([3, 4, 12]));
|
||||
assert.deepEqual(math.eval('f(x) = a * x; a=2; f(4)'), new ResultSet([8]));
|
||||
assert.deepEqual(math.eval('b = 43; b * 4'), new ResultSet([172]));
|
||||
});
|
||||
|
||||
it('should throw an error if wrong number of arguments', function() {
|
||||
assert.throws(function () {math.eval()}, /TypeError: Too few arguments/);
|
||||
assert.throws(function () {math.eval('', {}, 3)}, /TypeError: Too many arguments/);
|
||||
});
|
||||
|
||||
it('should throw an error with a unit', function() {
|
||||
assert.throws(function () {math.eval(new Unit(5, 'cm'))}, /TypeError: Unexpected type of argument/);
|
||||
});
|
||||
|
||||
it('should throw an error with a complex number', function() {
|
||||
assert.throws(function () {math.eval(new Complex(2,3))}, /TypeError: Unexpected type of argument/);
|
||||
});
|
||||
|
||||
it('should throw an error with a boolean', function() {
|
||||
assert.throws(function () {math.eval(true)}, TypeError);
|
||||
});
|
||||
|
||||
it('should handle the given scope', function() {
|
||||
var scope = {
|
||||
a: 3,
|
||||
b: 4
|
||||
};
|
||||
assert.deepEqual(math.eval('a*b', scope), 12);
|
||||
assert.deepEqual(math.eval('c=5', scope), 5);
|
||||
assert.deepEqual(math.format(math.eval('f(x) = x^a', scope)), 'f(x)');
|
||||
|
||||
assert.deepEqual(Object.keys(scope).length, 4);
|
||||
assert.deepEqual(scope.a, 3);
|
||||
assert.deepEqual(scope.b, 4);
|
||||
assert.deepEqual(scope.c, 5);
|
||||
assert.deepEqual(typeof scope.f, 'function');
|
||||
|
||||
assert.equal(scope.f(3), 27);
|
||||
scope.a = 2;
|
||||
assert.equal(scope.f(3), 9);
|
||||
scope.hello = function (name) {
|
||||
return 'hello, ' + name + '!';
|
||||
};
|
||||
assert.deepEqual(math.eval('hello("jos")', scope), 'hello, jos!');
|
||||
});
|
||||
|
||||
it('should LaTeX eval', function () {
|
||||
var expr1 = math.parse('eval(expr)');
|
||||
var expr2 = math.parse('eval(expr,scope)');
|
||||
|
||||
assert.equal(expr1.toTex(), '\\mathrm{eval}\\left( expr\\right)');
|
||||
assert.equal(expr2.toTex(), '\\mathrm{eval}\\left( expr, scope\\right)');
|
||||
});
|
||||
|
||||
});
|
||||
60
nodered/rootfs/data/node_modules/mathjs/test/expression/function/help.test.js
generated
vendored
Normal file
60
nodered/rootfs/data/node_modules/mathjs/test/expression/function/help.test.js
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
var assert = require('assert'),
|
||||
error = require('../../../lib/error/index'),
|
||||
math = require('../../../index');
|
||||
|
||||
describe('help', function() {
|
||||
|
||||
it('should find documentation for a function by its name', function() {
|
||||
var help = math.help('sin');
|
||||
assert.ok(help instanceof math.type.Help);
|
||||
assert.deepEqual(help.doc, math.expression.docs.sin);
|
||||
});
|
||||
|
||||
it('should find documentation for a function by the function itself', function() {
|
||||
var help = math.help(math.sin);
|
||||
assert.ok(help instanceof math.type.Help);
|
||||
assert.deepEqual(help.doc, math.expression.docs.sin);
|
||||
});
|
||||
|
||||
it('should throw an error on wrong number of arguments', function() {
|
||||
assert.throws(function () {math.help()}, /TypeError: Too few arguments/);
|
||||
assert.throws(function () {math.help('sin', 2)}, /TypeError: Too many arguments/);
|
||||
});
|
||||
|
||||
it('should find help from a function name', function() {
|
||||
var help = math.help('sin');
|
||||
assert(help instanceof math.type.Help);
|
||||
assert.equal(help.doc.name, 'sin');
|
||||
});
|
||||
|
||||
it('should find help from a function', function() {
|
||||
var help = math.help(math.sin);
|
||||
assert(help instanceof math.type.Help);
|
||||
assert.equal(help.doc.name, 'sin');
|
||||
});
|
||||
|
||||
it('should find help from a constant name', function() {
|
||||
var help = math.help('pi');
|
||||
assert(help instanceof math.type.Help);
|
||||
assert.equal(help.doc.name, 'pi');
|
||||
});
|
||||
|
||||
it('should find help from a constant', function() {
|
||||
var help = math.help(math.pi);
|
||||
assert(help instanceof math.type.Help);
|
||||
assert.equal(help.doc.name, 'pi');
|
||||
});
|
||||
|
||||
it('should throw an error when no help is found', function() {
|
||||
// assert.throws(function () {math.help(undefined)}, /No documentation found/);
|
||||
assert.throws(function () {math.help(new Date())}, /No documentation found/);
|
||||
assert.throws(function () {math.help('nonExistingFunction')}, /No documentation found/);
|
||||
assert.throws(function () {math.help('parse')}, /No documentation found/);
|
||||
});
|
||||
|
||||
it('should LaTeX help', function () {
|
||||
var expression = math.parse('help(parse)');
|
||||
assert.equal(expression.toTex(), '\\mathrm{help}\\left( parse\\right)');
|
||||
});
|
||||
|
||||
});
|
||||
31
nodered/rootfs/data/node_modules/mathjs/test/expression/function/parse.test.js
generated
vendored
Normal file
31
nodered/rootfs/data/node_modules/mathjs/test/expression/function/parse.test.js
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
// test parse
|
||||
var assert = require('assert');
|
||||
var error = require('../../../lib/error/index');
|
||||
var math = require('../../../index');
|
||||
var Node = math.expression.node.Node;
|
||||
|
||||
describe('parse', function() {
|
||||
|
||||
it('should parse an expression', function() {
|
||||
var node = math.parse('(5+3)/4');
|
||||
assert.ok(node instanceof Node);
|
||||
assert.equal(node.compile().eval(), 2);
|
||||
});
|
||||
|
||||
it('should parse multiple expressions', function() {
|
||||
var nodes = math.parse(['2+3', '4+5']);
|
||||
assert.ok(Array.isArray(nodes));
|
||||
assert.equal(nodes.length, 2);
|
||||
|
||||
assert.ok(nodes[0] instanceof Node);
|
||||
assert.ok(nodes[1] instanceof Node);
|
||||
assert.equal(nodes[0].compile().eval(), 5);
|
||||
assert.equal(nodes[1].compile().eval(), 9);
|
||||
});
|
||||
|
||||
it('should LaTeX parse', function () {
|
||||
var expression = math.parse('parse(expr,options)');
|
||||
assert.equal(expression.toTex(), '\\mathrm{parse}\\left( expr, options\\right)');
|
||||
});
|
||||
|
||||
});
|
||||
19
nodered/rootfs/data/node_modules/mathjs/test/expression/function/parser.test.js
generated
vendored
Normal file
19
nodered/rootfs/data/node_modules/mathjs/test/expression/function/parser.test.js
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
var assert = require('assert');
|
||||
var math = require('../../../index');
|
||||
var Parser = math.expression.Parser;
|
||||
|
||||
describe('parser', function() {
|
||||
|
||||
it('should create a parser', function() {
|
||||
var parser = math.parser();
|
||||
|
||||
assert(parser instanceof Parser);
|
||||
});
|
||||
|
||||
it('should LaTeX parser', function () { //This doesn't really make sense in a way
|
||||
var expression = math.parse('parser()');
|
||||
assert.equal(expression.toTex(), '\\mathrm{parser}\\left(\\right)');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
11
nodered/rootfs/data/node_modules/mathjs/test/expression/keywords.test.js
generated
vendored
Normal file
11
nodered/rootfs/data/node_modules/mathjs/test/expression/keywords.test.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
// test keywords
|
||||
var assert = require('assert'),
|
||||
keywords = require('../../lib/expression/keywords');
|
||||
|
||||
describe('keywords', function() {
|
||||
|
||||
it('should return a map with reserved keywords', function() {
|
||||
assert.deepEqual(Object.keys(keywords).sort(), ['end'].sort());
|
||||
});
|
||||
|
||||
});
|
||||
465
nodered/rootfs/data/node_modules/mathjs/test/expression/node/AccessorNode.test.js
generated
vendored
Normal file
465
nodered/rootfs/data/node_modules/mathjs/test/expression/node/AccessorNode.test.js
generated
vendored
Normal file
@@ -0,0 +1,465 @@
|
||||
// test AccessorNode
|
||||
var assert = require('assert');
|
||||
var approx = require('../../../tools/approx');
|
||||
var math = require('../../../index');
|
||||
var bigmath = require('../../../index').create({number: 'BigNumber'});
|
||||
var Node = math.expression.node.Node;
|
||||
var ConstantNode = math.expression.node.ConstantNode;
|
||||
var OperatorNode = math.expression.node.OperatorNode;
|
||||
var SymbolNode = math.expression.node.SymbolNode;
|
||||
var AccessorNode = math.expression.node.AccessorNode;
|
||||
var IndexNode = math.expression.node.IndexNode;
|
||||
var RangeNode = math.expression.node.RangeNode;
|
||||
|
||||
describe('AccessorNode', function() {
|
||||
|
||||
it ('should create a AccessorNode', function () {
|
||||
var n = new AccessorNode(new Node(), new IndexNode([]));
|
||||
assert(n instanceof AccessorNode);
|
||||
assert(n instanceof Node);
|
||||
assert.equal(n.type, 'AccessorNode');
|
||||
});
|
||||
|
||||
it ('should have isAccessorNode', function () {
|
||||
var node = new AccessorNode(new Node(), new IndexNode([]));
|
||||
assert(node.isAccessorNode);
|
||||
});
|
||||
|
||||
it ('should throw an error when calling with wrong arguments', function () {
|
||||
assert.throws(function () {new AccessorNode()}, TypeError);
|
||||
assert.throws(function () {new AccessorNode('a', new IndexNode([]))}, TypeError);
|
||||
assert.throws(function () {new AccessorNode(new Node, new IndexNode([2, 3]))}, TypeError);
|
||||
assert.throws(function () {new AccessorNode(new Node, new IndexNode([new Node(), 3]))}, TypeError);
|
||||
});
|
||||
|
||||
it ('should throw an error when calling without new operator', function () {
|
||||
assert.throws(function () {AccessorNode(new Node(), new IndexNode([]))}, SyntaxError);
|
||||
});
|
||||
|
||||
it ('should get the name of an AccessorNode', function () {
|
||||
var n = new AccessorNode(new SymbolNode('a'), new IndexNode([new ConstantNode('toString')]));
|
||||
assert.equal(n.name, 'toString');
|
||||
|
||||
var n = new AccessorNode(new SymbolNode('a'), new IndexNode([new ConstantNode(1)]));
|
||||
assert.equal(n.name, '');
|
||||
});
|
||||
|
||||
it ('should compile a AccessorNode', function () {
|
||||
var a = new bigmath.expression.node.SymbolNode('a');
|
||||
var index = new IndexNode([
|
||||
new bigmath.expression.node.ConstantNode(2),
|
||||
new bigmath.expression.node.ConstantNode(1)
|
||||
]);
|
||||
var n = new bigmath.expression.node.AccessorNode(a, index);
|
||||
var expr = n.compile();
|
||||
|
||||
var scope = {
|
||||
a: [[1, 2], [3, 4]]
|
||||
};
|
||||
assert.equal(expr.eval(scope), 3);
|
||||
});
|
||||
|
||||
it ('should compile a AccessorNode with range and context parameters', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var index = new IndexNode([
|
||||
new ConstantNode(2),
|
||||
new RangeNode(
|
||||
new ConstantNode(1),
|
||||
new SymbolNode('end')
|
||||
)
|
||||
]);
|
||||
var n = new AccessorNode(a, index);
|
||||
var expr = n.compile();
|
||||
|
||||
var scope = {
|
||||
a: [[1, 2], [3, 4]]
|
||||
};
|
||||
assert.deepEqual(expr.eval(scope), [[3, 4]]);
|
||||
});
|
||||
|
||||
it ('should compile a AccessorNode with a property', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var index = new IndexNode([new ConstantNode('b')]);
|
||||
var n = new AccessorNode(a, index);
|
||||
var expr = n.compile();
|
||||
|
||||
var scope = {
|
||||
a: { b: 42 }
|
||||
};
|
||||
assert.deepEqual(expr.eval(scope), 42);
|
||||
});
|
||||
|
||||
it ('should throw a one-based index error when out of range (Array)', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var index = new IndexNode([new ConstantNode(4)]);
|
||||
var n = new AccessorNode(a, index);
|
||||
var expr = n.compile();
|
||||
|
||||
var scope = {
|
||||
a: [1,2,3]
|
||||
};
|
||||
assert.throws(function () { expr.eval(scope) }, /Index out of range \(4 > 3\)/);
|
||||
});
|
||||
|
||||
it ('should throw a one-based index error when out of range (Matrix)', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var index = new IndexNode([new ConstantNode(4)]);
|
||||
var n = new AccessorNode(a, index);
|
||||
var expr = n.compile();
|
||||
|
||||
var scope = {
|
||||
a: math.matrix([1,2,3])
|
||||
};
|
||||
assert.throws(function () { expr.eval(scope) }, /Index out of range \(4 > 3\)/);
|
||||
});
|
||||
|
||||
it ('should throw a one-based index error when out of range (string)', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var index = new IndexNode([new ConstantNode(4)]);
|
||||
var n = new AccessorNode(a, index);
|
||||
var expr = n.compile();
|
||||
|
||||
var scope = {
|
||||
a: 'hey'
|
||||
};
|
||||
assert.throws(function () { expr.eval(scope) }, /Index out of range \(4 > 3\)/);
|
||||
});
|
||||
|
||||
it ('should throw an error when applying a matrix index onto an object', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var index = new IndexNode([new ConstantNode(4)]);
|
||||
var n = new AccessorNode(a, index);
|
||||
var expr = n.compile();
|
||||
|
||||
var scope = {
|
||||
a: {}
|
||||
};
|
||||
assert.throws(function () { expr.eval(scope) }, /Cannot apply a numeric index as object property/);
|
||||
});
|
||||
|
||||
it ('should throw an error when applying an index onto a scalar', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var index = new IndexNode([new ConstantNode(4)]);
|
||||
var n = new AccessorNode(a, index);
|
||||
var expr = n.compile();
|
||||
|
||||
var scope = {
|
||||
a: 42
|
||||
};
|
||||
assert.throws(function () { expr.eval(scope) }, /Cannot apply index: unsupported type of object/);
|
||||
});
|
||||
|
||||
it ('should compile a AccessorNode with negative step range and context parameters', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var index = new IndexNode([
|
||||
new ConstantNode(2),
|
||||
new RangeNode(
|
||||
new SymbolNode('end'),
|
||||
new ConstantNode(1),
|
||||
new ConstantNode(-1)
|
||||
)
|
||||
]);
|
||||
var n = new AccessorNode(a, index);
|
||||
var expr = n.compile();
|
||||
|
||||
var scope = {
|
||||
a: [[1, 2], [3, 4]]
|
||||
};
|
||||
assert.deepEqual(expr.eval(scope), [[4, 3]]);
|
||||
});
|
||||
|
||||
it ('should compile a AccessorNode with "end" both as value and in a range', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var index = new IndexNode([
|
||||
new SymbolNode('end'),
|
||||
new RangeNode(
|
||||
new ConstantNode(1),
|
||||
new SymbolNode('end')
|
||||
)
|
||||
]);
|
||||
var n = new AccessorNode(a, index);
|
||||
var expr = n.compile();
|
||||
|
||||
var scope = {
|
||||
a: [[1, 2], [3, 4]]
|
||||
};
|
||||
assert.deepEqual(expr.eval(scope), [[3, 4]]);
|
||||
});
|
||||
|
||||
it ('should compile a AccessorNode with bignumber setting', function () {
|
||||
var a = new bigmath.expression.node.SymbolNode('a');
|
||||
var b = new bigmath.expression.node.ConstantNode(2);
|
||||
var c = new bigmath.expression.node.ConstantNode(1);
|
||||
var n = new bigmath.expression.node.AccessorNode(a, new IndexNode([b, c]));
|
||||
var expr = n.compile();
|
||||
|
||||
var scope = {
|
||||
a: [[1, 2], [3, 4]]
|
||||
};
|
||||
assert.deepEqual(expr.eval(scope), 3);
|
||||
});
|
||||
|
||||
it ('should filter an AccessorNode', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(1);
|
||||
var index = new IndexNode([b, c]);
|
||||
var n = new AccessorNode(a, index);
|
||||
|
||||
assert.deepEqual(n.filter(function (node) {return node.isAccessorNode}), [n]);
|
||||
assert.deepEqual(n.filter(function (node) {return node.isSymbolNode}), [a]);
|
||||
assert.deepEqual(n.filter(function (node) {return node.isRangeNode}), []);
|
||||
assert.deepEqual(n.filter(function (node) {return node.isConstantNode}), [b, c]);
|
||||
assert.deepEqual(n.filter(function (node) {return node.isConstantNode && node.value == '2'}), [b]);
|
||||
assert.deepEqual(n.filter(function (node) {return node.isConstantNode && node.value == '4'}), []);
|
||||
});
|
||||
|
||||
it ('should filter an empty AccessorNode', function () {
|
||||
var n = new AccessorNode(new SymbolNode('a'), new IndexNode([]));
|
||||
|
||||
assert.deepEqual(n.filter(function (node) {return node.isAccessorNode}), [n]);
|
||||
assert.deepEqual(n.filter(function (node) {return node.isConstantNode}), []);
|
||||
});
|
||||
|
||||
it ('should run forEach on an AccessorNode', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(1);
|
||||
var index = new IndexNode([b, c]);
|
||||
var n = new AccessorNode(a, index);
|
||||
|
||||
var nodes = [];
|
||||
var paths = [];
|
||||
n.forEach(function (node, path, parent) {
|
||||
nodes.push(node);
|
||||
paths.push(path);
|
||||
assert.strictEqual(parent, n);
|
||||
});
|
||||
|
||||
assert.equal(nodes.length, 2);
|
||||
assert.strictEqual(nodes[0], a);
|
||||
assert.strictEqual(nodes[1], index);
|
||||
assert.deepEqual(paths, ['object', 'index']);
|
||||
});
|
||||
|
||||
it ('should map an AccessorNode', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(1);
|
||||
var index = new IndexNode([b, c]);
|
||||
var n = new AccessorNode(a, index);
|
||||
|
||||
var nodes = [];
|
||||
var paths = [];
|
||||
var e = new SymbolNode('c');
|
||||
var f = n.map(function (node, path, parent) {
|
||||
nodes.push(node);
|
||||
paths.push(path);
|
||||
assert.strictEqual(parent, n);
|
||||
|
||||
return node instanceof SymbolNode ? e : node;
|
||||
});
|
||||
|
||||
assert.equal(nodes.length, 2);
|
||||
assert.strictEqual(nodes[0], a);
|
||||
assert.strictEqual(nodes[1], index);
|
||||
assert.deepEqual(paths, ['object', 'index']);
|
||||
|
||||
assert.notStrictEqual(f, n);
|
||||
assert.deepEqual(f.object, e);
|
||||
assert.deepEqual(f.index.dimensions[0], b);
|
||||
assert.deepEqual(f.index.dimensions[1], c);
|
||||
});
|
||||
|
||||
it ('should throw an error when the map callback does not return a node', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(1);
|
||||
var n = new AccessorNode(a, new IndexNode([b, c]));
|
||||
|
||||
assert.throws(function () {
|
||||
n.map(function () {});
|
||||
}, /Callback function must return a Node/)
|
||||
});
|
||||
|
||||
it ('should transform an IndexNodes object', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(1);
|
||||
var n = new AccessorNode(a, new IndexNode([b, c]));
|
||||
|
||||
var e = new SymbolNode('c');
|
||||
var f = n.transform(function (node) {
|
||||
return node instanceof SymbolNode ? e : node;
|
||||
});
|
||||
|
||||
assert.notStrictEqual(f, n);
|
||||
assert.deepEqual(f.object, e);
|
||||
assert.deepEqual(f.index.dimensions[0], b);
|
||||
assert.deepEqual(f.index.dimensions[1], c);
|
||||
});
|
||||
|
||||
it ('should transform an IndexNodes (nested) parameters', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(1);
|
||||
var n = new AccessorNode(a, new IndexNode([b, c]));
|
||||
|
||||
var e = new SymbolNode('c');
|
||||
var f = n.transform(function (node) {
|
||||
return node instanceof ConstantNode && node.value == '1' ? e : node;
|
||||
});
|
||||
|
||||
assert.notStrictEqual(f, n);
|
||||
assert.deepEqual(f.object, a);
|
||||
assert.deepEqual(f.index.dimensions[0], b);
|
||||
assert.deepEqual(f.index.dimensions[1], e);
|
||||
});
|
||||
|
||||
it ('should transform an AccessorNode itself', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(1);
|
||||
var n = new AccessorNode(a, new IndexNode([b, c]));
|
||||
|
||||
var e = new ConstantNode(5);
|
||||
var f = n.transform(function (node) {
|
||||
return node instanceof AccessorNode ? e : node;
|
||||
});
|
||||
|
||||
assert.notStrictEqual(f, n);
|
||||
assert.deepEqual(f, e);
|
||||
});
|
||||
|
||||
it ('should clone an AccessorNode', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(1);
|
||||
var n = new AccessorNode(a, new IndexNode([b, c]));
|
||||
|
||||
var d = n.clone();
|
||||
assert(d instanceof AccessorNode);
|
||||
assert.deepEqual(d, n);
|
||||
assert.notStrictEqual(d, n);
|
||||
assert.strictEqual(d.object, n.object);
|
||||
assert.strictEqual(d.index, n.index);
|
||||
assert.strictEqual(d.index.dimensions[0], n.index.dimensions[0]);
|
||||
assert.strictEqual(d.index.dimensions[1], n.index.dimensions[1]);
|
||||
});
|
||||
|
||||
it ('should test equality of an Node', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(1);
|
||||
var node1 = new AccessorNode(a, new IndexNode([b, c]));
|
||||
|
||||
var a = new SymbolNode('a');
|
||||
var b = new SymbolNode('b');
|
||||
var c = new ConstantNode(1);
|
||||
var node2 = new AccessorNode(a, new IndexNode([b, c]));
|
||||
|
||||
var a = new SymbolNode('a');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(1);
|
||||
var node3 = new AccessorNode(a, new IndexNode([b, c]));
|
||||
|
||||
assert.strictEqual(node1.equals(null), false);
|
||||
assert.strictEqual(node1.equals(undefined), false);
|
||||
assert.strictEqual(node1.equals(node2), false);
|
||||
assert.strictEqual(node1.equals(node3), true);
|
||||
});
|
||||
|
||||
it ('should stringify an AccessorNode', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var index = new IndexNode([
|
||||
new ConstantNode(2),
|
||||
new ConstantNode(1)
|
||||
]);
|
||||
|
||||
var n = new AccessorNode(a, index);
|
||||
assert.equal(n.toString(), 'a[2, 1]');
|
||||
|
||||
var n2 = new AccessorNode(a, new IndexNode([]));
|
||||
assert.equal(n2.toString(), 'a[]')
|
||||
});
|
||||
|
||||
it ('should stringify an AccessorNode with parentheses', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var b = new SymbolNode('b');
|
||||
var add = new OperatorNode('+', 'add', [a, b]);
|
||||
var bar = new AccessorNode(add, new IndexNode([new ConstantNode('bar')]));
|
||||
assert.equal(bar.toString(), '(a + b)["bar"]');
|
||||
});
|
||||
|
||||
it ('should stringify nested AccessorNode', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var foo = new AccessorNode(a, new IndexNode([new ConstantNode('foo')]));
|
||||
var bar = new AccessorNode(foo, new IndexNode([new ConstantNode('bar')]));
|
||||
assert.equal(bar.toString(), 'a["foo"]["bar"]');
|
||||
});
|
||||
|
||||
it ('should stringigy an AccessorNode with custom toString', function () {
|
||||
//Also checks if the custom functions get passed on to the children
|
||||
var customFunction = function (node, options) {
|
||||
if (node.type === 'AccessorNode') {
|
||||
var string = node.object.toString(options) + ' at ';
|
||||
node.index.dimensions.forEach(function (range) {
|
||||
string += range.toString(options) + ', ';
|
||||
});
|
||||
|
||||
return string;
|
||||
}
|
||||
else if (node.type === 'ConstantNode') {
|
||||
return 'const(' + node.value + ', ' + node.valueType + ')'
|
||||
}
|
||||
};
|
||||
|
||||
var a = new SymbolNode('a');
|
||||
var b = new ConstantNode(1);
|
||||
var c = new ConstantNode(2);
|
||||
|
||||
var n = new AccessorNode(a, new IndexNode([b, c]));
|
||||
|
||||
assert.equal(n.toString({handler: customFunction}), 'a at const(1, number), const(2, number), ');
|
||||
});
|
||||
|
||||
it ('should LaTeX an AccessorNode', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var index = new IndexNode([
|
||||
new ConstantNode(2),
|
||||
new ConstantNode(1)
|
||||
]);
|
||||
|
||||
var n = new AccessorNode(a, index);
|
||||
assert.equal(n.toTex(), ' a_{2,1}');
|
||||
|
||||
var n2 = new AccessorNode(a, new IndexNode([]));
|
||||
assert.equal(n2.toTex(), ' a_{}')
|
||||
});
|
||||
|
||||
it ('should LaTeX an AccessorNode with custom toTex', function () {
|
||||
//Also checks if the custom functions get passed on to the children
|
||||
var customFunction = function (node, options) {
|
||||
if (node.type === 'AccessorNode') {
|
||||
var latex = node.object.toTex(options) + ' at ';
|
||||
node.index.dimensions.forEach(function (range) {
|
||||
latex += range.toTex(options) + ', ';
|
||||
});
|
||||
|
||||
return latex;
|
||||
}
|
||||
else if (node.type === 'ConstantNode') {
|
||||
return 'const\\left(' + node.value + ', ' + node.valueType + '\\right)'
|
||||
}
|
||||
};
|
||||
|
||||
var a = new SymbolNode('a');
|
||||
var b = new ConstantNode(1);
|
||||
var c = new ConstantNode(2);
|
||||
|
||||
var n = new AccessorNode(a, new IndexNode([b, c]));
|
||||
|
||||
assert.equal(n.toTex({handler: customFunction}), ' a at const\\left(1, number\\right), const\\left(2, number\\right), ');
|
||||
});
|
||||
|
||||
});
|
||||
318
nodered/rootfs/data/node_modules/mathjs/test/expression/node/ArrayNode.test.js
generated
vendored
Normal file
318
nodered/rootfs/data/node_modules/mathjs/test/expression/node/ArrayNode.test.js
generated
vendored
Normal file
@@ -0,0 +1,318 @@
|
||||
// test ArrayNode
|
||||
var assert = require('assert');
|
||||
var approx = require('../../../tools/approx');
|
||||
var math = require('../../../index');
|
||||
var Node = math.expression.node.Node;
|
||||
var ConstantNode = math.expression.node.ConstantNode;
|
||||
var SymbolNode = math.expression.node.SymbolNode;
|
||||
var RangeNode = math.expression.node.RangeNode;
|
||||
var ArrayNode = math.expression.node.ArrayNode;
|
||||
|
||||
describe('ArrayNode', function() {
|
||||
|
||||
it ('should create an ArrayNode', function () {
|
||||
var c = new ConstantNode(1);
|
||||
var a = new ArrayNode([c]);
|
||||
var b = new ArrayNode([]);
|
||||
assert(a instanceof ArrayNode);
|
||||
assert(b instanceof ArrayNode);
|
||||
assert.equal(a.type, 'ArrayNode');
|
||||
assert.equal(b.type, 'ArrayNode');
|
||||
});
|
||||
|
||||
it ('should have isArrayNode', function () {
|
||||
var node = new ArrayNode([]);
|
||||
|
||||
assert(node.isArrayNode);
|
||||
});
|
||||
|
||||
it ('should throw an error when calling without new operator', function () {
|
||||
assert.throws(function () {ArrayNode()}, SyntaxError);
|
||||
});
|
||||
|
||||
it ('should throw an error on wrong constructor arguments', function () {
|
||||
assert.throws(function () {new ArrayNode(2)}, TypeError);
|
||||
assert.throws(function () {new ArrayNode([2, 3])}, TypeError);
|
||||
});
|
||||
|
||||
it ('should evaluate an ArrayNode', function () {
|
||||
var c = new ConstantNode(1);
|
||||
var a = new ArrayNode([c]);
|
||||
var b = new ArrayNode();
|
||||
|
||||
assert.deepEqual(a.compile().eval(), math.matrix([1]));
|
||||
assert.deepEqual(b.compile().eval(), math.matrix([]));
|
||||
});
|
||||
|
||||
it ('should compile an ArrayNode and evaluate as Matrix', function () {
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(3);
|
||||
var d = new ConstantNode(4);
|
||||
var n = new ArrayNode([a, b, c, d]);
|
||||
|
||||
var expr = n.compile();
|
||||
assert.deepEqual(expr.eval(), math.matrix([1,2,3,4]));
|
||||
});
|
||||
|
||||
it ('should compile an ArrayNode and evaluate as Array', function () {
|
||||
var mathArray = math.create({matrix: 'Array'});
|
||||
var a = new mathArray.expression.node.ConstantNode(1);
|
||||
var b = new mathArray.expression.node.ConstantNode(2);
|
||||
var c = new mathArray.expression.node.ConstantNode(3);
|
||||
var d = new mathArray.expression.node.ConstantNode(4);
|
||||
var n = new mathArray.expression.node.ArrayNode([a, b, c, d]);
|
||||
var expr = n.compile();
|
||||
assert.deepEqual(expr.eval(), [1,2,3,4]);
|
||||
});
|
||||
|
||||
it ('should compile nested ArrayNodes', function () {
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(3);
|
||||
var d = new ConstantNode(4);
|
||||
|
||||
var n2 = new ArrayNode([a, b]);
|
||||
var n3 = new ArrayNode([c, d]);
|
||||
var n4 = new ArrayNode([n2, n3]);
|
||||
|
||||
var expr = n4.compile();
|
||||
assert.deepEqual(expr.eval(), math.matrix([[1,2],[3,4]]));
|
||||
});
|
||||
|
||||
it ('should find an ArrayNode', function () {
|
||||
var a = new ConstantNode(1);
|
||||
var b = new SymbolNode('x');
|
||||
var c = new ConstantNode(2);
|
||||
var d = new ArrayNode([a, b, c]);
|
||||
|
||||
assert.deepEqual(d.filter(function (node) {return node instanceof ArrayNode}), [d]);
|
||||
assert.deepEqual(d.filter(function (node) {return node instanceof SymbolNode}), [b]);
|
||||
assert.deepEqual(d.filter(function (node) {return node instanceof RangeNode}), []);
|
||||
assert.deepEqual(d.filter(function (node) {return node instanceof ConstantNode}), [a, c]);
|
||||
assert.deepEqual(d.filter(function (node) {return node instanceof ConstantNode && node.value == '2'}), [c]);
|
||||
});
|
||||
|
||||
it ('should run forEach on an ArrayNode', function () {
|
||||
// [x, 2]
|
||||
var a = new SymbolNode('x');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ArrayNode([a, b]);
|
||||
|
||||
var d = new ConstantNode(3);
|
||||
var nodes = [];
|
||||
var paths = [];
|
||||
c.forEach(function (node, path, parent) {
|
||||
nodes.push(node);
|
||||
paths.push(path);
|
||||
assert.strictEqual(parent, c);
|
||||
});
|
||||
|
||||
assert.deepEqual(paths, ['items[0]', 'items[1]']);
|
||||
assert.equal(nodes.length, 2);
|
||||
assert.strictEqual(nodes[0], a);
|
||||
assert.strictEqual(nodes[1], b);
|
||||
});
|
||||
|
||||
it ('should map an ArrayNode', function () {
|
||||
// [x, 2]
|
||||
var a = new SymbolNode('x');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ArrayNode([a, b]);
|
||||
|
||||
var d = new ConstantNode(3);
|
||||
var nodes = [];
|
||||
var paths = [];
|
||||
var e = c.map(function (node, path, parent) {
|
||||
nodes.push(node);
|
||||
paths.push(path);
|
||||
assert.strictEqual(parent, c);
|
||||
|
||||
return (node instanceof SymbolNode) && (node.name == 'x') ? d : node;
|
||||
});
|
||||
|
||||
assert.deepEqual(paths, ['items[0]', 'items[1]']);
|
||||
assert.equal(nodes.length, 2);
|
||||
assert.strictEqual(nodes[0], a);
|
||||
assert.strictEqual(nodes[1], b);
|
||||
|
||||
assert.notStrictEqual(e, c);
|
||||
assert.deepEqual(e.items[0], d);
|
||||
assert.deepEqual(e.items[1], b);
|
||||
});
|
||||
|
||||
it ('should throw an error when the map callback does not return a node', function () {
|
||||
var a = new SymbolNode('x');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ArrayNode([a, b]);
|
||||
|
||||
assert.throws(function () {
|
||||
c.map(function () {});
|
||||
}, /Callback function must return a Node/)
|
||||
});
|
||||
|
||||
it ('should transform an ArrayNodes parameters', function () {
|
||||
// [x, 2]
|
||||
var a = new SymbolNode('x');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ArrayNode([a, b]);
|
||||
|
||||
var d = new ConstantNode(3);
|
||||
var e = c.transform(function (node) {
|
||||
return (node instanceof SymbolNode) && (node.name == 'x') ? d : node;
|
||||
});
|
||||
|
||||
assert.notStrictEqual(e, c);
|
||||
assert.deepEqual(e.items[0], d);
|
||||
assert.deepEqual(e.items[1], b);
|
||||
});
|
||||
|
||||
it ('should transform an ArrayNode itself', function () {
|
||||
// [x, 2]
|
||||
var a = new SymbolNode('x');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ArrayNode([a, b]);
|
||||
|
||||
var d = new ConstantNode(3);
|
||||
var e = c.transform(function (node) {
|
||||
return (node instanceof ArrayNode) ? d : node;
|
||||
});
|
||||
|
||||
assert.notStrictEqual(e, c);
|
||||
assert.deepEqual(e, d);
|
||||
});
|
||||
|
||||
it ('should traverse an ArrayNode', function () {
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ArrayNode([a, b]);
|
||||
|
||||
var count = 0;
|
||||
c.traverse(function (node, path, parent) {
|
||||
count++;
|
||||
|
||||
switch(count) {
|
||||
case 1:
|
||||
assert.strictEqual(node, c);
|
||||
assert.strictEqual(path, null);
|
||||
assert.strictEqual(parent, null);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
assert.strictEqual(node, a);
|
||||
assert.strictEqual(path, 'items[0]');
|
||||
assert.strictEqual(parent, c);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
assert.strictEqual(node, b);
|
||||
assert.strictEqual(path, 'items[1]');
|
||||
assert.strictEqual(parent, c);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
assert.equal(count, 3);
|
||||
});
|
||||
|
||||
it ('should clone an ArrayNode', function () {
|
||||
// [x, 2]
|
||||
var a = new SymbolNode('x');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ArrayNode([a, b]);
|
||||
|
||||
var d = c.clone();
|
||||
assert(d instanceof ArrayNode);
|
||||
assert.deepEqual(c, d);
|
||||
assert.notStrictEqual(c, d);
|
||||
assert.strictEqual(c.items[0], d.items[0]);
|
||||
assert.strictEqual(c.items[1], d.items[1]);
|
||||
});
|
||||
|
||||
it ('test equality with other nodes', function () {
|
||||
// [x, 2]
|
||||
var a = new SymbolNode('x');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ArrayNode([a, b]);
|
||||
|
||||
assert.strictEqual(c.equals(null), false);
|
||||
assert.strictEqual(c.equals(undefined), false);
|
||||
assert.strictEqual(c.equals(new ArrayNode([new SymbolNode('x'), new ConstantNode(2)])), true);
|
||||
assert.strictEqual(c.equals(new ArrayNode([new SymbolNode('x'), new ConstantNode(2), new ConstantNode(3)])), false);
|
||||
assert.strictEqual(c.equals(new ArrayNode([new SymbolNode('x'), new ConstantNode(3)])), false);
|
||||
assert.strictEqual(c.equals(new ArrayNode([new SymbolNode('x')])), false);
|
||||
});
|
||||
|
||||
it ('should stringify an ArrayNode', function () {
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(3);
|
||||
var d = new ConstantNode(4);
|
||||
var n = new ArrayNode([a, b, c, d]);
|
||||
|
||||
assert.equal(n.toString(), '[1, 2, 3, 4]');
|
||||
});
|
||||
|
||||
it ('should stringify an ArrayNode with custom toString', function () {
|
||||
//Also checks if the custom functions get passed on to the children
|
||||
var customFunction = function (node, options) {
|
||||
if (node.type === 'ArrayNode') {
|
||||
var string = '[';
|
||||
node.items.forEach(function (item) {
|
||||
string += item.toString(options) + ', ';
|
||||
});
|
||||
|
||||
string += ']';
|
||||
return string;
|
||||
}
|
||||
else if (node.type === 'ConstantNode') {
|
||||
return 'const(' + node.value + ', ' + node.valueType + ')'
|
||||
}
|
||||
};
|
||||
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
|
||||
var n = new ArrayNode([a, b]);
|
||||
|
||||
assert.equal(n.toString({handler: customFunction}), '[const(1, number), const(2, number), ]');
|
||||
});
|
||||
|
||||
it ('should LaTeX an ArrayNode', function () {
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(3);
|
||||
var d = new ConstantNode(4);
|
||||
var v1 = new ArrayNode([a, b]);
|
||||
var v2 = new ArrayNode([c, d]);
|
||||
var n = new ArrayNode([v1, v2]);
|
||||
|
||||
assert.equal(n.toTex(), '\\begin{bmatrix}1&2\\\\3&4\\\\\\end{bmatrix}');
|
||||
});
|
||||
|
||||
it ('should LaTeX an ArrayNode with custom toTex', function () {
|
||||
//Also checks if the custom functions get passed on to the children
|
||||
var customFunction = function (node, options) {
|
||||
if (node.type === 'ArrayNode') {
|
||||
var latex = '\\left[';
|
||||
node.items.forEach(function (item) {
|
||||
latex += item.toTex(options) + ', ';
|
||||
});
|
||||
|
||||
latex += '\\right]';
|
||||
return latex;
|
||||
}
|
||||
else if (node.type === 'ConstantNode') {
|
||||
return 'const\\left(' + node.value + ', ' + node.valueType + '\\right)'
|
||||
}
|
||||
};
|
||||
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
|
||||
var n = new ArrayNode([a, b]);
|
||||
|
||||
assert.equal(n.toTex({handler: customFunction}), '\\left[const\\left(1, number\\right), const\\left(2, number\\right), \\right]');
|
||||
});
|
||||
|
||||
});
|
||||
547
nodered/rootfs/data/node_modules/mathjs/test/expression/node/AssignmentNode.test.js
generated
vendored
Normal file
547
nodered/rootfs/data/node_modules/mathjs/test/expression/node/AssignmentNode.test.js
generated
vendored
Normal file
@@ -0,0 +1,547 @@
|
||||
// test AssignmentNode
|
||||
var assert = require('assert');
|
||||
var approx = require('../../../tools/approx');
|
||||
var math = require('../../../index');
|
||||
var Node = math.expression.node.Node;
|
||||
var AccessorNode = math.expression.node.AccessorNode;
|
||||
var ConstantNode = math.expression.node.ConstantNode;
|
||||
var SymbolNode = math.expression.node.SymbolNode;
|
||||
var RangeNode = math.expression.node.RangeNode;
|
||||
var ArrayNode = math.expression.node.ArrayNode;
|
||||
var AssignmentNode = math.expression.node.AssignmentNode;
|
||||
var OperatorNode = math.expression.node.OperatorNode;
|
||||
var IndexNode = math.expression.node.IndexNode;
|
||||
|
||||
describe('AssignmentNode', function() {
|
||||
|
||||
it ('should create an AssignmentNode', function () {
|
||||
var n = new AssignmentNode(new SymbolNode('a'), new Node());
|
||||
assert(n instanceof AssignmentNode);
|
||||
assert(n instanceof Node);
|
||||
assert.equal(n.type, 'AssignmentNode');
|
||||
});
|
||||
|
||||
it ('should have isAssignmentNode', function () {
|
||||
var node = new AssignmentNode(new SymbolNode('a'), new Node());
|
||||
assert(node.isAssignmentNode);
|
||||
});
|
||||
|
||||
it ('should throw an error when calling without new operator', function () {
|
||||
assert.throws(function () {AssignmentNode(new SymbolNode('a'), new Node())}, SyntaxError);
|
||||
});
|
||||
|
||||
it ('should throw an error when creating an AssignmentNode with a reserved keyword', function () {
|
||||
assert.throws(function () {
|
||||
new AssignmentNode(new SymbolNode('end'), new Node());
|
||||
}, /Cannot assign to symbol "end"/)
|
||||
});
|
||||
|
||||
it ('should throw an error on wrong constructor arguments', function () {
|
||||
assert.throws(function () {new AssignmentNode()}, TypeError );
|
||||
assert.throws(function () {new AssignmentNode(new Node(), new Node())}, TypeError );
|
||||
assert.throws(function () {new AssignmentNode('a', new Node())}, TypeError );
|
||||
assert.throws(function () {new AssignmentNode(2, new Node())}, TypeError );
|
||||
assert.throws(function () {new AssignmentNode(new Node(), new Node(), new Node())}, TypeError );
|
||||
});
|
||||
|
||||
it ('should get the name of an AssignmentNode', function () {
|
||||
var n = new AssignmentNode(new SymbolNode('a'), new ConstantNode(1));
|
||||
assert.equal(n.name, 'a');
|
||||
|
||||
var n2 = new AccessorNode(new SymbolNode('a'), new IndexNode([new ConstantNode('b')]));
|
||||
var n3 = new AssignmentNode(n2, new ConstantNode(1));
|
||||
assert.equal(n3.name, 'b');
|
||||
|
||||
var n4 = new AssignmentNode(new SymbolNode('a'), new IndexNode([new ConstantNode('b')]), new ConstantNode(1));
|
||||
assert.equal(n4.name, 'b');
|
||||
|
||||
var n5 = new AssignmentNode(new SymbolNode('a'), new IndexNode([new ConstantNode(1)]), new ConstantNode(1));
|
||||
assert.equal(n5.name, '');
|
||||
});
|
||||
|
||||
it ('should compile an AssignmentNode without index', function () {
|
||||
var n = new AssignmentNode(new SymbolNode('b'), new ConstantNode(3));
|
||||
|
||||
var expr = n.compile();
|
||||
|
||||
var scope = {};
|
||||
assert.equal(expr.eval(scope), 3);
|
||||
assert.equal(scope.b, 3);
|
||||
});
|
||||
|
||||
it ('should compile an AssignmentNode with property index', function () {
|
||||
var object = new SymbolNode('a');
|
||||
var index = new IndexNode([new ConstantNode('b')]);
|
||||
var value = new ConstantNode(3);
|
||||
var n = new AssignmentNode(object, index, value);
|
||||
|
||||
var expr = n.compile();
|
||||
|
||||
var scope = {
|
||||
a: {}
|
||||
};
|
||||
assert.equal(expr.eval(scope), 3);
|
||||
assert.deepEqual(scope, {a: {b: 3}});
|
||||
});
|
||||
|
||||
it ('should compile an AssignmentNode with nested property index', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var object = new AccessorNode(a, new IndexNode([new ConstantNode('b')]));
|
||||
var index = new IndexNode([new ConstantNode('c')]);
|
||||
var value = new ConstantNode(3);
|
||||
var n = new AssignmentNode(object, index, value);
|
||||
|
||||
var expr = n.compile();
|
||||
|
||||
var scope = {
|
||||
a: {
|
||||
b: {}
|
||||
}
|
||||
};
|
||||
assert.equal(expr.eval(scope), 3);
|
||||
assert.deepEqual(scope, {a: {b: {c: 3}}});
|
||||
});
|
||||
|
||||
it ('should compile an AssignmentNode with matrix index', function () {
|
||||
var object = new SymbolNode('a');
|
||||
var index = new IndexNode([
|
||||
new ConstantNode(2),
|
||||
new ConstantNode(1)
|
||||
]);
|
||||
var value = new ConstantNode(5);
|
||||
var n = new AssignmentNode(object, index, value);
|
||||
var expr = n.compile();
|
||||
|
||||
var scope = {
|
||||
a: [[0, 0], [0, 0]]
|
||||
};
|
||||
assert.strictEqual(expr.eval(scope), 5);
|
||||
assert.deepEqual(scope, {
|
||||
a: [[0, 0], [5, 0]]
|
||||
});
|
||||
});
|
||||
|
||||
it ('should compile an AssignmentNode with range and context parameters', function () {
|
||||
var object = new SymbolNode('a');
|
||||
var index = new IndexNode([
|
||||
new ConstantNode(2),
|
||||
new RangeNode(
|
||||
new ConstantNode(1),
|
||||
new SymbolNode('end')
|
||||
)
|
||||
]);
|
||||
var value = new SymbolNode('b');
|
||||
var n = new AssignmentNode(object, index, value);
|
||||
var expr = n.compile();
|
||||
|
||||
var scope = {
|
||||
a: [[0, 0], [0, 0]],
|
||||
b: [5, 6]
|
||||
};
|
||||
assert.deepEqual(expr.eval(scope), [5, 6]);
|
||||
assert.deepEqual(scope, {
|
||||
a: [[0, 0], [5, 6]],
|
||||
b: [5, 6]
|
||||
});
|
||||
});
|
||||
|
||||
it ('should compile an AssignmentNode with bignumber setting', function () {
|
||||
var bigmath = math.create({number: 'BigNumber'});
|
||||
|
||||
var object = new SymbolNode('a');
|
||||
var index = new bigmath.expression.node.IndexNode([
|
||||
new bigmath.expression.node.ConstantNode(2),
|
||||
new bigmath.expression.node.ConstantNode(1)
|
||||
]);
|
||||
var value = new bigmath.expression.node.ConstantNode(5);
|
||||
var n = new bigmath.expression.node.AssignmentNode(object, index, value);
|
||||
var expr = n.compile();
|
||||
|
||||
var scope = {
|
||||
a: [[0, 0], [0, 0]]
|
||||
};
|
||||
assert.deepEqual(expr.eval(scope), bigmath.bignumber(5));
|
||||
assert.deepEqual(scope, {
|
||||
a: [[0, 0], [bigmath.bignumber(5), 0]]
|
||||
});
|
||||
});
|
||||
|
||||
it ('should throw an error when applying an index onto a scalar', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var index = new IndexNode([new ConstantNode(4)]);
|
||||
var value = new ConstantNode(2);
|
||||
var n = new AssignmentNode(a, index, value);
|
||||
var expr = n.compile();
|
||||
|
||||
var scope = {
|
||||
a: 42
|
||||
};
|
||||
assert.throws(function () { expr.eval(scope) }, /Cannot apply index: unsupported type of object/);
|
||||
});
|
||||
|
||||
it ('should filter an AssignmentNode', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(1);
|
||||
var i = new IndexNode([b, c]);
|
||||
var v = new ConstantNode(2);
|
||||
var n = new AssignmentNode(a, i, v);
|
||||
|
||||
assert.deepEqual(n.filter(function (node) {return node.isAssignmentNode}), [n]);
|
||||
assert.deepEqual(n.filter(function (node) {return node.isSymbolNode}), [a]);
|
||||
assert.deepEqual(n.filter(function (node) {return node.isConstantNode}), [b, c, v]);
|
||||
assert.deepEqual(n.filter(function (node) {return node.value === '1'}), [c]);
|
||||
assert.deepEqual(n.filter(function (node) {return node.value === '2'}), [b, v]);
|
||||
assert.deepEqual(n.filter(function (node) {return node.name === 'q'}), []);
|
||||
});
|
||||
|
||||
it ('should filter an AssignmentNode without index', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var v = new ConstantNode(2);
|
||||
var n = new AssignmentNode(a, v);
|
||||
|
||||
assert.deepEqual(n.filter(function (node) {return node.isAssignmentNode}), [n]);
|
||||
assert.deepEqual(n.filter(function (node) {return node.isSymbolNode}), [a]);
|
||||
assert.deepEqual(n.filter(function (node) {return node.isConstantNode}), [v]);
|
||||
assert.deepEqual(n.filter(function (node) {return node.value === '2'}), [v]);
|
||||
assert.deepEqual(n.filter(function (node) {return node.name === 'q'}), []);
|
||||
});
|
||||
|
||||
it ('should run forEach on an AssignmentNode', function () {
|
||||
// A[1, x] = 3
|
||||
var a = new SymbolNode('A');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new SymbolNode('x');
|
||||
var i = new IndexNode([b, c]);
|
||||
var v = new ConstantNode(3);
|
||||
var n = new AssignmentNode(a, i, v);
|
||||
|
||||
var nodes = [];
|
||||
var paths = [];
|
||||
n.forEach(function (node, path, parent) {
|
||||
nodes.push(node);
|
||||
paths.push(path);
|
||||
assert.strictEqual(parent, n);
|
||||
});
|
||||
|
||||
assert.equal(nodes.length, 3);
|
||||
assert.strictEqual(nodes[0], a);
|
||||
assert.strictEqual(nodes[1], i);
|
||||
assert.strictEqual(nodes[2], v);
|
||||
assert.deepEqual(paths, ['object', 'index', 'value']);
|
||||
});
|
||||
|
||||
it ('should run forEach on an AssignmentNode without index', function () {
|
||||
// A[1, x] = 3
|
||||
var a = new SymbolNode('A');
|
||||
var v = new ConstantNode(3);
|
||||
var n = new AssignmentNode(a, v);
|
||||
|
||||
var nodes = [];
|
||||
var paths = [];
|
||||
n.forEach(function (node, path, parent) {
|
||||
nodes.push(node);
|
||||
paths.push(path);
|
||||
assert.strictEqual(parent, n);
|
||||
});
|
||||
|
||||
assert.equal(nodes.length, 2);
|
||||
assert.strictEqual(nodes[0], a);
|
||||
assert.strictEqual(nodes[1], v);
|
||||
assert.deepEqual(paths, ['object', 'value']);
|
||||
});
|
||||
|
||||
it ('should map an AssignmentNode', function () {
|
||||
// A[1, x] = 3
|
||||
var a = new SymbolNode('A');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new SymbolNode('x');
|
||||
var i = new IndexNode([b, c]);
|
||||
var v = new ConstantNode(3);
|
||||
var n = new AssignmentNode(a, i, v);
|
||||
|
||||
var nodes = [];
|
||||
var paths = [];
|
||||
var e = new ConstantNode(4);
|
||||
var f = n.map(function (node, path, parent) {
|
||||
nodes.push(node);
|
||||
paths.push(path);
|
||||
assert.strictEqual(parent, n);
|
||||
|
||||
return node instanceof SymbolNode && node.name == 'x' ? e : node;
|
||||
});
|
||||
|
||||
assert.equal(nodes.length, 3);
|
||||
assert.strictEqual(nodes[0], a);
|
||||
assert.strictEqual(nodes[1], i);
|
||||
assert.strictEqual(nodes[2], v);
|
||||
assert.deepEqual(paths, ['object', 'index', 'value']);
|
||||
|
||||
assert.notStrictEqual(f, n);
|
||||
assert.deepEqual(f.object, a);
|
||||
assert.deepEqual(f.index.dimensions[0], b);
|
||||
assert.deepEqual(f.index.dimensions[1], c); // not replaced, is nested
|
||||
assert.deepEqual(f.value, v);
|
||||
});
|
||||
|
||||
it ('should map an AssignmentNode without index', function () {
|
||||
// a = x + 2
|
||||
var a = new SymbolNode('a');
|
||||
var x = new SymbolNode('x');
|
||||
var d = new AssignmentNode(a, x);
|
||||
|
||||
var e = new ConstantNode(3);
|
||||
var nodes = [];
|
||||
var paths = [];
|
||||
var f = d.map(function (node, path, parent) {
|
||||
nodes.push(node);
|
||||
paths.push(path);
|
||||
assert.strictEqual(parent, d);
|
||||
return node instanceof SymbolNode && node.name == 'x' ? e : node;
|
||||
});
|
||||
|
||||
assert.equal(nodes.length, 2);
|
||||
assert.strictEqual(nodes[0], a);
|
||||
assert.strictEqual(nodes[1], x);
|
||||
assert.deepEqual(paths, ['object', 'value']);
|
||||
|
||||
assert.notStrictEqual(f, d);
|
||||
assert.strictEqual(d.value, x);
|
||||
assert.strictEqual(f.value, e);
|
||||
});
|
||||
|
||||
it ('should throw an error when the map callback does not return a node', function () {
|
||||
// A[1, x] = 3
|
||||
var a = new SymbolNode('A');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new SymbolNode('x');
|
||||
var i = new IndexNode([b, c]);
|
||||
var v = new ConstantNode(3);
|
||||
var n = new AssignmentNode(a, i, v);
|
||||
|
||||
assert.throws(function () {
|
||||
n.map(function () {});
|
||||
}, /Callback function must return a Node/)
|
||||
});
|
||||
|
||||
it ('should transform an AssignmentNodes (nested) parameters', function () {
|
||||
// a = x + 2
|
||||
var object = new SymbolNode('a');
|
||||
var x = new SymbolNode('x');
|
||||
var index = new IndexNode([x]);
|
||||
var b = new ConstantNode(2);
|
||||
var value = new OperatorNode('+', 'add', [x, b]);
|
||||
var d = new AssignmentNode(object, index, value);
|
||||
|
||||
var e = new ConstantNode(3);
|
||||
var f = d.transform(function (node) {
|
||||
return node.isSymbolNode && node.name == 'x' ? e : node;
|
||||
});
|
||||
|
||||
assert.notStrictEqual(f, d);
|
||||
assert.deepEqual(f.index.dimensions[0], e);
|
||||
assert.deepEqual(f.value.args[0], e);
|
||||
assert.deepEqual(f.value.args[1], b);
|
||||
});
|
||||
|
||||
it ('should transform an AssignmentNode itself', function () {
|
||||
// a = x + 2
|
||||
var object = new SymbolNode('a');
|
||||
var x = new SymbolNode('x');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new OperatorNode('+', 'add', [x, b]);
|
||||
var d = new AssignmentNode(object, c);
|
||||
|
||||
var e = new ConstantNode(5);
|
||||
var f = d.transform(function (node) {
|
||||
return node instanceof AssignmentNode ? e : node;
|
||||
});
|
||||
|
||||
assert.notStrictEqual(f, d);
|
||||
assert.deepEqual(f, e);
|
||||
});
|
||||
|
||||
it ('should traverse an AssignmentNode', function () {
|
||||
var object = new SymbolNode('a');
|
||||
var i = new IndexNode([]);
|
||||
var value = new ConstantNode(2);
|
||||
var a = new AssignmentNode(object, i, value);
|
||||
|
||||
var count = 0;
|
||||
a.traverse(function (node, index, parent) {
|
||||
count++;
|
||||
|
||||
switch(count) {
|
||||
case 1:
|
||||
assert.strictEqual(node, a);
|
||||
assert.strictEqual(index, null);
|
||||
assert.strictEqual(parent, null);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
assert.strictEqual(node, object);
|
||||
assert.strictEqual(index, 'object');
|
||||
assert.strictEqual(parent, a);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
assert.strictEqual(node, i);
|
||||
assert.strictEqual(index, 'index');
|
||||
assert.strictEqual(parent, a);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
assert.strictEqual(node, value);
|
||||
assert.strictEqual(index, 'value');
|
||||
assert.strictEqual(parent, a);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
assert.equal(count, 4);
|
||||
});
|
||||
|
||||
it ('should clone an AssignmentNode without index', function () {
|
||||
var object = new SymbolNode('a');
|
||||
var value = new ConstantNode(2);
|
||||
var a = new AssignmentNode(object, value);
|
||||
|
||||
var b = a.clone();
|
||||
assert(b instanceof AssignmentNode);
|
||||
assert.deepEqual(b, a);
|
||||
assert.notStrictEqual(b, a);
|
||||
assert.strictEqual(b.object, a.object);
|
||||
assert.strictEqual(b.index, a.index);
|
||||
assert.strictEqual(b.value, a.value);
|
||||
});
|
||||
|
||||
it ('should clone an AssignmentNode', function () {
|
||||
// A[1, x] = 3
|
||||
var a = new SymbolNode('A');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new SymbolNode('x');
|
||||
var i = new IndexNode([b, c]);
|
||||
var v = new ConstantNode(3);
|
||||
var d = new AssignmentNode(a, i, v);
|
||||
|
||||
var e = d.clone();
|
||||
|
||||
assert(e instanceof AssignmentNode);
|
||||
assert.deepEqual(e, d);
|
||||
assert.notStrictEqual(e, d);
|
||||
assert.strictEqual(e.object, d.object);
|
||||
assert.strictEqual(e.index, d.index);
|
||||
assert.strictEqual(e.value, d.value);
|
||||
});
|
||||
|
||||
it ('test equality another Node', function () {
|
||||
var a = new AssignmentNode(
|
||||
new SymbolNode('A'),
|
||||
new IndexNode([new ConstantNode(2), new SymbolNode('x')]),
|
||||
new ConstantNode(3));
|
||||
var b = new AssignmentNode(
|
||||
new SymbolNode('A'),
|
||||
new IndexNode([new ConstantNode(2), new SymbolNode('x')]),
|
||||
new ConstantNode(3));
|
||||
var c = new AssignmentNode(
|
||||
new SymbolNode('B'),
|
||||
new IndexNode([new ConstantNode(2), new SymbolNode('x')]),
|
||||
new ConstantNode(3));
|
||||
var d = new AssignmentNode(
|
||||
new SymbolNode('A'),
|
||||
new IndexNode([new ConstantNode(2)]),
|
||||
new ConstantNode(3));
|
||||
var e = new AssignmentNode(
|
||||
new SymbolNode('A'),
|
||||
new IndexNode([new ConstantNode(2), new SymbolNode('x')]),
|
||||
new ConstantNode(4));
|
||||
|
||||
assert.strictEqual(a.equals(null), false);
|
||||
assert.strictEqual(a.equals(undefined), false);
|
||||
assert.strictEqual(a.equals(b), true);
|
||||
assert.strictEqual(a.equals(c), false);
|
||||
assert.strictEqual(a.equals(d), false);
|
||||
assert.strictEqual(a.equals(e), false);
|
||||
});
|
||||
|
||||
it ('should respect the \'all\' parenthesis option', function () {
|
||||
var object = new SymbolNode('a');
|
||||
var value = new ConstantNode(1);
|
||||
var n = new AssignmentNode(object, value);
|
||||
|
||||
assert.equal(n.toString({parenthesis: 'all'}), 'a = (1)');
|
||||
assert.equal(n.toTex({parenthesis: 'all'}), ' a:=\\left(1\\right)');
|
||||
});
|
||||
|
||||
it ('should stringify a AssignmentNode', function () {
|
||||
var object = new SymbolNode('b');
|
||||
var value = new ConstantNode(3);
|
||||
var n = new AssignmentNode(object, value);
|
||||
|
||||
assert.equal(n.toString(), 'b = 3');
|
||||
});
|
||||
|
||||
it ('should stringify an AssignmentNode containing an AssignmentNode', function () {
|
||||
var value = new ConstantNode(2);
|
||||
var a = new AssignmentNode(new SymbolNode('a'), value);
|
||||
var n = new AssignmentNode(new SymbolNode('b'), a);
|
||||
|
||||
assert.equal(n.toString(), 'b = (a = 2)');
|
||||
});
|
||||
|
||||
it ('should stringify an AssignmentNode with custom toString', function () {
|
||||
//Also checks if custom funcions get passed to the children
|
||||
var customFunction = function (node, options) {
|
||||
if (node.type === 'AssignmentNode') {
|
||||
return node.object.toString(options) +
|
||||
(node.index ? node.index.toString(options) : '') +
|
||||
' equals ' + node.value.toString(options);
|
||||
}
|
||||
else if (node.type === 'ConstantNode') {
|
||||
return 'const(' + node.value + ', ' + node.valueType + ')'
|
||||
}
|
||||
};
|
||||
|
||||
var object = new SymbolNode('a');
|
||||
var value = new ConstantNode(1);
|
||||
var n = new AssignmentNode(object, value);
|
||||
|
||||
assert.equal(n.toString({handler: customFunction}), 'a equals const(1, number)');
|
||||
});
|
||||
|
||||
it ('should LaTeX a AssignmentNode', function () {
|
||||
var value = new ConstantNode(2);
|
||||
var a = new AssignmentNode(new SymbolNode('a'), value);
|
||||
|
||||
assert.equal(a.toTex(), ' a:=2');
|
||||
});
|
||||
|
||||
it ('should LaTeX an AssignmentNode containing an AssignmentNode', function () {
|
||||
var value = new ConstantNode(2);
|
||||
var a = new AssignmentNode(new SymbolNode('a'), value);
|
||||
var q = new AssignmentNode(new SymbolNode('q'), a);
|
||||
|
||||
assert.equal(q.toTex(), ' q:=\\left( a:=2\\right)');
|
||||
});
|
||||
|
||||
it ('should LaTeX an AssignmentNode with custom toTex', function () {
|
||||
//Also checks if custom funcions get passed to the children
|
||||
var customFunction = function (node, options) {
|
||||
if (node.isAssignmentNode) {
|
||||
return node.object.toTex(options) +
|
||||
(node.index ? node.index.toTex(options) : '') +
|
||||
'\\mbox{equals}' + node.value.toTex(options);
|
||||
}
|
||||
else if (node.type === 'ConstantNode') {
|
||||
return 'const\\left(' + node.value + ', ' + node.valueType + '\\right)'
|
||||
}
|
||||
};
|
||||
|
||||
var object = new SymbolNode('a');
|
||||
var value = new ConstantNode(1);
|
||||
var n = new AssignmentNode(object, value);
|
||||
|
||||
assert.equal(n.toTex({handler: customFunction}), ' a\\mbox{equals}const\\left(1, number\\right)');
|
||||
});
|
||||
|
||||
});
|
||||
330
nodered/rootfs/data/node_modules/mathjs/test/expression/node/BlockNode.test.js
generated
vendored
Normal file
330
nodered/rootfs/data/node_modules/mathjs/test/expression/node/BlockNode.test.js
generated
vendored
Normal file
@@ -0,0 +1,330 @@
|
||||
// test BlockNode
|
||||
var assert = require('assert');
|
||||
var approx = require('../../../tools/approx');
|
||||
var math = require('../../../index');
|
||||
var Node = math.expression.node.Node;
|
||||
var ConstantNode = math.expression.node.ConstantNode;
|
||||
var SymbolNode = math.expression.node.SymbolNode;
|
||||
var RangeNode = math.expression.node.RangeNode;
|
||||
var AssignmentNode = math.expression.node.AssignmentNode;
|
||||
var OperatorNode = math.expression.node.OperatorNode;
|
||||
var BlockNode = math.expression.node.BlockNode;
|
||||
var ResultSet = math.type.ResultSet;
|
||||
|
||||
describe('BlockNode', function() {
|
||||
|
||||
it ('should create a BlockNode', function () {
|
||||
var n = new BlockNode([]);
|
||||
assert(n instanceof BlockNode);
|
||||
assert(n instanceof Node);
|
||||
assert.equal(n.type, 'BlockNode');
|
||||
});
|
||||
|
||||
it ('should have isBlockNode', function () {
|
||||
var node = new BlockNode([]);
|
||||
assert(node.isBlockNode);
|
||||
});
|
||||
|
||||
it ('should throw an error when calling without new operator', function () {
|
||||
assert.throws(function () {BlockNode()}, SyntaxError);
|
||||
});
|
||||
|
||||
it ('should throw an error when adding invalid blocks', function () {
|
||||
assert.throws(function () {new BlockNode()}, /Array expected/);
|
||||
assert.throws(function () {new BlockNode([2])}, /Property "node" must be a Node/);
|
||||
assert.throws(function () {new BlockNode([{node: 2, visible:true}])}, /Property "node" must be a Node/);
|
||||
assert.throws(function () {new BlockNode([{node: new Node(), visible: 2}])}, /Property "visible" must be a boolean/);
|
||||
});
|
||||
|
||||
it ('should compile and evaluate a BlockNode', function () {
|
||||
var n = new BlockNode([
|
||||
{
|
||||
node: new ConstantNode(5),
|
||||
visible: true
|
||||
},
|
||||
{
|
||||
node: new AssignmentNode(new SymbolNode('foo'), new ConstantNode(3)),
|
||||
visible: false
|
||||
},
|
||||
{
|
||||
node: new SymbolNode('foo'),
|
||||
visible: true
|
||||
}
|
||||
]);
|
||||
|
||||
var scope = {};
|
||||
assert.deepEqual(n.compile().eval(scope), new ResultSet([5, 3]));
|
||||
assert.deepEqual(scope, {foo: 3});
|
||||
});
|
||||
|
||||
it ('expressions should be visible by default', function () {
|
||||
var n = new BlockNode([
|
||||
{node: new ConstantNode(5)}
|
||||
]);
|
||||
|
||||
assert.deepEqual(n.compile().eval(), new ResultSet([5]));
|
||||
});
|
||||
|
||||
it ('should filter a BlockNode', function () {
|
||||
var a = new ConstantNode(5);
|
||||
var b2 = new ConstantNode(3);
|
||||
var foo = new SymbolNode('foo');
|
||||
var b = new AssignmentNode(foo, b2);
|
||||
var c = new SymbolNode('foo');
|
||||
var d = new BlockNode([
|
||||
{node: a, visible: true},
|
||||
{node: b, visible: false},
|
||||
{node: c, visible: true}
|
||||
]);
|
||||
|
||||
assert.deepEqual(d.filter(function (node) {return node instanceof BlockNode}), [d]);
|
||||
assert.deepEqual(d.filter(function (node) {return node instanceof SymbolNode}), [foo, c]);
|
||||
assert.deepEqual(d.filter(function (node) {return node instanceof RangeNode}), []);
|
||||
assert.deepEqual(d.filter(function (node) {return node instanceof ConstantNode}), [a, b2]);
|
||||
assert.deepEqual(d.filter(function (node) {return node instanceof ConstantNode && node.value == '3'}), [b2]);
|
||||
});
|
||||
|
||||
it ('should run forEach on a BlockNode', function () {
|
||||
// [x, 2]
|
||||
var x = new SymbolNode('x');
|
||||
var two = new ConstantNode(2);
|
||||
var c = new OperatorNode('+', 'add', [two, x]);
|
||||
var a = new BlockNode([
|
||||
{node: x},
|
||||
{node: c}
|
||||
]);
|
||||
|
||||
var nodes = [];
|
||||
var paths = [];
|
||||
a.forEach(function (node, path, parent) {
|
||||
nodes.push(node);
|
||||
paths.push(path);
|
||||
assert.strictEqual(parent, a);
|
||||
});
|
||||
|
||||
assert.equal(nodes.length, 2);
|
||||
assert.strictEqual(nodes[0], x);
|
||||
assert.strictEqual(nodes[1], c);
|
||||
assert.deepEqual(paths, ['blocks[0].node', 'blocks[1].node']);
|
||||
});
|
||||
|
||||
it ('should map a BlockNode', function () {
|
||||
// [x, 2]
|
||||
var x = new SymbolNode('x');
|
||||
var two = new ConstantNode(2);
|
||||
var c = new OperatorNode('+', 'add', [two, x]);
|
||||
var a = new BlockNode([
|
||||
{node: x},
|
||||
{node: c}
|
||||
]);
|
||||
|
||||
var nodes = [];
|
||||
var paths = [];
|
||||
var d = new ConstantNode(3);
|
||||
var e = a.map(function (node, path, parent) {
|
||||
nodes.push(node);
|
||||
paths.push(path);
|
||||
assert.strictEqual(parent, a);
|
||||
return node instanceof SymbolNode && node.name == 'x' ? d : node;
|
||||
});
|
||||
|
||||
assert.equal(nodes.length, 2);
|
||||
assert.strictEqual(nodes[0], x);
|
||||
assert.strictEqual(nodes[1], c);
|
||||
assert.deepEqual(paths, ['blocks[0].node', 'blocks[1].node']);
|
||||
|
||||
assert.notStrictEqual(e, a);
|
||||
assert.strictEqual(e.blocks[0].node, d);
|
||||
assert.strictEqual(e.blocks[1].node, c);
|
||||
|
||||
// should not touch nested nodes
|
||||
assert.strictEqual(e.blocks[1].node.args[0], two);
|
||||
assert.strictEqual(e.blocks[1].node.args[1], x);
|
||||
});
|
||||
|
||||
it ('should throw an error when the map callback does not return a node', function () {
|
||||
var x = new SymbolNode('x');
|
||||
var two = new ConstantNode(2);
|
||||
var c = new OperatorNode('+', 'add', [two, x]);
|
||||
var a = new BlockNode([
|
||||
{node: x},
|
||||
{node: c}
|
||||
]);
|
||||
|
||||
assert.throws(function () {
|
||||
a.map(function () {});
|
||||
}, /Callback function must return a Node/)
|
||||
});
|
||||
|
||||
it ('should transform a BlockNodes parameters', function () {
|
||||
// [x, 2]
|
||||
var b = new SymbolNode('x');
|
||||
var c = new ConstantNode(2);
|
||||
var a = new BlockNode([
|
||||
{node: b},
|
||||
{node: c}
|
||||
]);
|
||||
|
||||
var d = new ConstantNode(3);
|
||||
var e = a.transform(function (node) {
|
||||
return node instanceof SymbolNode && node.name == 'x' ? d : node;
|
||||
});
|
||||
|
||||
assert.notStrictEqual(e, a);
|
||||
assert.deepEqual(e.blocks[0].node, d);
|
||||
assert.deepEqual(e.blocks[1].node, c);
|
||||
});
|
||||
|
||||
it ('should transform a BlockNode itself', function () {
|
||||
// [x, 2]
|
||||
var a = new BlockNode([]);
|
||||
|
||||
var d = new ConstantNode(3);
|
||||
var e = a.transform(function (node) {
|
||||
return node instanceof BlockNode ? d : node;
|
||||
});
|
||||
|
||||
assert.notStrictEqual(e, a);
|
||||
assert.deepEqual(e, d);
|
||||
});
|
||||
|
||||
it ('should traverse a BlockNode', function () {
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
var c = new BlockNode([
|
||||
{node: a, visible: true},
|
||||
{node: b, visible: true}
|
||||
]);
|
||||
|
||||
var count = 0;
|
||||
c.traverse(function (node, index, parent) {
|
||||
count++;
|
||||
|
||||
switch(count) {
|
||||
case 1:
|
||||
assert.strictEqual(node, c);
|
||||
assert.strictEqual(index, null);
|
||||
assert.strictEqual(parent, null);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
assert.strictEqual(node, a);
|
||||
assert.strictEqual(index, 'blocks[0].node');
|
||||
assert.strictEqual(parent, c);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
assert.strictEqual(node, b);
|
||||
assert.strictEqual(index, 'blocks[1].node');
|
||||
assert.strictEqual(parent, c);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
assert.equal(count, 3);
|
||||
});
|
||||
|
||||
it ('should clone a BlockNode', function () {
|
||||
// [x, 2]
|
||||
var b = new SymbolNode('x');
|
||||
var c = new ConstantNode(2);
|
||||
var a = new BlockNode([
|
||||
{node: b},
|
||||
{node: c}
|
||||
]);
|
||||
|
||||
var d = a.clone();
|
||||
assert(d instanceof BlockNode);
|
||||
assert.deepEqual(a, d);
|
||||
assert.notStrictEqual(a, d);
|
||||
assert.notStrictEqual(a.blocks, d.blocks);
|
||||
assert.notStrictEqual(a.blocks[0], d.blocks[0]);
|
||||
assert.notStrictEqual(a.blocks[1], d.blocks[1]);
|
||||
assert.strictEqual(a.blocks[0].node, d.blocks[0].node);
|
||||
assert.strictEqual(a.blocks[1].node, d.blocks[1].node);
|
||||
});
|
||||
|
||||
it ('test equality another Node', function () {
|
||||
var a = new BlockNode([ {node: new SymbolNode('x')}, {node: new ConstantNode(2)} ]);
|
||||
var b = new BlockNode([ {node: new SymbolNode('x')}, {node: new ConstantNode(2)} ]);
|
||||
var c = new BlockNode([ {node: new SymbolNode('x')}, {node: new ConstantNode(4)} ]);
|
||||
var d = new BlockNode([ {node: new SymbolNode('x')}, {node: new ConstantNode(2), visible: false} ]);
|
||||
var e = new BlockNode([ {node: new SymbolNode('x')}, {node: new ConstantNode(2)}, {node: new ConstantNode(5)} ]);
|
||||
|
||||
assert.strictEqual(a.equals(null), false);
|
||||
assert.strictEqual(a.equals(undefined), false);
|
||||
assert.strictEqual(a.equals(b), true);
|
||||
assert.strictEqual(a.equals(c), false);
|
||||
assert.strictEqual(a.equals(d), false);
|
||||
assert.strictEqual(a.equals(e), false);
|
||||
});
|
||||
|
||||
it ('should stringify a BlockNode', function () {
|
||||
var n = new BlockNode([
|
||||
{node: new ConstantNode(5), visible:true},
|
||||
{node: new AssignmentNode(new SymbolNode('foo'), new ConstantNode(3)), visible:false},
|
||||
{node: new SymbolNode('foo'), visible:true}
|
||||
]);
|
||||
|
||||
assert.equal(n.toString(), '5\nfoo = 3;\nfoo');
|
||||
});
|
||||
|
||||
it ('should stringify a BlockNode with custom toString', function () {
|
||||
//Also checks if the custom functions get passed on to the children
|
||||
var customFunction = function (node, options) {
|
||||
if (node.type === 'BlockNode') {
|
||||
var string = '';
|
||||
node.blocks.forEach(function (block) {
|
||||
string += block.node.toString(options) + '; ';
|
||||
});
|
||||
|
||||
return string;
|
||||
}
|
||||
else if (node.type === 'ConstantNode') {
|
||||
return 'const(' + node.value + ', ' + node.valueType + ')'
|
||||
}
|
||||
};
|
||||
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
|
||||
var n = new BlockNode([{node: a}, {node: b}]);
|
||||
|
||||
assert.equal(n.toString({handler: customFunction}), 'const(1, number); const(2, number); ');
|
||||
});
|
||||
|
||||
it ('should LaTeX a BlockNode', function () {
|
||||
var n = new BlockNode([
|
||||
{node: new ConstantNode(5), visible:true},
|
||||
{node: new AssignmentNode(new SymbolNode('foo'), new ConstantNode(3)), visible:false},
|
||||
{node: new SymbolNode('foo'), visible:true}
|
||||
]);
|
||||
|
||||
assert.equal(n.toTex(), '5\\;\\;\n foo:=3;\\;\\;\n foo');
|
||||
});
|
||||
|
||||
it ('should LaTeX a BlockNode with custom toTex', function () {
|
||||
//Also checks if the custom functions get passed on to the children
|
||||
var customFunction = function (node, options) {
|
||||
if (node.type === 'BlockNode') {
|
||||
var latex = '';
|
||||
node.blocks.forEach(function (block) {
|
||||
latex += block.node.toTex(options) + '; ';
|
||||
});
|
||||
|
||||
return latex;
|
||||
}
|
||||
else if (node.type === 'ConstantNode') {
|
||||
return 'const\\left(' + node.value + ', ' + node.valueType + '\\right)'
|
||||
}
|
||||
};
|
||||
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
|
||||
var n = new BlockNode([{node: a}, {node: b}]);
|
||||
|
||||
assert.equal(n.toTex({handler: customFunction}), 'const\\left(1, number\\right); const\\left(2, number\\right); ');
|
||||
});
|
||||
|
||||
});
|
||||
333
nodered/rootfs/data/node_modules/mathjs/test/expression/node/ConditionalNode.test.js
generated
vendored
Normal file
333
nodered/rootfs/data/node_modules/mathjs/test/expression/node/ConditionalNode.test.js
generated
vendored
Normal file
@@ -0,0 +1,333 @@
|
||||
// test ConditionalNode
|
||||
var assert = require('assert');
|
||||
var approx = require('../../../tools/approx');
|
||||
var math = require('../../../index');
|
||||
var Node = math.expression.node.Node;
|
||||
var ConstantNode = math.expression.node.ConstantNode;
|
||||
var SymbolNode = math.expression.node.SymbolNode;
|
||||
var AssignmentNode = math.expression.node.AssignmentNode;
|
||||
var ConditionalNode = math.expression.node.ConditionalNode;
|
||||
|
||||
describe('ConditionalNode', function() {
|
||||
var condition = new ConstantNode(true);
|
||||
var zero = new ConstantNode(0);
|
||||
var one = new ConstantNode(1);
|
||||
var two = new ConstantNode(2);
|
||||
var three = new ConstantNode(3);
|
||||
var a = new AssignmentNode(new SymbolNode('a'), two);
|
||||
var b = new AssignmentNode(new SymbolNode('b'), three);
|
||||
|
||||
it ('should create a ConditionalNode', function () {
|
||||
var n = new ConditionalNode(condition, a, b);
|
||||
assert(n instanceof ConditionalNode);
|
||||
assert(n instanceof Node);
|
||||
assert.equal(n.type, 'ConditionalNode');
|
||||
});
|
||||
|
||||
it ('should have isConditionalNode', function () {
|
||||
var node = new ConditionalNode(condition, a, b);
|
||||
assert(node.isConditionalNode);
|
||||
});
|
||||
|
||||
it ('should throw an error when calling without new operator', function () {
|
||||
assert.throws(function () {ConditionalNode()}, SyntaxError);
|
||||
});
|
||||
|
||||
it ('should throw an error when creating without arguments', function () {
|
||||
assert.throws(function () {new ConditionalNode()}, TypeError);
|
||||
assert.throws(function () {new ConditionalNode(condition)}, TypeError);
|
||||
assert.throws(function () {new ConditionalNode(condition, a)}, TypeError);
|
||||
assert.throws(function () {new ConditionalNode(condition, null, b)}, TypeError);
|
||||
});
|
||||
|
||||
it ('should lazy evaluate a ConditionalNode', function () {
|
||||
var n = new ConditionalNode(condition, a, b);
|
||||
var expr = n.compile();
|
||||
var scope = {};
|
||||
assert.equal(expr.eval(scope), 2);
|
||||
assert.deepEqual(scope, {a: 2});
|
||||
});
|
||||
|
||||
describe('evaluate', function () {
|
||||
var condition = new ConditionalNode(new SymbolNode('a'), one, zero);
|
||||
|
||||
it('should evaluate boolean conditions', function() {
|
||||
assert.equal(condition.compile().eval({a: true}), 1);
|
||||
assert.equal(condition.compile().eval({a: false}), 0);
|
||||
});
|
||||
|
||||
it('should evaluate number conditions', function() {
|
||||
assert.equal(condition.compile().eval({a: 1}), 1);
|
||||
assert.equal(condition.compile().eval({a: 4}), 1);
|
||||
assert.equal(condition.compile().eval({a: -1}), 1);
|
||||
assert.equal(condition.compile().eval({a: 0}), 0);
|
||||
});
|
||||
|
||||
it('should evaluate bignumber conditions', function() {
|
||||
assert.equal(condition.compile().eval({a: math.bignumber(1)}), 1);
|
||||
assert.equal(condition.compile().eval({a: math.bignumber(4)}), 1);
|
||||
assert.equal(condition.compile().eval({a: math.bignumber(-1)}), 1);
|
||||
assert.equal(condition.compile().eval({a: math.bignumber(0)}), 0);
|
||||
});
|
||||
|
||||
it('should evaluate complex number conditions', function() {
|
||||
assert.equal(condition.compile().eval({a: math.complex(2, 3)}), 1);
|
||||
assert.equal(condition.compile().eval({a: math.complex(2, 0)}), 1);
|
||||
assert.equal(condition.compile().eval({a: math.complex(0, 3)}), 1);
|
||||
assert.equal(condition.compile().eval({a: math.complex(0, 0)}), 0);
|
||||
});
|
||||
|
||||
it('should evaluate string conditions', function() {
|
||||
assert.equal(condition.compile().eval({a: 'hello'}), 1);
|
||||
assert.equal(condition.compile().eval({a: ''}), 0);
|
||||
});
|
||||
|
||||
it('should evaluate unit conditions', function() {
|
||||
assert.equal(condition.compile().eval({a: math.unit('5cm')}), 1);
|
||||
assert.equal(condition.compile().eval({a: math.unit('0 inch')}), 0);
|
||||
assert.equal(condition.compile().eval({a: math.unit('meter')}), 0);
|
||||
});
|
||||
|
||||
it('should evaluate null conditions', function() {
|
||||
assert.equal(condition.compile().eval({a: null}), 0);
|
||||
});
|
||||
|
||||
it('should evaluate undefined conditions', function() {
|
||||
assert.equal(condition.compile().eval({a: undefined}), 0);
|
||||
});
|
||||
|
||||
it('should throw an error in case of unsupported type of conditions', function() {
|
||||
assert.throws(function () {condition.compile().eval({a: {}})});
|
||||
assert.throws(function () {condition.compile().eval({a: []})});
|
||||
assert.throws(function () {condition.compile().eval({a: math.matrix()})});
|
||||
});
|
||||
});
|
||||
|
||||
it ('should filter a ConditionalNode', function () {
|
||||
var n = new ConditionalNode(condition, a, b);
|
||||
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof ConditionalNode}), [n]);
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof ConstantNode}), [condition, two, three]);
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof ConstantNode && node.value == '2'}), [two]);
|
||||
});
|
||||
|
||||
it ('should run forEach on a ConditionalNode', function () {
|
||||
var condition = new ConstantNode(1);
|
||||
var a = new ConstantNode(2);
|
||||
var b = new ConstantNode(3);
|
||||
var n = new ConditionalNode(condition, a, b);
|
||||
|
||||
var nodes = [];
|
||||
var paths = [];
|
||||
n.forEach(function (node, path, parent) {
|
||||
nodes.push(node);
|
||||
paths.push(path);
|
||||
assert.strictEqual(parent, n);
|
||||
});
|
||||
|
||||
assert.equal(nodes.length, 3);
|
||||
assert.strictEqual(nodes[0], condition);
|
||||
assert.strictEqual(nodes[1], a);
|
||||
assert.strictEqual(nodes[2], b);
|
||||
assert.deepEqual(paths, ['condition', 'trueExpr', 'falseExpr']);
|
||||
});
|
||||
|
||||
it ('should map a ConditionalNode', function () {
|
||||
var condition = new ConstantNode(1);
|
||||
var a = new ConstantNode(2);
|
||||
var b = new ConstantNode(3);
|
||||
var n = new ConditionalNode(condition, a, b);
|
||||
|
||||
var nodes = [];
|
||||
var paths = [];
|
||||
var e = new ConstantNode(4);
|
||||
var f = n.map(function (node, path, parent) {
|
||||
nodes.push(node);
|
||||
paths.push(path);
|
||||
assert.strictEqual(parent, n);
|
||||
|
||||
return node instanceof ConstantNode && node.value == '1' ? e : node;
|
||||
});
|
||||
|
||||
assert.equal(nodes.length, 3);
|
||||
assert.strictEqual(nodes[0], condition);
|
||||
assert.strictEqual(nodes[1], a);
|
||||
assert.strictEqual(nodes[2], b);
|
||||
assert.deepEqual(paths, ['condition', 'trueExpr', 'falseExpr']);
|
||||
|
||||
assert.notStrictEqual(f, n);
|
||||
assert.strictEqual(f.condition, e);
|
||||
assert.strictEqual(f.trueExpr, a);
|
||||
assert.strictEqual(f.falseExpr, b);
|
||||
});
|
||||
|
||||
it ('should throw an error when the map callback does not return a node', function () {
|
||||
var condition = new ConstantNode(1);
|
||||
var a = new ConstantNode(2);
|
||||
var b = new ConstantNode(3);
|
||||
var n = new ConditionalNode(condition, a, b);
|
||||
|
||||
assert.throws(function () {
|
||||
n.map(function () {});
|
||||
}, /Callback function must return a Node/)
|
||||
});
|
||||
|
||||
it ('should transform a ConditionalNodes condition', function () {
|
||||
var condition = new ConstantNode(1);
|
||||
var a = new ConstantNode(2);
|
||||
var b = new ConstantNode(3);
|
||||
var n = new ConditionalNode(condition, a, b);
|
||||
|
||||
var e = new ConstantNode(4);
|
||||
var f = n.transform(function (node) {
|
||||
return node instanceof ConstantNode && node.value == '1' ? e : node;
|
||||
});
|
||||
|
||||
assert.notStrictEqual(f, n);
|
||||
assert.deepEqual(f.condition, e);
|
||||
assert.deepEqual(f.trueExpr, a);
|
||||
assert.deepEqual(f.falseExpr, b);
|
||||
});
|
||||
|
||||
it ('should transform a ConditionalNodes trueExpr', function () {
|
||||
var condition = new ConstantNode(1);
|
||||
var a = new ConstantNode(2);
|
||||
var b = new ConstantNode(3);
|
||||
var n = new ConditionalNode(condition, a, b);
|
||||
|
||||
var e = new ConstantNode(4);
|
||||
var f = n.transform(function (node) {
|
||||
return node instanceof ConstantNode && node.value == '2' ? e : node;
|
||||
});
|
||||
|
||||
assert.notStrictEqual(f, n);
|
||||
assert.deepEqual(f.condition, condition);
|
||||
assert.deepEqual(f.trueExpr, e);
|
||||
assert.deepEqual(f.falseExpr, b);
|
||||
});
|
||||
|
||||
it ('should transform a ConditionalNodes falseExpr', function () {
|
||||
var condition = new ConstantNode(1);
|
||||
var a = new ConstantNode(2);
|
||||
var b = new ConstantNode(3);
|
||||
var n = new ConditionalNode(condition, a, b);
|
||||
|
||||
var e = new ConstantNode(4);
|
||||
var f = n.transform(function (node) {
|
||||
return node instanceof ConstantNode && node.value == '3' ? e : node;
|
||||
});
|
||||
|
||||
assert.notStrictEqual(f, n);
|
||||
assert.deepEqual(f.condition, condition);
|
||||
assert.deepEqual(f.trueExpr, a);
|
||||
assert.deepEqual(f.falseExpr, e);
|
||||
});
|
||||
|
||||
it ('should transform a ConditionalNode itself', function () {
|
||||
var condition = new ConstantNode(1);
|
||||
var a = new ConstantNode(2);
|
||||
var b = new ConstantNode(3);
|
||||
var n = new ConditionalNode(condition, a, b);
|
||||
|
||||
var e = new ConstantNode(5);
|
||||
var f = n.transform(function (node) {
|
||||
return node instanceof ConditionalNode ? e : node;
|
||||
});
|
||||
|
||||
assert.notStrictEqual(f, n);
|
||||
assert.deepEqual(f, e);
|
||||
});
|
||||
|
||||
it ('should clone a ConditionalNode itself', function () {
|
||||
var condition = new ConstantNode(1);
|
||||
var a = new ConstantNode(2);
|
||||
var b = new ConstantNode(3);
|
||||
var c = new ConditionalNode(condition, a, b);
|
||||
|
||||
var d = c.clone();
|
||||
|
||||
assert(d instanceof ConditionalNode);
|
||||
assert.deepEqual(d, c);
|
||||
assert.notStrictEqual(d, c);
|
||||
assert.strictEqual(d.condition, c.condition);
|
||||
assert.strictEqual(d.trueExpr, c.trueExpr);
|
||||
assert.strictEqual(d.falseExpr, c.falseExpr);
|
||||
});
|
||||
|
||||
it ('test equality another Node', function () {
|
||||
var a = new ConditionalNode(new ConstantNode(1), new ConstantNode(2), new ConstantNode(3));
|
||||
var b = new ConditionalNode(new ConstantNode(1), new ConstantNode(2), new ConstantNode(3));
|
||||
var c = new ConditionalNode(new SymbolNode('x'), new ConstantNode(2), new ConstantNode(3));
|
||||
var d = new ConditionalNode(new ConstantNode(1), new ConstantNode(5), new ConstantNode(3));
|
||||
var e = new ConditionalNode(new ConstantNode(1), new ConstantNode(2), new ConstantNode(55));
|
||||
|
||||
assert.strictEqual(a.equals(null), false);
|
||||
assert.strictEqual(a.equals(undefined), false);
|
||||
assert.strictEqual(a.equals(b), true);
|
||||
assert.strictEqual(a.equals(c), false);
|
||||
assert.strictEqual(a.equals(d), false);
|
||||
assert.strictEqual(a.equals(e), false);
|
||||
});
|
||||
|
||||
it ('should respect the \'all\' parenthesis option', function () {
|
||||
assert.equal(math.parse('a?b:c').toString({parenthesis: 'all'}), '(a) ? (b) : (c)');
|
||||
});
|
||||
|
||||
it ('should stringify a ConditionalNode', function () {
|
||||
var n = new ConditionalNode(condition, a, b);
|
||||
|
||||
assert.equal(n.toString(), 'true ? (a = 2) : (b = 3)');
|
||||
});
|
||||
|
||||
it ('should stringify a ConditionalNode with custom toString', function () {
|
||||
//Also checks if the custom functions get passed on to the children
|
||||
var customFunction = function (node, options) {
|
||||
if (node.type === 'ConditionalNode') {
|
||||
return 'if ' + node.condition.toString(options)
|
||||
+ ' then ' + node.trueExpr.toString(options)
|
||||
+ ' else ' + node.falseExpr.toString(options);
|
||||
}
|
||||
else if (node.type === 'ConstantNode') {
|
||||
return 'const(' + node.value + ', ' + node.valueType + ')'
|
||||
}
|
||||
};
|
||||
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(3);
|
||||
|
||||
var n = new ConditionalNode(a, b, c);
|
||||
|
||||
assert.equal(n.toString({handler: customFunction}), 'if const(1, number) then const(2, number) else const(3, number)');
|
||||
});
|
||||
|
||||
it ('should LaTeX a ConditionalNode', function () {
|
||||
var n = new ConditionalNode(condition, a, b);
|
||||
|
||||
// note that b is enclosed in \\mathrm{...} since it's a unit
|
||||
assert.equal(n.toTex(), '\\begin{cases} { a:=2}, &\\quad{\\text{if }\\;true}\\\\{\\mathrm{b}:=3}, &\\quad{\\text{otherwise}}\\end{cases}');
|
||||
});
|
||||
|
||||
it ('should LaTeX a ConditionalNode with custom toTex', function () {
|
||||
//Also checks if the custom functions get passed on to the children
|
||||
var customFunction = function (node, options) {
|
||||
if (node.type === 'ConditionalNode') {
|
||||
return 'if ' + node.condition.toTex(options)
|
||||
+ ' then ' + node.trueExpr.toTex(options)
|
||||
+ ' else ' + node.falseExpr.toTex(options);
|
||||
}
|
||||
else if (node.type === 'ConstantNode') {
|
||||
return 'const\\left(' + node.value + ', ' + node.valueType + '\\right)'
|
||||
}
|
||||
};
|
||||
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(3);
|
||||
|
||||
var n = new ConditionalNode(a, b, c);
|
||||
|
||||
assert.equal(n.toTex({handler: customFunction}), 'if const\\left(1, number\\right) then const\\left(2, number\\right) else const\\left(3, number\\right)');
|
||||
});
|
||||
|
||||
});
|
||||
191
nodered/rootfs/data/node_modules/mathjs/test/expression/node/ConstantNode.test.js
generated
vendored
Normal file
191
nodered/rootfs/data/node_modules/mathjs/test/expression/node/ConstantNode.test.js
generated
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
// test ConstantNode
|
||||
var assert = require('assert');
|
||||
var approx = require('../../../tools/approx');
|
||||
var math = require('../../../index');
|
||||
var bigmath = require('../../../index').create({number: 'BigNumber'});
|
||||
var Node = math.expression.node.Node;
|
||||
var ConstantNode = math.expression.node.ConstantNode;
|
||||
var SymbolNode = math.expression.node.SymbolNode;
|
||||
|
||||
describe('ConstantNode', function() {
|
||||
|
||||
it ('should create a ConstantNode with value type', function () {
|
||||
var a = new ConstantNode('3', 'number');
|
||||
assert(a instanceof Node);
|
||||
assert.equal(a.type, 'ConstantNode');
|
||||
});
|
||||
|
||||
it ('should create a ConstantNode without value type', function () {
|
||||
var a = new ConstantNode(3);
|
||||
assert(a instanceof Node);
|
||||
assert.equal(a.type, 'ConstantNode');
|
||||
// TODO: extensively test each of the supported types
|
||||
|
||||
assert.deepEqual(new ConstantNode(3), new ConstantNode('3', 'number'));
|
||||
assert.deepEqual(new ConstantNode('hello'), new ConstantNode('hello', 'string'));
|
||||
assert.deepEqual(new ConstantNode(true), new ConstantNode('true', 'boolean'));
|
||||
assert.deepEqual(new ConstantNode(false), new ConstantNode('false', 'boolean'));
|
||||
assert.deepEqual(new ConstantNode(null), new ConstantNode('null', 'null'));
|
||||
assert.deepEqual(new ConstantNode(undefined), new ConstantNode('undefined', 'undefined'));
|
||||
});
|
||||
|
||||
it ('should have isConstantNode', function () {
|
||||
var node = new ConstantNode(1);
|
||||
assert(node.isConstantNode);
|
||||
});
|
||||
|
||||
it ('should throw an error when calling without new operator', function () {
|
||||
assert.throws(function () {ConstantNode('3', 'number')}, SyntaxError);
|
||||
});
|
||||
|
||||
it ('should throw an error in case of wrong construction arguments', function () {
|
||||
assert.throws(function () {new ConstantNode(3, 'number');}, TypeError);
|
||||
assert.throws(function () {new ConstantNode(new Date());}, TypeError);
|
||||
assert.throws(function () {new ConstantNode('3', Number);}, TypeError);
|
||||
});
|
||||
|
||||
it ('should throw an error in case of unknown type of constant', function () {
|
||||
assert.throws(function () {new ConstantNode('3', 'bla').compile();}, TypeError);
|
||||
});
|
||||
|
||||
it ('should compile a ConstantNode', function () {
|
||||
var expr = new ConstantNode('2.3', 'number').compile();
|
||||
assert.strictEqual(expr.eval(), 2.3);
|
||||
|
||||
expr = new ConstantNode('002.3', 'number').compile();
|
||||
assert.strictEqual(expr.eval(), 2.3);
|
||||
|
||||
expr = new ConstantNode('hello', 'string').compile();
|
||||
assert.strictEqual(expr.eval(), 'hello');
|
||||
|
||||
expr = new ConstantNode('true', 'boolean').compile();
|
||||
assert.strictEqual(expr.eval(), true);
|
||||
|
||||
expr = new ConstantNode('undefined', 'undefined').compile();
|
||||
assert.strictEqual(expr.eval(), undefined);
|
||||
|
||||
expr = new ConstantNode('null', 'null').compile();
|
||||
assert.strictEqual(expr.eval(), null);
|
||||
|
||||
});
|
||||
|
||||
it ('should compile a ConstantNode with bigmath', function () {
|
||||
var expr = new bigmath.expression.node.ConstantNode('2.3', 'number').compile();
|
||||
assert.deepEqual(expr.eval(), new bigmath.type.BigNumber(2.3));
|
||||
});
|
||||
|
||||
it ('should find a ConstantNode', function () {
|
||||
var a = new ConstantNode('2', 'number');
|
||||
assert.deepEqual(a.filter(function (node) {return node instanceof ConstantNode}), [a]);
|
||||
assert.deepEqual(a.filter(function (node) {return node instanceof SymbolNode}), []);
|
||||
});
|
||||
|
||||
it ('should run forEach on a ConstantNode', function () {
|
||||
var a = new ConstantNode(2);
|
||||
a.forEach(function () {
|
||||
assert.ok(false, 'should not execute, constant has no childs')
|
||||
});
|
||||
});
|
||||
|
||||
it ('should map a ConstantNode', function () {
|
||||
var a = new ConstantNode(2);
|
||||
var b = a.map(function () {
|
||||
assert.ok(false, 'should not execute, constant has no childs')
|
||||
});
|
||||
|
||||
assert.notStrictEqual(b, a);
|
||||
assert.deepEqual(b, a);
|
||||
});
|
||||
|
||||
it ('should transform a ConstantNode', function () {
|
||||
var a = new ConstantNode(2);
|
||||
var b = new ConstantNode(3);
|
||||
var c = a.transform(function (node) {
|
||||
return node instanceof ConstantNode && node.value == '2' ? b : node;
|
||||
});
|
||||
assert.deepEqual(c, b);
|
||||
|
||||
// no match should leave the node as is
|
||||
var d = a.transform(function (node) {
|
||||
return node instanceof ConstantNode && node.value == '99' ? b : node;
|
||||
});
|
||||
assert.notStrictEqual(d, a);
|
||||
assert.deepEqual(d, a);
|
||||
});
|
||||
|
||||
it ('should clone a ConstantNode', function () {
|
||||
var a = new ConstantNode(2);
|
||||
var b = a.clone();
|
||||
|
||||
assert(b instanceof ConstantNode);
|
||||
assert.deepEqual(a, b);
|
||||
assert.notStrictEqual(a, b);
|
||||
assert.equal(a.value, b.value);
|
||||
assert.equal(a.valueType, b.valueType);
|
||||
});
|
||||
|
||||
it ('test equality another Node', function () {
|
||||
var a = new ConstantNode(2);
|
||||
|
||||
assert.strictEqual(a.equals(null), false);
|
||||
assert.strictEqual(a.equals(undefined), false);
|
||||
assert.strictEqual(a.equals(new ConstantNode(2)), true);
|
||||
assert.strictEqual(a.equals(new ConstantNode(3)), false);
|
||||
assert.strictEqual(a.equals(new ConstantNode('2', 'number')), true);
|
||||
assert.strictEqual(a.equals(new ConstantNode('2', 'string')), false);
|
||||
assert.strictEqual(a.equals(new SymbolNode('2')), false);
|
||||
assert.strictEqual(a.equals({value:2, valueType: 'number'}), false);
|
||||
});
|
||||
|
||||
it ('should stringify a ConstantNode', function () {
|
||||
assert.equal(new ConstantNode('3', 'number').toString(), '3');
|
||||
assert.deepEqual(new ConstantNode('3', 'number').toString(), '3');
|
||||
assert.equal(new ConstantNode('hi', 'string').toString(), '"hi"');
|
||||
assert.equal(new ConstantNode('true', 'boolean').toString(), 'true');
|
||||
assert.equal(new ConstantNode('false', 'boolean').toString(), 'false');
|
||||
assert.equal(new ConstantNode('undefined', 'undefined').toString(), 'undefined');
|
||||
assert.equal(new ConstantNode('null', 'null').toString(), 'null');
|
||||
});
|
||||
|
||||
it ('should stringify a ConstantNode with custom toString', function () {
|
||||
//Also checks if the custom functions get passed on to the children
|
||||
var customFunction = function (node, options) {
|
||||
if (node.type === 'ConstantNode') {
|
||||
return 'const(' + node.value + ', ' + node.valueType + ')'
|
||||
}
|
||||
};
|
||||
|
||||
var n = new ConstantNode(1);
|
||||
|
||||
assert.equal(n.toString({handler: customFunction}), 'const(1, number)');
|
||||
});
|
||||
|
||||
it ('should LaTeX a ConstantNode', function () {
|
||||
assert.equal(new ConstantNode('3', 'number').toTex(), '3');
|
||||
assert.deepEqual(new ConstantNode('3', 'number').toTex(), '3');
|
||||
assert.equal(new ConstantNode('hi', 'string').toTex(), '\\mathtt{"hi"}');
|
||||
assert.equal(new ConstantNode('true', 'boolean').toTex(), 'true');
|
||||
assert.equal(new ConstantNode('false', 'boolean').toTex(), 'false');
|
||||
assert.equal(new ConstantNode('undefined', 'undefined').toTex(), 'undefined');
|
||||
assert.equal(new ConstantNode('null', 'null').toTex(), 'null');
|
||||
});
|
||||
|
||||
it ('should LaTeX a ConstantNode in exponential notation', function () {
|
||||
var n = new ConstantNode('1e10', 'number');
|
||||
assert.equal(n.toTex(), '1\\cdot10^{10}');
|
||||
});
|
||||
|
||||
it ('should LaTeX a ConstantNode with custom toTex', function () {
|
||||
//Also checks if the custom functions get passed on to the children
|
||||
var customFunction = function (node, options) {
|
||||
if (node.type === 'ConstantNode') {
|
||||
return 'const\\left(' + node.value + ', ' + node.valueType + '\\right)'
|
||||
}
|
||||
};
|
||||
|
||||
var n = new ConstantNode(1);
|
||||
|
||||
assert.equal(n.toTex({handler: customFunction}), 'const\\left(1, number\\right)');
|
||||
});
|
||||
|
||||
});
|
||||
438
nodered/rootfs/data/node_modules/mathjs/test/expression/node/FunctionAssignmentNode.test.js
generated
vendored
Normal file
438
nodered/rootfs/data/node_modules/mathjs/test/expression/node/FunctionAssignmentNode.test.js
generated
vendored
Normal file
@@ -0,0 +1,438 @@
|
||||
// test FunctionAssignmentNode
|
||||
var assert = require('assert');
|
||||
var approx = require('../../../tools/approx');
|
||||
var math = require('../../../index').create();
|
||||
var Node = math.expression.node.Node;
|
||||
var ConstantNode = math.expression.node.ConstantNode;
|
||||
var SymbolNode = math.expression.node.SymbolNode;
|
||||
var AssignmentNode = math.expression.node.AssignmentNode;
|
||||
var ConditionalNode = math.expression.node.ConditionalNode;
|
||||
var OperatorNode = math.expression.node.OperatorNode;
|
||||
var FunctionNode = math.expression.node.FunctionNode;
|
||||
var FunctionAssignmentNode = math.expression.node.FunctionAssignmentNode;
|
||||
var RangeNode = math.expression.node.RangeNode;
|
||||
|
||||
describe('FunctionAssignmentNode', function() {
|
||||
|
||||
it ('should create a FunctionAssignmentNode', function () {
|
||||
var n = new FunctionAssignmentNode('f', ['x'], new ConstantNode(2));
|
||||
assert(n instanceof FunctionAssignmentNode);
|
||||
assert(n instanceof Node);
|
||||
assert.equal(n.type, 'FunctionAssignmentNode');
|
||||
});
|
||||
|
||||
it ('should have isFunctionAssignmentNode', function () {
|
||||
var node = new FunctionAssignmentNode('f', ['x'], new ConstantNode(2));
|
||||
assert(node.isFunctionAssignmentNode);
|
||||
});
|
||||
|
||||
it ('should throw an error when calling without new operator', function () {
|
||||
assert.throws(function () {FunctionAssignmentNode('f', ['x'], new ConstantNode(2))}, SyntaxError);
|
||||
});
|
||||
|
||||
it ('should throw an error on wrong constructor arguments', function () {
|
||||
assert.throws(function () {new FunctionAssignmentNode()}, TypeError);
|
||||
assert.throws(function () {new FunctionAssignmentNode('a')}, TypeError);
|
||||
assert.throws(function () {new FunctionAssignmentNode('a', ['x'])}, TypeError);
|
||||
assert.throws(function () {new FunctionAssignmentNode(null, ['x'], new ConstantNode(2))}, TypeError);
|
||||
});
|
||||
|
||||
it ('should compile a FunctionAssignmentNode', function () {
|
||||
var a = new ConstantNode(2);
|
||||
var x = new SymbolNode('x');
|
||||
var o = new OperatorNode('+', 'add', [a, x]);
|
||||
var n = new FunctionAssignmentNode('f', ['x'], o);
|
||||
|
||||
var expr = n.compile();
|
||||
var scope = {};
|
||||
var f = expr.eval(scope);
|
||||
assert.equal(typeof scope.f, 'function');
|
||||
assert.equal(scope.f(3), 5);
|
||||
assert.equal(scope.f(5), 7);
|
||||
|
||||
});
|
||||
|
||||
it ('should compile a typed FunctionAssignmentNode', function () {
|
||||
var a = new ConstantNode(2);
|
||||
var x = new SymbolNode('x');
|
||||
var o = new OperatorNode('+', 'add', [a, x]);
|
||||
var n = new FunctionAssignmentNode('f', [{name: 'x', type: 'number' }], o);
|
||||
|
||||
var expr = n.compile();
|
||||
var scope = {};
|
||||
var f = expr.eval(scope);
|
||||
assert.equal(typeof scope.f, 'function');
|
||||
assert.equal(scope.f(3), 5);
|
||||
assert.equal(scope.f(5), 7);
|
||||
assert.throws(function () { scope.f(new Date())}, /Unexpected type of argument in function f/);
|
||||
assert.throws(function () { scope.f(2, 2)}, /Too many arguments in function f/);
|
||||
assert.throws(function () { scope.f()}, /Too few arguments in function f/);
|
||||
});
|
||||
|
||||
it ('should eval a recursive FunctionAssignmentNode', function () {
|
||||
var x = new SymbolNode('x');
|
||||
var one = new ConstantNode(1);
|
||||
var condition = new OperatorNode('<=', 'smallerEq', [x, one]);
|
||||
var truePart = one;
|
||||
var falsePart = new OperatorNode('*', 'multiply', [
|
||||
x,
|
||||
new FunctionNode(new SymbolNode('factorial'), [
|
||||
new OperatorNode('-', 'subtract', [
|
||||
x,
|
||||
one
|
||||
])
|
||||
])
|
||||
]);
|
||||
var n1 = new ConditionalNode(condition, truePart, falsePart);
|
||||
|
||||
var n2 = new FunctionAssignmentNode('factorial', ['x'], n1);
|
||||
|
||||
var expr = n2.compile();
|
||||
var scope = {};
|
||||
var factorial = expr.eval(scope);
|
||||
assert.equal(typeof scope.factorial, 'function');
|
||||
assert.equal(factorial(3), 6);
|
||||
assert.equal(factorial(5), 120);
|
||||
});
|
||||
|
||||
it ('should eval a recursive FunctionAssignmentNode with two recursive calls', function () {
|
||||
var x = new SymbolNode('x');
|
||||
var zero = new ConstantNode(0);
|
||||
var one = new ConstantNode(1);
|
||||
var two = new ConstantNode(2);
|
||||
|
||||
var n1 = new ConditionalNode(
|
||||
new OperatorNode('<=', 'smallerEq', [x, zero]),
|
||||
zero,
|
||||
new ConditionalNode(
|
||||
new OperatorNode('<=', 'smallerEq', [x, two]),
|
||||
one,
|
||||
new OperatorNode('+', 'add', [
|
||||
new FunctionNode(new SymbolNode('fib'), [
|
||||
new OperatorNode('-', 'subtract', [ x, one ])
|
||||
]),
|
||||
new FunctionNode(new SymbolNode('fib'), [
|
||||
new OperatorNode('-', 'subtract', [ x, two ])
|
||||
])
|
||||
])
|
||||
)
|
||||
);
|
||||
|
||||
var n2 = new FunctionAssignmentNode('fib', ['x'], n1);
|
||||
//var n2 = math.parse('fib(x) = (x <= 0) ? 0 : ((x <= 2) ? 1 : (fib(x - 1) + f(fib - 2)))');
|
||||
|
||||
var expr = n2.compile();
|
||||
var scope = {};
|
||||
var fib = expr.eval(scope);
|
||||
|
||||
assert.equal(typeof fib, 'function');
|
||||
assert.equal(fib(0), 0);
|
||||
assert.equal(fib(1), 1);
|
||||
assert.equal(fib(2), 1);
|
||||
assert.equal(fib(3), 2);
|
||||
assert.equal(fib(4), 3);
|
||||
assert.equal(fib(5), 5);
|
||||
assert.equal(fib(6), 8);
|
||||
assert.equal(fib(7), 13);
|
||||
assert.equal(fib(8), 21);
|
||||
});
|
||||
|
||||
it ('should pass function arguments in scope to functions with rawArgs', function () {
|
||||
var outputScope = function (args, math, scope) {
|
||||
return scope;
|
||||
}
|
||||
outputScope.rawArgs = true;
|
||||
math.import({ outputScope: outputScope }, { override: true });
|
||||
|
||||
// f(x) = outputScope(x)
|
||||
var x = new SymbolNode('x');
|
||||
var o = new FunctionNode('outputScope', [x]);
|
||||
var n = new FunctionAssignmentNode('f', ['x'], o);
|
||||
|
||||
var scope = {a: 2};
|
||||
var f = n.eval(scope);
|
||||
assert.deepEqual(f(3), {a: 2, f: f, x: 3});
|
||||
});
|
||||
|
||||
it ('should pass function arguments in scope to functions with rawArgs returned by another function', function () {
|
||||
var outputScope = function (args, math, scope) {
|
||||
return scope;
|
||||
}
|
||||
|
||||
outputScope.rawArgs = true;
|
||||
var returnOutputScope = function () {
|
||||
return outputScope
|
||||
}
|
||||
|
||||
math.import({
|
||||
outputScope: outputScope,
|
||||
returnOutputScope: returnOutputScope
|
||||
}, { override: true });
|
||||
|
||||
// f(x, y) = returnOutputScope(x)(y)
|
||||
var a = new FunctionNode('returnOutputScope', [new SymbolNode('x')]);
|
||||
var b = new FunctionNode(a, [new SymbolNode('y')]);
|
||||
var n = new FunctionAssignmentNode('f', ['x', 'y'], b);
|
||||
|
||||
var scope = {a: 2};
|
||||
var f = n.eval(scope);
|
||||
assert.deepEqual(f(3, 4), {a: 2, f: f, x: 3, y: 4});
|
||||
});
|
||||
|
||||
it ('should pass function arguments in scope to functions with rawArgs and transform', function () {
|
||||
var outputScope = function (x) {
|
||||
return 'should not occur'
|
||||
}
|
||||
outputScope.transform = function (args, math, scope) {
|
||||
return scope;
|
||||
}
|
||||
outputScope.transform.rawArgs = true;
|
||||
math.import({ outputScope: outputScope }, { override: true });
|
||||
|
||||
// f(x) = outputScope(x)
|
||||
var x = new SymbolNode('x');
|
||||
var o = new FunctionNode('outputScope', [x]);
|
||||
var n = new FunctionAssignmentNode('f', ['x'], o);
|
||||
|
||||
var scope = {a: 2};
|
||||
var f = n.eval(scope);
|
||||
assert.deepEqual(f(3), {a: 2, f: f, x: 3});
|
||||
});
|
||||
|
||||
it ('should filter a FunctionAssignmentNode', function () {
|
||||
var a = new ConstantNode(2);
|
||||
var x = new SymbolNode('x');
|
||||
var o = new OperatorNode('+', 'add', [a, x]);
|
||||
var n = new FunctionAssignmentNode('f', ['x'], o);
|
||||
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof FunctionAssignmentNode}), [n]);
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof SymbolNode}), [x]);
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof RangeNode}), []);
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof ConstantNode}), [a]);
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof ConstantNode && node.value == '2'}), [a]);
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof ConstantNode && node.value == '4'}), []);
|
||||
});
|
||||
|
||||
it ('should throw an error when creating a FunctionAssignmentNode with a reserved keyword', function () {
|
||||
assert.throws(function () {
|
||||
new FunctionAssignmentNode('end', ['x'], new ConstantNode(2));
|
||||
}, /Illegal function name/)
|
||||
});
|
||||
|
||||
it ('should filter a FunctionAssignmentNode without expression', function () {
|
||||
var e = new FunctionAssignmentNode('f', ['x'], new ConstantNode(2));
|
||||
|
||||
assert.deepEqual(e.filter(function (node) {return node instanceof FunctionAssignmentNode}), [e]);
|
||||
assert.deepEqual(e.filter(function (node) {return node instanceof SymbolNode}), []);
|
||||
});
|
||||
|
||||
it ('should run forEach on a FunctionAssignmentNode', function () {
|
||||
var a = new ConstantNode(2);
|
||||
var n = new FunctionAssignmentNode('f', ['x'], a);
|
||||
|
||||
var nodes = [];
|
||||
var paths = [];
|
||||
n.forEach(function (node, path, parent) {
|
||||
nodes.push(node);
|
||||
paths.push(path);
|
||||
assert.strictEqual(parent, n);
|
||||
});
|
||||
|
||||
assert.equal(nodes.length, 1);
|
||||
assert.strictEqual(nodes[0], a);
|
||||
assert.deepEqual(paths, ['expr']);
|
||||
});
|
||||
|
||||
it ('should map a FunctionAssignmentNode', function () {
|
||||
var a = new ConstantNode(2);
|
||||
var n = new FunctionAssignmentNode('f', ['x'], a);
|
||||
|
||||
var nodes = [];
|
||||
var paths = [];
|
||||
var e = new ConstantNode(3);
|
||||
var f = n.map(function (node, path, parent) {
|
||||
nodes.push(node);
|
||||
paths.push(path);
|
||||
assert.strictEqual(parent, n);
|
||||
|
||||
return node instanceof SymbolNode && node.name == 'x' ? e : node;
|
||||
});
|
||||
|
||||
assert.equal(nodes.length, 1);
|
||||
assert.strictEqual(nodes[0], a);
|
||||
assert.deepEqual(paths, ['expr']);
|
||||
|
||||
assert.notStrictEqual(f, n);
|
||||
assert.deepEqual(f.expr, a);
|
||||
});
|
||||
|
||||
it ('should throw an error when the map callback does not return a node', function () {
|
||||
var a = new ConstantNode(2);
|
||||
var n = new FunctionAssignmentNode('f', ['x'], a);
|
||||
|
||||
assert.throws(function () {
|
||||
n.map(function () {});
|
||||
}, /Callback function must return a Node/)
|
||||
});
|
||||
|
||||
it ('should transform a FunctionAssignmentNodes (nested) parameters', function () {
|
||||
// f(x) = 2 + x
|
||||
var a = new ConstantNode(2);
|
||||
var x = new SymbolNode('x');
|
||||
var c = new OperatorNode('+', 'add', [a, x]);
|
||||
var n = new FunctionAssignmentNode('f', ['x'], c);
|
||||
|
||||
var e = new ConstantNode(3);
|
||||
var f = n.transform(function (node) {
|
||||
return node instanceof SymbolNode && node.name == 'x' ? e : node;
|
||||
});
|
||||
|
||||
assert.notStrictEqual(f, n);
|
||||
assert.deepEqual(f.expr.args[0], a);
|
||||
assert.deepEqual(f.expr.args[1], e);
|
||||
});
|
||||
|
||||
it ('should transform a FunctionAssignmentNode itself', function () {
|
||||
// f(x) = 2 + x
|
||||
var a = new ConstantNode(2);
|
||||
var x = new SymbolNode('x');
|
||||
var c = new OperatorNode('+', 'add', [a, x]);
|
||||
var n = new FunctionAssignmentNode('f', ['x'], c);
|
||||
|
||||
var e = new ConstantNode(5);
|
||||
var f = n.transform(function (node) {
|
||||
return node instanceof FunctionAssignmentNode ? e : node;
|
||||
});
|
||||
|
||||
assert.notStrictEqual(f, n);
|
||||
assert.deepEqual(f, e);
|
||||
});
|
||||
|
||||
it ('should clone a FunctionAssignmentNode', function () {
|
||||
// f(x) = 2 + x
|
||||
var a = new ConstantNode(2);
|
||||
var x = new SymbolNode('x');
|
||||
var c = new OperatorNode('+', 'add', [a, x]);
|
||||
var d = new FunctionAssignmentNode('f', ['x'], c);
|
||||
|
||||
var e = d.clone();
|
||||
assert(e instanceof FunctionAssignmentNode);
|
||||
assert.deepEqual(e, d);
|
||||
assert.notStrictEqual(e, d);
|
||||
assert.strictEqual(e.expr, d.expr);
|
||||
});
|
||||
|
||||
it ('test equality another Node', function () {
|
||||
var a = new FunctionAssignmentNode('f', ['x'],
|
||||
new OperatorNode('+', 'add', [new ConstantNode(2), new SymbolNode('x')]));
|
||||
var b = new FunctionAssignmentNode('f', ['x'],
|
||||
new OperatorNode('+', 'add', [new ConstantNode(2), new SymbolNode('x')]));
|
||||
var c = new FunctionAssignmentNode('g', ['x'],
|
||||
new OperatorNode('+', 'add', [new ConstantNode(2), new SymbolNode('x')]));
|
||||
var d = new FunctionAssignmentNode('f', ['y'],
|
||||
new OperatorNode('+', 'add', [new ConstantNode(2), new SymbolNode('x')]));
|
||||
var e = new FunctionAssignmentNode('f', ['x'],
|
||||
new OperatorNode('+', 'add', [new ConstantNode(3), new SymbolNode('x')]));
|
||||
var f = new SymbolNode('add');
|
||||
|
||||
assert.strictEqual(a.equals(null), false);
|
||||
assert.strictEqual(a.equals(undefined), false);
|
||||
assert.strictEqual(a.equals(b), true);
|
||||
assert.strictEqual(a.equals(c), false);
|
||||
assert.strictEqual(a.equals(d), false);
|
||||
assert.strictEqual(a.equals(e), false);
|
||||
assert.strictEqual(a.equals(f), false);
|
||||
});
|
||||
|
||||
it ('should respect the \'all\' parenthesis option', function () {
|
||||
var expr = math.parse('f(x)=x+1');
|
||||
assert.equal(expr.toString({parenthesis: 'all'}), 'f(x) = (x + 1)');
|
||||
assert.equal(expr.toTex({parenthesis: 'all'}), '\\mathrm{f}\\left(x\\right):=\\left( x+1\\right)');
|
||||
});
|
||||
|
||||
it ('should stringify a FunctionAssignmentNode', function () {
|
||||
var a = new ConstantNode(2);
|
||||
var x = new SymbolNode('x');
|
||||
var o = new OperatorNode('+', 'add', [a, x]);
|
||||
var n = new FunctionAssignmentNode('f', ['x'], o);
|
||||
|
||||
assert.equal(n.toString(), 'f(x) = 2 + x');
|
||||
});
|
||||
|
||||
it ('should stringify a FunctionAssignmentNode conataining an AssignmentNode', function () {
|
||||
var a = new ConstantNode(2);
|
||||
|
||||
var n1 = new AssignmentNode(new SymbolNode('a'), a);
|
||||
var n = new FunctionAssignmentNode('f', ['x'], n1);
|
||||
|
||||
assert.equal(n.toString(), 'f(x) = (a = 2)');
|
||||
});
|
||||
|
||||
it ('should stringify a FunctionAssignmentNode with custom toString', function () {
|
||||
//Also checks if the custom functions get passed on to the children
|
||||
var customFunction = function (node, options) {
|
||||
if (node.type === 'FunctionAssignmentNode') {
|
||||
var string = '[' + node.name + '](';
|
||||
node.params.forEach(function (param) {
|
||||
string += param + ', ';
|
||||
});
|
||||
|
||||
string += ')=' + node.expr.toString(options);
|
||||
return string;
|
||||
}
|
||||
else if (node.type === 'ConstantNode') {
|
||||
return 'const(' + node.value + ', ' + node.valueType + ')'
|
||||
}
|
||||
};
|
||||
|
||||
var a = new ConstantNode(1);
|
||||
|
||||
var n = new FunctionAssignmentNode('func', ['x'], a);
|
||||
|
||||
assert.equal(n.toString({handler: customFunction}), '[func](x, )=const(1, number)');
|
||||
});
|
||||
|
||||
it ('should LaTeX a FunctionAssignmentNode', function() {
|
||||
var a = new ConstantNode(2);
|
||||
var x = new SymbolNode('x');
|
||||
var o = new OperatorNode('/', 'divide', [x, a]);
|
||||
var p = new OperatorNode('^', 'pow', [o, a]);
|
||||
var n = new FunctionAssignmentNode('f', ['x'], p);
|
||||
|
||||
assert.equal(n.toTex(), '\\mathrm{f}\\left(x\\right):=\\left({\\frac{ x}{2}}\\right)^{2}');
|
||||
});
|
||||
|
||||
it ('should LaTeX a FunctionAssignmentNode containing an AssignmentNode', function () {
|
||||
var a = new ConstantNode(2);
|
||||
|
||||
var n1 = new AssignmentNode(new SymbolNode('a'), a);
|
||||
var n = new FunctionAssignmentNode('f', ['x'], n1);
|
||||
|
||||
assert.equal(n.toTex(), '\\mathrm{f}\\left(x\\right):=\\left( a:=2\\right)');
|
||||
});
|
||||
|
||||
it ('should LaTeX a FunctionAssignmentNode with custom toTex', function () {
|
||||
//Also checks if the custom functions get passed on to the children
|
||||
var customFunction = function (node, options) {
|
||||
if (node.type === 'FunctionAssignmentNode') {
|
||||
var latex = '\\mbox{' + node.name + '}\\left(';
|
||||
node.params.forEach(function (param) {
|
||||
latex += param + ', ';
|
||||
});
|
||||
|
||||
latex += '\\right)=' + node.expr.toTex(options);
|
||||
return latex;
|
||||
}
|
||||
else if (node.type === 'ConstantNode') {
|
||||
return 'const\\left(' + node.value + ', ' + node.valueType + '\\right)'
|
||||
}
|
||||
};
|
||||
|
||||
var a = new ConstantNode(1);
|
||||
|
||||
var n = new FunctionAssignmentNode('func', ['x'], a);
|
||||
|
||||
assert.equal(n.toTex({handler: customFunction}), '\\mbox{func}\\left(x, \\right)=const\\left(1, number\\right)');
|
||||
});
|
||||
|
||||
});
|
||||
583
nodered/rootfs/data/node_modules/mathjs/test/expression/node/FunctionNode.test.js
generated
vendored
Normal file
583
nodered/rootfs/data/node_modules/mathjs/test/expression/node/FunctionNode.test.js
generated
vendored
Normal file
@@ -0,0 +1,583 @@
|
||||
// test FunctionNode
|
||||
var assert = require('assert');
|
||||
var approx = require('../../../tools/approx');
|
||||
var math = require('../../../index').create();
|
||||
var Node = math.expression.node.Node;
|
||||
var ConstantNode = math.expression.node.ConstantNode;
|
||||
var SymbolNode = math.expression.node.SymbolNode;
|
||||
var FunctionNode = math.expression.node.FunctionNode;
|
||||
var OperatorNode = math.expression.node.OperatorNode;
|
||||
var RangeNode = math.expression.node.RangeNode;
|
||||
var IndexNode = math.expression.node.IndexNode;
|
||||
var AccessorNode = math.expression.node.AccessorNode;
|
||||
|
||||
describe('FunctionNode', function() {
|
||||
|
||||
it ('should create a FunctionNode', function () {
|
||||
var c = new ConstantNode(4);
|
||||
var n = new FunctionNode(new SymbolNode('sqrt'), [c]);
|
||||
assert(n instanceof FunctionNode);
|
||||
assert(n instanceof Node);
|
||||
assert.equal(n.type, 'FunctionNode');
|
||||
});
|
||||
|
||||
it ('should have isFunctionNode', function () {
|
||||
var c = new ConstantNode(1);
|
||||
var node = new FunctionNode(new SymbolNode('square'), [c]);
|
||||
assert(node.isFunctionNode);
|
||||
});
|
||||
|
||||
it ('should throw an error when calling without new operator', function () {
|
||||
var s = new SymbolNode('sqrt');
|
||||
var c = new ConstantNode(4);
|
||||
assert.throws(function () {FunctionNode(s, [c])}, SyntaxError);
|
||||
});
|
||||
|
||||
it ('should throw an error when calling with wrong arguments', function () {
|
||||
var s = new SymbolNode('sqrt');
|
||||
var c = new ConstantNode(4);
|
||||
assert.throws(function () {new FunctionNode(new Date(), [])}, TypeError);
|
||||
assert.throws(function () {new FunctionNode(s, [2, 3])}, TypeError);
|
||||
assert.throws(function () {new FunctionNode(s, [c, 3])}, TypeError);
|
||||
});
|
||||
|
||||
it ('should get the name of a FunctionNode', function () {
|
||||
var n1 = new FunctionNode(new SymbolNode('sqrt'), [new ConstantNode(4)]);
|
||||
assert.equal(n1.name, 'sqrt');
|
||||
|
||||
var n = new AccessorNode(new SymbolNode('a'), new IndexNode([new ConstantNode('toString')]));
|
||||
var n2 = new FunctionNode(n, [new ConstantNode(4)]);
|
||||
assert.equal(n2.name, 'toString');
|
||||
|
||||
var n3 = new FunctionNode(new OperatorNode('+', 'add', []), [new ConstantNode(4)]);
|
||||
assert.equal(n3.name, '');
|
||||
});
|
||||
|
||||
it ('should compile a FunctionNode', function () {
|
||||
var s = new SymbolNode('sqrt');
|
||||
var c = new ConstantNode(4);
|
||||
var n = new FunctionNode(s, [c]);
|
||||
|
||||
var scope = {};
|
||||
assert.equal(n.compile().eval(scope), 2);
|
||||
});
|
||||
|
||||
it ('should compile a FunctionNode containing an index', function () {
|
||||
var s = new SymbolNode('foo');
|
||||
var range = [new ConstantNode('bar')];
|
||||
var i = new IndexNode(range);
|
||||
var a = new AccessorNode(s, i);
|
||||
var c = new ConstantNode(4);
|
||||
var n = new FunctionNode(a, [c]);
|
||||
|
||||
var scope = {
|
||||
foo: {
|
||||
bar: function (x) {
|
||||
return x * x;
|
||||
}
|
||||
}
|
||||
};
|
||||
assert.equal(n.compile().eval(scope), 16);
|
||||
});
|
||||
|
||||
it ('should execute a FunctionNode with the right context', function () {
|
||||
var s = new SymbolNode('foo');
|
||||
var i = new IndexNode([new ConstantNode('getCount')]);
|
||||
var a = new AccessorNode(s, i);
|
||||
var c = new ConstantNode(4);
|
||||
var n = new FunctionNode(a, [c]);
|
||||
|
||||
var scope = {
|
||||
foo: {
|
||||
count: 42,
|
||||
getCount: function () {
|
||||
return this.count;
|
||||
}
|
||||
}
|
||||
};
|
||||
assert.equal(n.compile().eval(scope), 42);
|
||||
});
|
||||
|
||||
it ('should compile a FunctionNode with a raw function', function () {
|
||||
var mymath = math.create();
|
||||
function myFunction (args, _math, _scope) {
|
||||
assert.equal(args.length, 2);
|
||||
assert(args[0] instanceof mymath.expression.node.Node);
|
||||
assert(args[1] instanceof mymath.expression.node.Node);
|
||||
assert.deepEqual(_math.__proto__, mymath);
|
||||
assert.deepEqual(_scope, scope);
|
||||
return 'myFunction(' + args.join(', ') + ')';
|
||||
}
|
||||
myFunction.rawArgs = true;
|
||||
mymath.import({myFunction: myFunction});
|
||||
|
||||
var s = new SymbolNode('myFunction');
|
||||
var a = new mymath.expression.node.ConstantNode(4);
|
||||
var b = new mymath.expression.node.ConstantNode(5);
|
||||
var n = new mymath.expression.node.FunctionNode(s, [a, b]);
|
||||
|
||||
var scope = {};
|
||||
assert.equal(n.compile().eval(scope), 'myFunction(4, 5)');
|
||||
});
|
||||
|
||||
it ('should compile a FunctionNode containing an index resolving to a function with rawArgs', function () {
|
||||
var mymath = math.create();
|
||||
function myFunction (args, _math, _scope) {
|
||||
assert.equal(args.length, 2);
|
||||
assert(args[0] instanceof mymath.expression.node.Node);
|
||||
assert(args[1] instanceof mymath.expression.node.Node);
|
||||
assert.deepEqual(_math.__proto__, mymath);
|
||||
assert.deepEqual(_scope, scope);
|
||||
return 'myFunction(' + args.join(', ') + ')';
|
||||
}
|
||||
myFunction.rawArgs = true;
|
||||
|
||||
var obj = new SymbolNode('obj');
|
||||
var prop = new ConstantNode('myFunction');
|
||||
var i = new IndexNode([prop]);
|
||||
var a = new AccessorNode(obj, i);
|
||||
var b = new mymath.expression.node.ConstantNode(4);
|
||||
var c = new mymath.expression.node.ConstantNode(5);
|
||||
var n = new mymath.expression.node.FunctionNode(a, [b, c]);
|
||||
|
||||
var scope = {
|
||||
obj: {
|
||||
myFunction: myFunction
|
||||
}
|
||||
};
|
||||
assert.equal(n.compile().eval(scope), 'myFunction(4, 5)');
|
||||
});
|
||||
|
||||
it ('should compile a FunctionNode with overloaded a raw function', function () {
|
||||
var mymath = math.create();
|
||||
function myFunction (args, _math, _scope) {
|
||||
assert.ok(false, 'should not be executed');
|
||||
}
|
||||
myFunction.rawArgs = true;
|
||||
mymath.import({myFunction: myFunction});
|
||||
|
||||
var s = new SymbolNode('myFunction');
|
||||
var a = new mymath.expression.node.ConstantNode(4);
|
||||
var b = new mymath.expression.node.ConstantNode(5);
|
||||
var n = new mymath.expression.node.FunctionNode(s, [a, b]);
|
||||
|
||||
var scope = {
|
||||
myFunction: function () {
|
||||
return 42;
|
||||
}
|
||||
};
|
||||
assert.equal(n.compile().eval(scope), 42);
|
||||
});
|
||||
|
||||
it ('should filter a FunctionNode', function () {
|
||||
var s = new SymbolNode('a');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(1);
|
||||
var n = new FunctionNode(s, [b, c]);
|
||||
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof FunctionNode}), [n]);
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof RangeNode}), []);
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof ConstantNode}), [b, c]);
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof ConstantNode && node.value == '2'}), [b]);
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof ConstantNode && node.value == '4'}), []);
|
||||
});
|
||||
|
||||
it ('should run forEach on a FunctionNode', function () {
|
||||
// multiply(x + 2, x)
|
||||
var s = new SymbolNode('multiply');
|
||||
var a = new SymbolNode('x');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new OperatorNode('+', 'add', [a, b]);
|
||||
var d = new SymbolNode('x');
|
||||
var f = new FunctionNode(s, [c, d]);
|
||||
|
||||
var nodes = [];
|
||||
var paths = [];
|
||||
f.forEach(function (node, path, parent) {
|
||||
nodes.push(node);
|
||||
paths.push(path);
|
||||
assert.strictEqual(parent, f);
|
||||
});
|
||||
|
||||
assert.equal(nodes.length, 2);
|
||||
assert.strictEqual(nodes[0], c);
|
||||
assert.strictEqual(nodes[1], d);
|
||||
assert.deepEqual(paths, ['args[0]', 'args[1]']);
|
||||
});
|
||||
|
||||
it ('should map a FunctionNode', function () {
|
||||
// multiply(x + 2, x)
|
||||
var s = new SymbolNode('multiply');
|
||||
var a = new SymbolNode('x');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new OperatorNode('+', 'add', [a, b]);
|
||||
var d = new SymbolNode('x');
|
||||
var f = new FunctionNode(s, [c, d]);
|
||||
|
||||
var nodes = [];
|
||||
var paths = [];
|
||||
var g = new ConstantNode(3);
|
||||
var h = f.map(function (node, path, parent) {
|
||||
nodes.push(node);
|
||||
paths.push(path);
|
||||
assert.strictEqual(parent, f);
|
||||
|
||||
return node instanceof SymbolNode && node.name == 'x' ? g : node;
|
||||
});
|
||||
|
||||
assert.equal(nodes.length, 2);
|
||||
assert.strictEqual(nodes[0], c);
|
||||
assert.strictEqual(nodes[1], d);
|
||||
assert.deepEqual(paths, ['args[0]', 'args[1]']);
|
||||
|
||||
assert.notStrictEqual(h, f);
|
||||
assert.strictEqual(h.args[0], c);
|
||||
assert.strictEqual(h.args[0].args[0], a);
|
||||
assert.strictEqual(h.args[0].args[1], b);
|
||||
assert.equal(h.fn.name, 'multiply');
|
||||
assert.strictEqual(h.args[1], g);
|
||||
});
|
||||
|
||||
it ('should throw an error when the map callback does not return a node', function () {
|
||||
var s = new SymbolNode('factorial');
|
||||
var b = new ConstantNode(2);
|
||||
var f = new FunctionNode(s, [b]);
|
||||
|
||||
assert.throws(function () {
|
||||
f.map(function () {});
|
||||
}, /Callback function must return a Node/)
|
||||
});
|
||||
|
||||
it ('should transform a FunctionNodes (nested) parameters', function () {
|
||||
// multiply(x + 2, x)
|
||||
var s = new SymbolNode('multiply');
|
||||
var a = new SymbolNode('x');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new OperatorNode('+', 'add', [a, b]);
|
||||
var d = new SymbolNode('x');
|
||||
var f = new FunctionNode(s, [c, d]);
|
||||
|
||||
var g = new ConstantNode(3);
|
||||
var h = f.transform(function (node) {
|
||||
return node instanceof SymbolNode && node.name == 'x' ? g : node;
|
||||
});
|
||||
|
||||
assert.notStrictEqual(h, f);
|
||||
assert.deepEqual(h.args[0].args[0], g);
|
||||
assert.deepEqual(h.args[0].args[1], b);
|
||||
assert.deepEqual(h.name, 'multiply');
|
||||
assert.deepEqual(h.args[1], g);
|
||||
});
|
||||
|
||||
it ('should transform a FunctionNodes name', function () {
|
||||
// add(2, 3)
|
||||
var s = new SymbolNode('add');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(3);
|
||||
var d = new FunctionNode(s, [b, c]);
|
||||
|
||||
var f = d.transform(function (node) {
|
||||
if (node instanceof FunctionNode) {
|
||||
node.fn = new SymbolNode('subtract');
|
||||
}
|
||||
return node;
|
||||
});
|
||||
|
||||
assert.notStrictEqual(f, d);
|
||||
assert.deepEqual(f.name, 'subtract');
|
||||
});
|
||||
|
||||
it ('should transform a FunctionNode itself', function () {
|
||||
// add(2, 3)
|
||||
var s = new SymbolNode('add');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(3);
|
||||
var d = new FunctionNode(s, [b, c]);
|
||||
|
||||
var e = new ConstantNode(5);
|
||||
var f = d.transform(function (node) {
|
||||
return node instanceof FunctionNode ? e : node;
|
||||
});
|
||||
|
||||
assert.deepEqual(f, e);
|
||||
});
|
||||
|
||||
it ('should traverse a FunctionNode', function () {
|
||||
// add(2, 3)
|
||||
var s = new SymbolNode('add');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(3);
|
||||
var d = new FunctionNode(s, [b, c]);
|
||||
|
||||
var count = 0;
|
||||
d.traverse(function (node, path, parent) {
|
||||
count++;
|
||||
|
||||
switch(count) {
|
||||
case 1:
|
||||
assert.strictEqual(node, d);
|
||||
assert.strictEqual(path, null);
|
||||
assert.strictEqual(parent, null);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
assert.strictEqual(node, b);
|
||||
assert.strictEqual(path, 'args[0]');
|
||||
assert.strictEqual(parent, d);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
assert.strictEqual(node, c);
|
||||
assert.strictEqual(path, 'args[1]');
|
||||
assert.strictEqual(parent, d);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
assert.equal(count, 3);
|
||||
});
|
||||
|
||||
it ('should clone a FunctionNode', function () {
|
||||
// add(2, 3)
|
||||
var s = new SymbolNode('add');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(3);
|
||||
var d = new FunctionNode(s, [b, c]);
|
||||
|
||||
var e = d.clone();
|
||||
assert(e instanceof FunctionNode);
|
||||
assert.deepEqual(e, d);
|
||||
assert.notStrictEqual(e, d);
|
||||
assert.equal(e.name, d.name);
|
||||
assert.notStrictEqual(e.args, d.args);
|
||||
assert.strictEqual(e.args[0], d.args[0]);
|
||||
assert.strictEqual(e.args[1], d.args[1]);
|
||||
});
|
||||
|
||||
it ('test equality another Node', function () {
|
||||
var a = new FunctionNode(new SymbolNode('add'), [new ConstantNode(2), new ConstantNode(3)]);
|
||||
var b = new FunctionNode(new SymbolNode('add'), [new ConstantNode(2), new ConstantNode(3)]);
|
||||
var c = new FunctionNode(new SymbolNode('subtract'), [new ConstantNode(2), new ConstantNode(3)]);
|
||||
var d = new FunctionNode(new SymbolNode('add'), [new ConstantNode(4), new ConstantNode(3)]);
|
||||
var e = new SymbolNode('add');
|
||||
|
||||
assert.strictEqual(a.equals(null), false);
|
||||
assert.strictEqual(a.equals(undefined), false);
|
||||
assert.strictEqual(a.equals(b), true);
|
||||
assert.strictEqual(a.equals(c), false);
|
||||
assert.strictEqual(a.equals(d), false);
|
||||
assert.strictEqual(a.equals(e), false);
|
||||
});
|
||||
|
||||
it ('should stringify a FunctionNode', function () {
|
||||
var s = new SymbolNode('sqrt');
|
||||
var c = new ConstantNode(4);
|
||||
var n = new FunctionNode(s, [c]);
|
||||
|
||||
assert.equal(n.toString(), 'sqrt(4)');
|
||||
});
|
||||
|
||||
it ('should pass options when stringifying a FunctionNode', function () {
|
||||
var s = new SymbolNode('sqrt');
|
||||
var a = new ConstantNode(2);
|
||||
var b = new SymbolNode('x');
|
||||
var c = new OperatorNode('*', 'multiply', [a, b], true); // implicit
|
||||
var n = new FunctionNode(s, [c]);
|
||||
|
||||
assert.equal(n.toString(), 'sqrt(2 x)');
|
||||
var options = {implicit: 'show'};
|
||||
assert.equal(n.toString(options), 'sqrt(2 * x)');
|
||||
});
|
||||
|
||||
it ('should stringify a FunctionNode with custom toString', function () {
|
||||
//Also checks if the custom functions get passed on to the children
|
||||
var customFunction = function (node, options) {
|
||||
if (node.type === 'FunctionNode') {
|
||||
var string = '[' + node.name + '](';
|
||||
node.args.forEach(function (arg) {
|
||||
string += arg.toString(options) + ', ';
|
||||
});
|
||||
string += ')';
|
||||
return string;
|
||||
}
|
||||
else if (node.type === 'ConstantNode') {
|
||||
return 'const(' + node.value + ', ' + node.valueType + ')'
|
||||
}
|
||||
};
|
||||
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
|
||||
var n1 = new FunctionNode(new SymbolNode('add'), [a, b]);
|
||||
var n2 = new FunctionNode(new SymbolNode('subtract'), [a, b]);
|
||||
|
||||
assert.equal(n1.toString({handler: customFunction}), '[add](const(1, number), const(2, number), )');
|
||||
assert.equal(n2.toString({handler: customFunction}), '[subtract](const(1, number), const(2, number), )');
|
||||
});
|
||||
|
||||
it ('should stringify a FunctionNode with custom toString for a single function', function () {
|
||||
//Also checks if the custom functions get passed on to the children
|
||||
var customFunction = {
|
||||
'add': function (node, options) {
|
||||
return node.args[0].toString(options)
|
||||
+ ' ' + node.name + ' '
|
||||
+ node.args[1].toString(options);
|
||||
}
|
||||
};
|
||||
|
||||
var s = new SymbolNode('add');
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
var n = new FunctionNode(s, [a, b]);
|
||||
|
||||
assert.equal(n.toString({handler: customFunction}), '1 add 2');
|
||||
});
|
||||
|
||||
it ('should LaTeX a FunctionNode', function () {
|
||||
var s = new SymbolNode('sqrt');
|
||||
var c1 = new ConstantNode(4);
|
||||
var c2 = new ConstantNode(5);
|
||||
var n = new FunctionNode(s, [c1]);
|
||||
assert.equal(n.toTex(), '\\sqrt{4}');
|
||||
|
||||
// test permutations
|
||||
var n2 = new FunctionNode(new SymbolNode('permutations'), [c1]);
|
||||
assert.equal(n2.toTex(), '\\mathrm{permutations}\\left(4\\right)');
|
||||
|
||||
var o = new OperatorNode('+', 'add', [c1, c2]);
|
||||
var n3 = new FunctionNode(new SymbolNode('permutations'), [o]);
|
||||
assert.equal(n3.toTex(), '\\mathrm{permutations}\\left(4+5\\right)');
|
||||
});
|
||||
|
||||
it ('should have an identifier', function () {
|
||||
var s = new SymbolNode('factorial');
|
||||
var a = new ConstantNode(2);
|
||||
var n = new FunctionNode(s, [a]);
|
||||
|
||||
assert.equal(n.getIdentifier(), 'FunctionNode:factorial');
|
||||
});
|
||||
|
||||
it ('should LaTeX a FunctionNode with custom toTex', function () {
|
||||
//Also checks if the custom functions get passed on to the children
|
||||
var customFunction = function (node, options) {
|
||||
if (node.type === 'FunctionNode') {
|
||||
var latex = '\\mbox{' + node.name + '}\\left(';
|
||||
node.args.forEach(function (arg) {
|
||||
latex += arg.toTex(options) + ', ';
|
||||
});
|
||||
latex += '\\right)';
|
||||
return latex;
|
||||
}
|
||||
else if (node.type === 'ConstantNode') {
|
||||
return 'const\\left(' + node.value + ', ' + node.valueType + '\\right)'
|
||||
}
|
||||
};
|
||||
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
|
||||
var n1 = new FunctionNode(new SymbolNode('add'), [a, b]);
|
||||
var n2 = new FunctionNode(new SymbolNode('subtract'), [a, b]);
|
||||
|
||||
assert.equal(n1.toTex({handler: customFunction}), '\\mbox{add}\\left(const\\left(1, number\\right), const\\left(2, number\\right), \\right)');
|
||||
assert.equal(n2.toTex({handler: customFunction}), '\\mbox{subtract}\\left(const\\left(1, number\\right), const\\left(2, number\\right), \\right)');
|
||||
});
|
||||
|
||||
it ('should LaTeX a FunctionNode with custom toTex for a single function', function () {
|
||||
//Also checks if the custom functions get passed on to the children
|
||||
var customFunction = {
|
||||
'add': function (node, options) {
|
||||
return node.args[0].toTex(options)
|
||||
+ ' ' + node.name + ' '
|
||||
+ node.args[1].toTex(options);
|
||||
}
|
||||
};
|
||||
|
||||
var s = new SymbolNode('add');
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
var n = new FunctionNode(s, [a, b]);
|
||||
|
||||
assert.equal(n.toTex({handler: customFunction}), '1 add 2');
|
||||
});
|
||||
|
||||
it ('should LaTeX a FunctionNode with callback attached to the function', function () {
|
||||
var customMath = math.create();
|
||||
customMath.add.toTex = function (node, options) {
|
||||
return node.args[0].toTex(options) + ' plus ' + node.args[1].toTex(options);
|
||||
};
|
||||
|
||||
assert.equal(customMath.parse('add(1,2)').toTex(), '1 plus 2');
|
||||
});
|
||||
|
||||
it ('should LaTeX a FunctionNode with template string attached to the function', function () {
|
||||
var customMath = math.create();
|
||||
customMath.add.toTex = '${args[0]} plus ${args[1]}';
|
||||
|
||||
assert.equal(customMath.parse('add(1,2)').toTex(), '1 plus 2');
|
||||
});
|
||||
|
||||
it ('should LaTeX a FunctionNode with object of callbacks attached to the function', function () {
|
||||
var customMath = math.create();
|
||||
customMath.sum.toTex = {
|
||||
2: "${args[0]}+${args[1]}",
|
||||
3: function (node, options) {
|
||||
return node.args[0] + '+' + node.args[1] + '+' + node.args[2];
|
||||
}
|
||||
};
|
||||
|
||||
assert.equal(customMath.parse('sum(1,2)').toTex(), '1+2');
|
||||
assert.equal(customMath.parse('sum(1,2,3)').toTex(), '1+2+3');
|
||||
});
|
||||
|
||||
it ('should LaTeX templates with string properties', function () {
|
||||
var customMath = math.create();
|
||||
customMath.add.toTex = '${name}';
|
||||
|
||||
assert.equal(customMath.parse('add(1,2)').toTex(), 'add');
|
||||
});
|
||||
|
||||
it ('should LaTeX templates with node properties', function () {
|
||||
var customMath = math.create();
|
||||
customMath.add.toTex = '${args[0]} plus ${args[1]}';
|
||||
|
||||
assert.equal(customMath.parse('add(1,2)').toTex(), '1 plus 2');
|
||||
});
|
||||
|
||||
it ('should LaTeX templates with properties that are arrays of Nodes', function () {
|
||||
var customMath = math.create();
|
||||
customMath.add.toTex = '${args}';
|
||||
|
||||
assert.equal(customMath.parse('add(1,2)').toTex(), '1,2');
|
||||
});
|
||||
|
||||
it ('should throw an Error for templates with properties that don\'t exist', function () {
|
||||
var customMath = math.create();
|
||||
customMath.add.toTex = '${some_property}';
|
||||
|
||||
assert.throws(function () {customMath.parse('add(1,2)').toTex()}, ReferenceError);
|
||||
});
|
||||
|
||||
it ('should throw an Error for templates with properties that aren\'t Nodes or Strings or Arrays of Nodes', function () {
|
||||
var customMath = math.create();
|
||||
customMath.add.toTex = '${some_property}';
|
||||
var tree = customMath.parse('add(1,2)');
|
||||
|
||||
tree.some_property = {};
|
||||
assert.throws(function () {tree.toTex()}, TypeError);
|
||||
|
||||
customMath.add.prototype.some_property = 1;
|
||||
tree.some_property = 1;
|
||||
assert.throws(function () {tree.toTex()}, TypeError);
|
||||
});
|
||||
|
||||
it ('should throw an Error for templates with properties that are arrays of non Nodes', function () {
|
||||
var customMath = math.create();
|
||||
customMath.add.toTex = '${some_property}';
|
||||
var tree = customMath.parse('add(1,2)');
|
||||
tree.some_property = [1,2];
|
||||
|
||||
assert.throws(function () {tree.toTex()}, TypeError);
|
||||
});
|
||||
|
||||
});
|
||||
254
nodered/rootfs/data/node_modules/mathjs/test/expression/node/IndexNode.test.js
generated
vendored
Normal file
254
nodered/rootfs/data/node_modules/mathjs/test/expression/node/IndexNode.test.js
generated
vendored
Normal file
@@ -0,0 +1,254 @@
|
||||
// test IndexNode
|
||||
var assert = require('assert');
|
||||
var approx = require('../../../tools/approx');
|
||||
var math = require('../../../index');
|
||||
var Node = math.expression.node.Node;
|
||||
var ConstantNode = math.expression.node.ConstantNode;
|
||||
var SymbolNode = math.expression.node.SymbolNode;
|
||||
var IndexNode = math.expression.node.IndexNode;
|
||||
var RangeNode = math.expression.node.RangeNode;
|
||||
|
||||
describe('IndexNode', function() {
|
||||
|
||||
it ('should create a IndexNode', function () {
|
||||
var n = new IndexNode([]);
|
||||
assert(n instanceof IndexNode);
|
||||
assert(n instanceof Node);
|
||||
assert.equal(n.type, 'IndexNode');
|
||||
});
|
||||
|
||||
it ('should have isIndexNode', function () {
|
||||
var node = new IndexNode([]);
|
||||
assert(node.isIndexNode);
|
||||
});
|
||||
|
||||
it ('should throw an error when calling with wrong arguments', function () {
|
||||
assert.throws(function () {new IndexNode()}, TypeError);
|
||||
assert.throws(function () {new IndexNode('a')}, TypeError);
|
||||
assert.throws(function () {new IndexNode(new Node())}, TypeError);
|
||||
assert.throws(function () {new IndexNode([new Node(), 3])}, TypeError);
|
||||
});
|
||||
|
||||
it ('should throw an error when calling without new operator', function () {
|
||||
assert.throws(function () {IndexNode([])}, SyntaxError);
|
||||
});
|
||||
|
||||
|
||||
it ('should filter an IndexNode', function () {
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(1);
|
||||
var n = new IndexNode([b, c]);
|
||||
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof IndexNode}), [n]);
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof RangeNode}), []);
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof ConstantNode}), [b, c]);
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof ConstantNode && node.value == '2'}), [b]);
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof ConstantNode && node.value == '4'}), []);
|
||||
});
|
||||
|
||||
it ('should filter an empty IndexNode', function () {
|
||||
var n = new IndexNode([]);
|
||||
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof IndexNode}), [n]);
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof ConstantNode}), []);
|
||||
});
|
||||
|
||||
it ('should run forEach on an IndexNode', function () {
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(1);
|
||||
var n = new IndexNode([b, c]);
|
||||
|
||||
var nodes = [];
|
||||
var paths = [];
|
||||
n.forEach(function (node, path, parent) {
|
||||
nodes.push(node);
|
||||
paths.push(path);
|
||||
assert.strictEqual(parent, n);
|
||||
});
|
||||
|
||||
assert.equal(nodes.length, 2);
|
||||
assert.strictEqual(nodes[0], b);
|
||||
assert.strictEqual(nodes[1], c);
|
||||
assert.deepEqual(paths, ['dimensions[0]', 'dimensions[1]']);
|
||||
});
|
||||
|
||||
it ('should map an IndexNode', function () {
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(1);
|
||||
var n = new IndexNode([b, c]);
|
||||
|
||||
var nodes = [];
|
||||
var paths = [];
|
||||
var e = new ConstantNode(-1);
|
||||
var f = n.map(function (node, path, parent) {
|
||||
nodes.push(node);
|
||||
paths.push(path);
|
||||
assert.strictEqual(parent, n);
|
||||
|
||||
return node.isConstantNode && node.value === '1' ? e : node;
|
||||
});
|
||||
|
||||
assert.equal(nodes.length, 2);
|
||||
assert.strictEqual(nodes[0], b);
|
||||
assert.strictEqual(nodes[1], c);
|
||||
assert.deepEqual(paths, ['dimensions[0]', 'dimensions[1]']);
|
||||
|
||||
assert.notStrictEqual(f, n);
|
||||
assert.deepEqual(f.dimensions[0], b);
|
||||
assert.deepEqual(f.dimensions[1], e);
|
||||
});
|
||||
|
||||
it ('should throw an error when the map callback does not return a node', function () {
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(1);
|
||||
var n = new IndexNode([b, c]);
|
||||
|
||||
assert.throws(function () {
|
||||
n.map(function () {});
|
||||
}, /Callback function must return a Node/)
|
||||
});
|
||||
|
||||
it ('should transform an IndexNodes (nested) parameters', function () {
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(1);
|
||||
var n = new IndexNode([b, c]);
|
||||
|
||||
var e = new SymbolNode('c');
|
||||
var f = n.transform(function (node) {
|
||||
return node.isConstantNode && node.value === '1' ? e : node;
|
||||
});
|
||||
|
||||
assert.notStrictEqual(f, n);
|
||||
assert.deepEqual(f.dimensions[0], b);
|
||||
assert.deepEqual(f.dimensions[1], e);
|
||||
});
|
||||
|
||||
it ('should transform an IndexNode itself', function () {
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(1);
|
||||
var n = new IndexNode([b, c]);
|
||||
|
||||
var e = new ConstantNode(5);
|
||||
var f = n.transform(function (node) {
|
||||
return node.isIndexNode ? e : node;
|
||||
});
|
||||
|
||||
assert.notStrictEqual(f, n);
|
||||
assert.deepEqual(f, e);
|
||||
});
|
||||
|
||||
it ('should clone an IndexNode', function () {
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(1);
|
||||
var n = new IndexNode([b, c]);
|
||||
|
||||
var d = n.clone();
|
||||
assert(d.isIndexNode);
|
||||
assert.deepEqual(d, n);
|
||||
assert.notStrictEqual(d, n);
|
||||
assert.notStrictEqual(d.dimensions, n.dimensions);
|
||||
assert.strictEqual(d.dimensions[0], n.dimensions[0]);
|
||||
assert.strictEqual(d.dimensions[1], n.dimensions[1]);
|
||||
});
|
||||
|
||||
it ('test equality another Node', function () {
|
||||
var a = new IndexNode([new ConstantNode(2), new ConstantNode(1)]);
|
||||
var b = new IndexNode([new ConstantNode(2), new ConstantNode(1)]);
|
||||
var c = new IndexNode([new ConstantNode(2)]);
|
||||
var d = new IndexNode([new ConstantNode(2), new ConstantNode(1), new ConstantNode(3)]);
|
||||
var e = new IndexNode([new ConstantNode(2), new ConstantNode(4)]);
|
||||
var f = new SymbolNode('x');
|
||||
|
||||
assert.strictEqual(a.equals(null), false);
|
||||
assert.strictEqual(a.equals(undefined), false);
|
||||
assert.strictEqual(a.equals(b), true);
|
||||
assert.strictEqual(a.equals(c), false);
|
||||
assert.strictEqual(a.equals(d), false);
|
||||
assert.strictEqual(a.equals(e), false);
|
||||
assert.strictEqual(a.equals(f), false);
|
||||
});
|
||||
|
||||
it ('should stringify an IndexNode', function () {
|
||||
var dimensions = [
|
||||
new ConstantNode(2),
|
||||
new ConstantNode(1)
|
||||
];
|
||||
|
||||
var n = new IndexNode(dimensions);
|
||||
assert.equal(n.toString(), '[2, 1]');
|
||||
|
||||
var n2 = new IndexNode([]);
|
||||
assert.equal(n2.toString(), '[]')
|
||||
});
|
||||
|
||||
it ('should stringify an IndexNode with dot notation', function () {
|
||||
var dimensions = [new ConstantNode('a')];
|
||||
|
||||
var n = new IndexNode(dimensions, true);
|
||||
assert.equal(n.toString(), '.a');
|
||||
});
|
||||
|
||||
it ('should stringigy an IndexNode with custom toString', function () {
|
||||
//Also checks if the custom functions get passed on to the children
|
||||
var customFunction = function (node, options) {
|
||||
if (node.type === 'IndexNode') {
|
||||
return node.dimensions.map(function (range) {
|
||||
return range.toString(options);
|
||||
}).join(', ');
|
||||
}
|
||||
else if (node.type === 'ConstantNode') {
|
||||
return 'const(' + node.value + ', ' + node.valueType + ')'
|
||||
}
|
||||
};
|
||||
|
||||
var b = new ConstantNode(1);
|
||||
var c = new ConstantNode(2);
|
||||
|
||||
var n = new IndexNode([b, c]);
|
||||
|
||||
assert.equal(n.toString({handler: customFunction}), 'const(1, number), const(2, number)');
|
||||
});
|
||||
|
||||
it ('should LaTeX an IndexNode', function () {
|
||||
var dimensions = [
|
||||
new ConstantNode(2),
|
||||
new ConstantNode(1)
|
||||
];
|
||||
|
||||
var n = new IndexNode(dimensions);
|
||||
assert.equal(n.toTex(), '_{2,1}');
|
||||
|
||||
var n2 = new IndexNode([]);
|
||||
assert.equal(n2.toTex(), '_{}')
|
||||
});
|
||||
|
||||
it ('should LaTeX an IndexNode with dot notation', function () {
|
||||
var dimensions = [new ConstantNode('a')];
|
||||
|
||||
var n = new IndexNode(dimensions, true);
|
||||
assert.equal(n.toString(), '.a');
|
||||
});
|
||||
|
||||
it ('should LaTeX an IndexNode with custom toTex', function () {
|
||||
//Also checks if the custom functions get passed on to the children
|
||||
var customFunction = function (node, options) {
|
||||
if (node.type === 'IndexNode') {
|
||||
return node.dimensions.map(function (range) {
|
||||
return range.toTex(options);
|
||||
}).join(', ');
|
||||
|
||||
return latex;
|
||||
}
|
||||
else if (node.type === 'ConstantNode') {
|
||||
return 'const\\left(' + node.value + ', ' + node.valueType + '\\right)'
|
||||
}
|
||||
};
|
||||
|
||||
var b = new ConstantNode(1);
|
||||
var c = new ConstantNode(2);
|
||||
var n = new IndexNode([b, c]);
|
||||
|
||||
assert.equal(n.toTex({handler: customFunction}), 'const\\left(1, number\\right), const\\left(2, number\\right)');
|
||||
});
|
||||
|
||||
});
|
||||
174
nodered/rootfs/data/node_modules/mathjs/test/expression/node/Node.test.js
generated
vendored
Normal file
174
nodered/rootfs/data/node_modules/mathjs/test/expression/node/Node.test.js
generated
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
// test Node
|
||||
var assert = require('assert');
|
||||
var approx = require('../../../tools/approx');
|
||||
var math = require('../../../index');
|
||||
var Node = math.expression.node.Node;
|
||||
|
||||
describe('Node', function() {
|
||||
function MyNode (value) {
|
||||
this.value = value;
|
||||
}
|
||||
MyNode.prototype = new Node();
|
||||
MyNode.prototype.forEach = function () {};
|
||||
MyNode.prototype.map = function () {
|
||||
return new MyNode(this.value);
|
||||
};
|
||||
|
||||
it ('should create a Node', function () {
|
||||
var n = new Node();
|
||||
assert(n instanceof Node);
|
||||
});
|
||||
|
||||
it ('should have isNode', function () {
|
||||
var node = new Node();
|
||||
assert(node.isNode);
|
||||
});
|
||||
|
||||
it ('should throw an error when calling without new operator', function () {
|
||||
assert.throws(function () {Node()}, SyntaxError);
|
||||
});
|
||||
|
||||
it ('should filter a Node', function () {
|
||||
var n = new MyNode(2);
|
||||
|
||||
assert.deepEqual(n.filter(function () {return true}), [n]);
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof Node}), [n]);
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof Date}), []);
|
||||
});
|
||||
|
||||
it ('should transform a Node', function () {
|
||||
var a = new MyNode(2);
|
||||
var b = new MyNode(3);
|
||||
var c = a.transform(function (node) {
|
||||
return b;
|
||||
});
|
||||
assert.deepEqual(c, b);
|
||||
|
||||
// no match
|
||||
a = new MyNode(2);
|
||||
b = new MyNode(3);
|
||||
c = a.transform(function (node) {
|
||||
return node;
|
||||
});
|
||||
assert.deepEqual(c, a);
|
||||
});
|
||||
|
||||
it ('should transform a Node using a replacement function', function () {
|
||||
var a = new MyNode(2);
|
||||
var b = new MyNode(3);
|
||||
var c = a.transform(function (node) {
|
||||
assert.deepEqual(node, a);
|
||||
return b;
|
||||
});
|
||||
assert.deepEqual(c, b);
|
||||
});
|
||||
|
||||
it ('should throw an error when cloning a Node interface', function () {
|
||||
assert.throws(function () {
|
||||
var a = new Node();
|
||||
a.clone();
|
||||
}, /Cannot clone a Node interface/);
|
||||
});
|
||||
|
||||
it ('should shallow clone the content of a Node', function () {
|
||||
var a = new math.expression.node.ConstantNode(1);
|
||||
var b = new math.expression.node.ConstantNode(2);
|
||||
var c = new math.expression.node.OperatorNode('+', 'add', [a, b]);
|
||||
|
||||
var clone = c.clone();
|
||||
|
||||
assert.deepEqual(c, clone);
|
||||
assert.notStrictEqual(c, clone);
|
||||
assert.strictEqual(clone.args[0], c.args[0]);
|
||||
assert.strictEqual(clone.args[1], c.args[1]);
|
||||
});
|
||||
|
||||
it ('should deepClone the content of a Node', function () {
|
||||
var a = new math.expression.node.ConstantNode(1);
|
||||
var b = new math.expression.node.ConstantNode(2);
|
||||
var c = new math.expression.node.OperatorNode('+', 'add', [a, b]);
|
||||
|
||||
var clone = c.cloneDeep();
|
||||
|
||||
assert.deepEqual(c, clone);
|
||||
assert.notStrictEqual(c, clone);
|
||||
assert.notStrictEqual(clone.args[0], c.args[0]);
|
||||
assert.notStrictEqual(clone.args[1], c.args[1]);
|
||||
});
|
||||
|
||||
it ('test equality with another Node', function () {
|
||||
assert.strictEqual(new Node().equals(new Node()), true);
|
||||
assert.strictEqual(new Node().equals(null), false);
|
||||
assert.strictEqual(new Node().equals(undefined), false);
|
||||
assert.strictEqual(new Node().equals({}), false);
|
||||
});
|
||||
|
||||
it ('should throw an error when stringifying a Node interface', function () {
|
||||
assert.throws(function () {
|
||||
var node = new Node();
|
||||
node.toString();
|
||||
}, /_toString not implemented for Node/);
|
||||
});
|
||||
|
||||
it ('should throw an error when calling _toTex', function () {
|
||||
assert.throws(function () {
|
||||
var node = new Node();
|
||||
node._toTex();
|
||||
}, /_toTex not implemented for Node/);
|
||||
});
|
||||
|
||||
it ('should ignore custom toString if it returns nothing', function () {
|
||||
var callback1 = function (node, callback) {};
|
||||
var callback2 = {
|
||||
bla: function (node, callbacks) {}
|
||||
};
|
||||
var mymath = math.create();
|
||||
mymath.expression.node.Node.prototype._toString = function () {
|
||||
return 'default';
|
||||
};
|
||||
var n1 = new mymath.expression.node.Node();
|
||||
var s = new mymath.expression.node.SymbolNode('bla');
|
||||
var n2 = new mymath.expression.node.FunctionNode(s, []);
|
||||
|
||||
assert.equal(n1.toString(callback1), 'default');
|
||||
assert.equal(n2.toString(callback2), 'bla()');
|
||||
});
|
||||
|
||||
|
||||
it ('should ignore custom toTex if it returns nothing', function () {
|
||||
var callback1 = function (node, callback) {};
|
||||
var callback2 = {
|
||||
bla: function (node, callbacks) {}
|
||||
};
|
||||
var mymath = math.create();
|
||||
mymath.expression.node.Node.prototype._toTex = function () {
|
||||
return 'default';
|
||||
};
|
||||
var n1 = new mymath.expression.node.Node();
|
||||
var s = new mymath.expression.node.SymbolNode('bla');
|
||||
var n2 = new mymath.expression.node.FunctionNode(s, []);
|
||||
|
||||
assert.equal(n1.toTex(callback1), 'default');
|
||||
assert.equal(n2.toTex(callback2), '\\mathrm{bla}\\left(\\right)');
|
||||
});
|
||||
|
||||
it ('should throw an error when compiling an abstract node', function () {
|
||||
var node = new Node();
|
||||
assert.throws(function () {
|
||||
node.compile()
|
||||
}, /Cannot compile a Node interface/);
|
||||
});
|
||||
|
||||
it ('should have an identifier', function () {
|
||||
var node = new Node();
|
||||
|
||||
assert.equal(node.getIdentifier(), 'Node');
|
||||
});
|
||||
|
||||
it ('should get the content of a Node', function () {
|
||||
var c = new math.expression.node.ConstantNode(1);
|
||||
|
||||
assert.equal(c.getContent(), c);
|
||||
assert.deepEqual(c.getContent(), c);
|
||||
});
|
||||
});
|
||||
285
nodered/rootfs/data/node_modules/mathjs/test/expression/node/ObjectNode.test.js
generated
vendored
Normal file
285
nodered/rootfs/data/node_modules/mathjs/test/expression/node/ObjectNode.test.js
generated
vendored
Normal file
@@ -0,0 +1,285 @@
|
||||
// test ObjectNode
|
||||
var assert = require('assert');
|
||||
var approx = require('../../../tools/approx');
|
||||
var math = require('../../../index');
|
||||
var Node = math.expression.node.Node;
|
||||
var ConstantNode = math.expression.node.ConstantNode;
|
||||
var SymbolNode = math.expression.node.SymbolNode;
|
||||
var RangeNode = math.expression.node.RangeNode;
|
||||
var ObjectNode = math.expression.node.ObjectNode;
|
||||
|
||||
// FIXME: a lot of tests depend on order of object keys, whilst the order is officially undeterministic
|
||||
|
||||
describe('ObjectNode', function() {
|
||||
|
||||
it ('should create an ObjectNode', function () {
|
||||
var c = new ConstantNode(1);
|
||||
var a = new ObjectNode({c: c});
|
||||
var b = new ObjectNode();
|
||||
assert(a instanceof ObjectNode);
|
||||
assert(b instanceof ObjectNode);
|
||||
assert.equal(a.type, 'ObjectNode');
|
||||
assert.equal(b.type, 'ObjectNode');
|
||||
});
|
||||
|
||||
it ('should have isObjectNode', function () {
|
||||
var node = new ObjectNode({});
|
||||
|
||||
assert(node.isObjectNode);
|
||||
});
|
||||
|
||||
it ('should throw an error when calling without new operator', function () {
|
||||
assert.throws(function () {ObjectNode()}, SyntaxError);
|
||||
});
|
||||
|
||||
it ('should throw an error on wrong constructor arguments', function () {
|
||||
assert.throws(function () {new ObjectNode(2)}, TypeError);
|
||||
assert.throws(function () {new ObjectNode({a: 2, b: 3})}, TypeError);
|
||||
});
|
||||
|
||||
it ('should evaluate an ObjectNode', function () {
|
||||
var c = new ConstantNode(1);
|
||||
var a = new ObjectNode({c: c});
|
||||
var b = new ObjectNode();
|
||||
|
||||
assert.deepEqual(a.compile().eval(), {c: 1});
|
||||
assert.deepEqual(b.compile().eval(), {});
|
||||
});
|
||||
|
||||
it ('should compile nested ObjectNodes', function () {
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(3);
|
||||
var d = new ConstantNode(4);
|
||||
|
||||
var n2 = new ObjectNode({a: a, b: b});
|
||||
var n3 = new ObjectNode({c: c, d: d});
|
||||
var n4 = new ObjectNode({n2: n2, n3: n3});
|
||||
|
||||
var expr = n4.compile();
|
||||
assert.deepEqual(expr.eval(), {n2: {a: 1, b: 2}, n3: {c: 3, d: 4}});
|
||||
});
|
||||
|
||||
it ('should filter an ObjectNode', function () {
|
||||
var a = new ConstantNode(1);
|
||||
var b = new SymbolNode('x');
|
||||
var c = new ConstantNode(2);
|
||||
var d = new ObjectNode({a: a, b: b, c: c});
|
||||
|
||||
assert.deepEqual(d.filter(function (node) {return node instanceof ObjectNode}), [d]);
|
||||
assert.deepEqual(d.filter(function (node) {return node instanceof SymbolNode}), [b]);
|
||||
assert.deepEqual(d.filter(function (node) {return node instanceof RangeNode}), []);
|
||||
assert.deepEqual(d.filter(function (node) {return node instanceof ConstantNode}), [a, c]);
|
||||
assert.deepEqual(d.filter(function (node) {return node instanceof ConstantNode && node.value == '2'}), [c]);
|
||||
});
|
||||
|
||||
it ('should run forEach on an ObjectNode', function () {
|
||||
var a = new SymbolNode('x');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ObjectNode({a: a, b: b});
|
||||
|
||||
var nodes = [];
|
||||
var paths = [];
|
||||
c.forEach(function (node, path, parent) {
|
||||
nodes.push(node);
|
||||
paths.push(path);
|
||||
assert.strictEqual(parent, c);
|
||||
});
|
||||
|
||||
assert.deepEqual(paths, ['properties["a"]', 'properties["b"]']);
|
||||
assert.equal(nodes.length, 2);
|
||||
assert.strictEqual(nodes[0], a);
|
||||
assert.strictEqual(nodes[1], b);
|
||||
});
|
||||
|
||||
it ('should map an ObjectNode', function () {
|
||||
var a = new SymbolNode('x');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ObjectNode({a: a, b: b});
|
||||
|
||||
var d = new ConstantNode(3);
|
||||
var nodes = [];
|
||||
var paths = [];
|
||||
var e = c.map(function (node, path, parent) {
|
||||
nodes.push(node);
|
||||
paths.push(path);
|
||||
assert.strictEqual(parent, c);
|
||||
|
||||
return (node instanceof SymbolNode) && (node.name == 'x') ? d : node;
|
||||
});
|
||||
|
||||
assert.deepEqual(paths, ['properties["a"]', 'properties["b"]']);
|
||||
assert.equal(nodes.length, 2);
|
||||
assert.strictEqual(nodes[0], a);
|
||||
assert.strictEqual(nodes[1], b);
|
||||
|
||||
assert.notStrictEqual(e, c);
|
||||
assert.deepEqual(e.properties["a"], d);
|
||||
assert.deepEqual(e.properties["b"], b);
|
||||
});
|
||||
|
||||
it ('should throw an error when the map callback does not return a node', function () {
|
||||
var a = new SymbolNode('x');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ObjectNode({a: a, b: b});
|
||||
|
||||
assert.throws(function () {
|
||||
c.map(function () {});
|
||||
}, /Callback function must return a Node/)
|
||||
});
|
||||
|
||||
it ('should transform an ObjectNodes parameters', function () {
|
||||
var a = new SymbolNode('x');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ObjectNode({a: a, b: b});
|
||||
|
||||
var d = new ConstantNode(3);
|
||||
var e = c.transform(function (node) {
|
||||
return (node instanceof SymbolNode) && (node.name == 'x') ? d : node;
|
||||
});
|
||||
|
||||
assert.notStrictEqual(e, c);
|
||||
assert.deepEqual(e.properties["a"], d);
|
||||
assert.deepEqual(e.properties["b"], b);
|
||||
});
|
||||
|
||||
it ('should transform an ObjectNode itself', function () {
|
||||
var a = new SymbolNode('x');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ObjectNode({a: a, b: b});
|
||||
|
||||
var d = new ConstantNode(3);
|
||||
var e = c.transform(function (node) {
|
||||
return (node instanceof ObjectNode) ? d : node;
|
||||
});
|
||||
|
||||
assert.notStrictEqual(e, c);
|
||||
assert.deepEqual(e, d);
|
||||
});
|
||||
|
||||
it ('should traverse an ObjectNode', function () {
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(3);
|
||||
var d = new ObjectNode({a: a, b: b});
|
||||
var e = new ObjectNode({c: c, d: d});
|
||||
|
||||
var count = 0;
|
||||
e.traverse(function (node, path, parent) {
|
||||
count++;
|
||||
|
||||
switch(count) {
|
||||
case 1:
|
||||
assert.strictEqual(path, null);
|
||||
assert.strictEqual(node, e);
|
||||
assert.strictEqual(parent, null);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
assert.strictEqual(path, 'properties["c"]');
|
||||
assert.strictEqual(node, c);
|
||||
assert.strictEqual(parent, e);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
assert.strictEqual(path, 'properties["d"]');
|
||||
assert.strictEqual(node, d);
|
||||
assert.strictEqual(parent, e);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
assert.strictEqual(path, 'properties["a"]');
|
||||
assert.strictEqual(node, a);
|
||||
assert.strictEqual(parent, d);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
assert.strictEqual(path, 'properties["b"]');
|
||||
assert.strictEqual(node, b);
|
||||
assert.strictEqual(parent, d);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
assert.equal(count, 5);
|
||||
});
|
||||
|
||||
it ('should clone an ObjectNode', function () {
|
||||
var a = new SymbolNode('x');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ObjectNode({a: a, b: b});
|
||||
|
||||
var d = c.clone();
|
||||
assert(d instanceof ObjectNode);
|
||||
assert.deepEqual(c, d);
|
||||
assert.notStrictEqual(c, d);
|
||||
assert.strictEqual(c.properties["a"], d.properties["a"]);
|
||||
assert.strictEqual(c.properties["b"], d.properties["b"]);
|
||||
});
|
||||
|
||||
it ('test equality another Node', function () {
|
||||
var a = new ObjectNode({a: new SymbolNode('a'), b: new ConstantNode(2)});
|
||||
var b = new ObjectNode({a: new SymbolNode('a'), b: new ConstantNode(2)});
|
||||
var c = new ObjectNode({a: new SymbolNode('a'), b: new ConstantNode(2), c: new ConstantNode(3)});
|
||||
var d = new ObjectNode({a: new SymbolNode('foo'), b: new ConstantNode(2)});
|
||||
var e = new ObjectNode({a: new SymbolNode('a')});
|
||||
var f = new SymbolNode('x');
|
||||
|
||||
assert.strictEqual(a.equals(null), false);
|
||||
assert.strictEqual(a.equals(undefined), false);
|
||||
assert.strictEqual(a.equals(b), true);
|
||||
assert.strictEqual(a.equals(c), false);
|
||||
assert.strictEqual(a.equals(d), false);
|
||||
assert.strictEqual(a.equals(e), false);
|
||||
assert.strictEqual(a.equals(f), false);
|
||||
});
|
||||
|
||||
it ('should stringify an ObjectNode', function () {
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(3);
|
||||
var n1 = new ObjectNode({a: a, b: b});
|
||||
var n2 = new ObjectNode({c: c, n1: n1});
|
||||
|
||||
assert.equal(n2.toString(), '{"c": 3, "n1": {"a": 1, "b": 2}}');
|
||||
});
|
||||
|
||||
it ('should stringify an ObjectNode with custom toString', function () {
|
||||
var customFunction = function (node, options) {
|
||||
if (node.type === 'ConstantNode') {
|
||||
return 'const(' + node.value + ', ' + node.valueType + ')'
|
||||
}
|
||||
};
|
||||
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
var n = new ObjectNode({a: a, b: b});
|
||||
|
||||
assert.equal(n.toString({handler: customFunction}), '{"a": const(1, number), "b": const(2, number)}');
|
||||
});
|
||||
|
||||
it ('should LaTeX an ObjectNode', function () {
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(3);
|
||||
var n1 = new ObjectNode({a: a, b: b});
|
||||
var n2 = new ObjectNode({c: c, n1: n1});
|
||||
|
||||
assert.equal(n2.toTex(), '\\left\\{\\begin{array}{ll}\\mathbf{c:} & 3\\\\\n\\mathbf{n1:} & \\left\\{\\begin{array}{ll}\\mathbf{a:} & 1\\\\\n\\mathbf{b:} & 2\\\\\\end{array}\\right\\}\\\\\\end{array}\\right\\}')
|
||||
});
|
||||
|
||||
it ('should LaTeX an ObjectNode with custom toTex', function () {
|
||||
var customFunction = function (node, options) {
|
||||
if (node.type === 'ConstantNode') {
|
||||
return 'const\\left(' + node.value + ', ' + node.valueType + '\\right)'
|
||||
}
|
||||
};
|
||||
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
var n = new ObjectNode({a: a, b: b});
|
||||
|
||||
assert.equal(n.toTex({handler: customFunction}), '\\left\\{\\begin{array}{ll}\\mathbf{a:} & const\\left(1, number\\right)\\\\\n\\mathbf{b:} & const\\left(2, number\\right)\\\\\\end{array}\\right\\}');
|
||||
});
|
||||
|
||||
});
|
||||
727
nodered/rootfs/data/node_modules/mathjs/test/expression/node/OperatorNode.test.js
generated
vendored
Normal file
727
nodered/rootfs/data/node_modules/mathjs/test/expression/node/OperatorNode.test.js
generated
vendored
Normal file
@@ -0,0 +1,727 @@
|
||||
// test OperatorNode
|
||||
var assert = require('assert');
|
||||
var approx = require('../../../tools/approx');
|
||||
var math = require('../../../index');
|
||||
var Node = math.expression.node.Node;
|
||||
var ConstantNode = math.expression.node.ConstantNode;
|
||||
var SymbolNode = math.expression.node.SymbolNode;
|
||||
var OperatorNode = math.expression.node.OperatorNode;
|
||||
var ConditionalNode = math.expression.node.ConditionalNode;
|
||||
|
||||
describe('OperatorNode', function() {
|
||||
|
||||
it ('should create an OperatorNode', function () {
|
||||
var n = new OperatorNode('op', 'fn', []);
|
||||
assert(n instanceof OperatorNode);
|
||||
assert(n instanceof Node);
|
||||
assert.equal(n.type, 'OperatorNode');
|
||||
});
|
||||
|
||||
it ('should have isOperatorNode', function () {
|
||||
var node = new OperatorNode('op', 'fn', []);
|
||||
assert(node.isOperatorNode);
|
||||
});
|
||||
|
||||
it ('should throw an error when calling without new operator', function () {
|
||||
var a = new ConstantNode(2);
|
||||
var b = new ConstantNode(3);
|
||||
assert.throws(function () {OperatorNode('+', 'add', [a, b])}, SyntaxError);
|
||||
});
|
||||
|
||||
it ('should compile an OperatorNode', function () {
|
||||
var a = new ConstantNode(2);
|
||||
var b = new ConstantNode(3);
|
||||
var n = new OperatorNode('+', 'add', [a, b]);
|
||||
|
||||
var expr = n.compile();
|
||||
|
||||
assert.equal(expr.eval(), 5);
|
||||
});
|
||||
|
||||
it ('should throw an error in case of unresolved operator function', function () {
|
||||
var a = new ConstantNode(2);
|
||||
var b = new ConstantNode(3);
|
||||
var n = new OperatorNode('***', 'foo', [a, b]);
|
||||
|
||||
assert.throws(function () {
|
||||
n.compile();
|
||||
}, /Function foo missing in provided namespace/);
|
||||
});
|
||||
|
||||
it ('should filter an OperatorNode', function () {
|
||||
var a = new ConstantNode(2);
|
||||
var b = new ConstantNode(3);
|
||||
var n = new OperatorNode('+', 'add', [a, b]);
|
||||
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof OperatorNode}), [n]);
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof SymbolNode}), []);
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof ConstantNode}), [a, b]);
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof ConstantNode && node.value == '2'}), [a]);
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof ConstantNode && node.value == '4'}), []);
|
||||
});
|
||||
|
||||
it ('should filter an OperatorNode without contents', function () {
|
||||
var n = new OperatorNode('op', 'fn', []);
|
||||
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof OperatorNode}), [n]);
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof SymbolNode}), []);
|
||||
});
|
||||
|
||||
it ('should run forEach on an OperatorNode', function () {
|
||||
// x^2-x
|
||||
var a = new SymbolNode('x');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new OperatorNode('^', 'pow', [a, b]);
|
||||
var d = new SymbolNode('x');
|
||||
var e = new OperatorNode('-', 'subtract', [c, d]);
|
||||
|
||||
var nodes = [];
|
||||
var paths = [];
|
||||
e.forEach(function (node, path, parent) {
|
||||
nodes.push(node);
|
||||
paths.push(path);
|
||||
assert.strictEqual(parent, e);
|
||||
});
|
||||
|
||||
assert.equal(nodes.length, 2);
|
||||
assert.strictEqual(nodes[0], c);
|
||||
assert.strictEqual(nodes[1], d);
|
||||
assert.deepEqual(paths, ['args[0]', 'args[1]']);
|
||||
});
|
||||
|
||||
it ('should map an OperatorNode', function () {
|
||||
// x^2-x
|
||||
var a = new SymbolNode('x');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new OperatorNode('^', 'pow', [a, b]);
|
||||
var d = new SymbolNode('x');
|
||||
var e = new OperatorNode('-', 'subtract', [c, d]);
|
||||
|
||||
var nodes = [];
|
||||
var paths = [];
|
||||
var f = new ConstantNode(3);
|
||||
var g = e.map(function (node, path, parent) {
|
||||
nodes.push(node);
|
||||
paths.push(path);
|
||||
assert.strictEqual(parent, e);
|
||||
|
||||
return node instanceof SymbolNode && node.name == 'x' ? f : node;
|
||||
});
|
||||
|
||||
assert.equal(nodes.length, 2);
|
||||
assert.strictEqual(nodes[0], c);
|
||||
assert.strictEqual(nodes[1], d);
|
||||
assert.deepEqual(paths, ['args[0]', 'args[1]']);
|
||||
|
||||
assert.notStrictEqual(g, e);
|
||||
assert.strictEqual(g.args[0], e.args[0]);
|
||||
assert.strictEqual(g.args[0].args[0], a); // nested x is not replaced
|
||||
assert.deepEqual(g.args[0].args[1], b);
|
||||
assert.deepEqual(g.args[1], f);
|
||||
});
|
||||
|
||||
it ('should throw an error when the map callback does not return a node', function () {
|
||||
var a = new SymbolNode('x');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new OperatorNode('^', 'pow', [a, b]);
|
||||
|
||||
assert.throws(function () {
|
||||
c.map(function () {});
|
||||
}, /Callback function must return a Node/)
|
||||
});
|
||||
|
||||
it ('should transform an OperatorNodes parameters', function () {
|
||||
// x^2-x
|
||||
var a = new SymbolNode('x');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new OperatorNode('^', 'pow', [a, b]);
|
||||
var d = new SymbolNode('x');
|
||||
var e = new OperatorNode('-', 'subtract', [c, d]);
|
||||
|
||||
var f = new ConstantNode(3);
|
||||
var g = e.transform(function (node) {
|
||||
return node instanceof SymbolNode && node.name == 'x' ? f : node;
|
||||
});
|
||||
|
||||
assert.deepEqual(g.args[1], f);
|
||||
});
|
||||
|
||||
it ('should transform an OperatorNode itself', function () {
|
||||
// x^2-x
|
||||
var a = new SymbolNode('x');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new OperatorNode('+', 'add', [a, b]);
|
||||
|
||||
var f = new ConstantNode(3);
|
||||
var g = c.transform(function (node) {
|
||||
return node instanceof OperatorNode ? f : node;
|
||||
});
|
||||
|
||||
assert.notStrictEqual(g, c);
|
||||
assert.deepEqual(g, f);
|
||||
});
|
||||
|
||||
it ('should clone an OperatorNode', function () {
|
||||
// x^2-x
|
||||
var a = new SymbolNode('x');
|
||||
var b = new ConstantNode(2);
|
||||
var c = new OperatorNode('+', 'add', [a, b]);
|
||||
|
||||
var d = c.clone();
|
||||
assert(d instanceof OperatorNode);
|
||||
assert.deepEqual(d, c);
|
||||
assert.notStrictEqual(d, c);
|
||||
assert.notStrictEqual(d.args, c.args);
|
||||
assert.strictEqual(d.args[0], c.args[0]);
|
||||
assert.strictEqual(d.args[1], c.args[1]);
|
||||
});
|
||||
|
||||
it ('should clone implicit multiplications', function () {
|
||||
var two = new ConstantNode(2);
|
||||
var x = new SymbolNode('x');
|
||||
var node = new OperatorNode('*', 'multiply', [two, x], true);
|
||||
|
||||
assert.equal('2 x', node.toString());
|
||||
assert.strictEqual(true, node.clone().implicit);
|
||||
assert.equal(node.toString(), node.clone().toString());
|
||||
});
|
||||
|
||||
it ('test equality another Node', function () {
|
||||
var a = new OperatorNode('+', 'add', [new SymbolNode('x'), new ConstantNode(2)]);
|
||||
var b = new OperatorNode('+', 'add', [new SymbolNode('x'), new ConstantNode(2)]);
|
||||
var c = new OperatorNode('*', 'multiply', [new SymbolNode('x'), new ConstantNode(2)]);
|
||||
var d = new OperatorNode('*', 'add', [new SymbolNode('x'), new ConstantNode(3)]);
|
||||
var e = new OperatorNode('*', 'add', [new SymbolNode('x'), new ConstantNode(2), new ConstantNode(4)]);
|
||||
|
||||
assert.strictEqual(a.equals(null), false);
|
||||
assert.strictEqual(a.equals(undefined), false);
|
||||
assert.strictEqual(a.equals(b), true);
|
||||
assert.strictEqual(a.equals(c), false);
|
||||
assert.strictEqual(a.equals(d), false);
|
||||
assert.strictEqual(a.equals(e), false);
|
||||
});
|
||||
|
||||
describe('toString', function () {
|
||||
it ('should stringify an OperatorNode', function () {
|
||||
var a = new ConstantNode(2);
|
||||
var b = new ConstantNode(3);
|
||||
var c = new ConstantNode(4);
|
||||
|
||||
var n = new OperatorNode('+', 'add', [a, b]);
|
||||
assert.equal(n.toString(), '2 + 3');
|
||||
});
|
||||
|
||||
it ('should stringify an OperatorNode with factorial', function () {
|
||||
var a = new ConstantNode(2);
|
||||
var n = new OperatorNode('!', 'factorial', [a]);
|
||||
assert.equal(n.toString(), '2!');
|
||||
});
|
||||
|
||||
it ('should stringify an OperatorNode with unary minus', function () {
|
||||
var a = new ConstantNode(2);
|
||||
var n = new OperatorNode('-', 'unaryMinus', [a]);
|
||||
assert.equal(n.toString(), '-2');
|
||||
});
|
||||
|
||||
it ('should stringify an OperatorNode with zero arguments', function () {
|
||||
var n = new OperatorNode('foo', 'foo', []);
|
||||
assert.equal(n.toString(), 'foo()');
|
||||
});
|
||||
|
||||
it ('should stringify an OperatorNode with more than two operators', function () {
|
||||
var a = new ConstantNode(2);
|
||||
var b = new ConstantNode(3);
|
||||
var c = new ConstantNode(4);
|
||||
|
||||
var n = new OperatorNode('foo', 'foo', [a, b, c]);
|
||||
assert.equal(n.toString(), 'foo(2, 3, 4)');
|
||||
|
||||
});
|
||||
|
||||
it ('should stringify addition and multiplication with more than two operands', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var b = new SymbolNode('b');
|
||||
var c = new SymbolNode('c');
|
||||
|
||||
var add = new OperatorNode('+', 'add', [a, b, c]);
|
||||
var multiply = new OperatorNode('*', 'multiply', [a, b, c]);
|
||||
var implicitMultiply = new OperatorNode('*', 'multiply', [a, b, c], true);
|
||||
|
||||
assert.equal(add.toString(), 'a + b + c');
|
||||
assert.equal(multiply.toString(), 'a * b * c');
|
||||
assert.equal(implicitMultiply.toString(), 'a b c');
|
||||
});
|
||||
|
||||
it ('should stringify addition and multiplication with more than two operands including OperatorNode', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var b = new SymbolNode('b');
|
||||
var c = new SymbolNode('c');
|
||||
var d = new SymbolNode('d');
|
||||
|
||||
var mult = new OperatorNode('*', 'multiply', [a,b]);
|
||||
var add = new OperatorNode('+', 'add', [a, b]);
|
||||
|
||||
var multipleMultWithMult = new OperatorNode('*', 'multiply', [c, mult, d]);
|
||||
var multipleMultWithAdd = new OperatorNode('*', 'multiply', [c, add, d]);
|
||||
var multipleAddWithMult = new OperatorNode('+', 'add', [c, mult, d]);
|
||||
var multipleAddWithAdd = new OperatorNode('+', 'add', [c, add, d]);
|
||||
|
||||
assert.equal(multipleMultWithMult.toString(), 'c * a * b * d');
|
||||
assert.equal(multipleMultWithAdd.toString(), 'c * (a + b) * d');
|
||||
assert.equal(multipleAddWithMult.toString(), 'c + a * b + d');
|
||||
assert.equal(multipleAddWithAdd.toString(), 'c + a + b + d');
|
||||
});
|
||||
|
||||
it ('should stringify an OperatorNode that contains an operatornode with more than two operands', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var b = new SymbolNode('b');
|
||||
var c = new SymbolNode('c');
|
||||
var d = new SymbolNode('d');
|
||||
|
||||
var mult = new OperatorNode('*', 'multiply', [a, b, c]);
|
||||
var add = new OperatorNode('+', 'add', [a, b, c]);
|
||||
|
||||
var addWithMult = new OperatorNode('+', 'add', [mult, d]);
|
||||
var addWithAdd = new OperatorNode('+', 'add', [add, d]);
|
||||
var multWithMult = new OperatorNode('*', 'multiply', [mult, d]);
|
||||
var multWithAdd = new OperatorNode('*', 'multiply', [add, d]);
|
||||
|
||||
assert.equal(addWithMult.toString(), 'a * b * c + d');
|
||||
assert.equal(addWithAdd.toString(), 'a + b + c + d');
|
||||
assert.equal(multWithMult.toString(), 'a * b * c * d');
|
||||
assert.equal(multWithAdd.toString(), '(a + b + c) * d');
|
||||
|
||||
});
|
||||
|
||||
it ('should stringify an OperatorNode with nested operator nodes', function () {
|
||||
var a = new ConstantNode(2);
|
||||
var b = new ConstantNode(3);
|
||||
var c = new ConstantNode(4);
|
||||
var d = new ConstantNode(5);
|
||||
|
||||
var n1 = new OperatorNode('+', 'add', [a, b]);
|
||||
var n2 = new OperatorNode('-', 'subtract', [c, d]);
|
||||
var n3 = new OperatorNode('*', 'multiply', [n1, n2]);
|
||||
|
||||
assert.equal(n1.toString(), '2 + 3');
|
||||
assert.equal(n2.toString(), '4 - 5');
|
||||
assert.equal(n3.toString(), '(2 + 3) * (4 - 5)');
|
||||
});
|
||||
|
||||
it ('should stringify left associative OperatorNodes that are associative with another Node', function () {
|
||||
assert.equal(math.parse('(a+b)+c').toString({parenthesis: 'auto'}), 'a + b + c');
|
||||
assert.equal(math.parse('a+(b+c)').toString({parenthesis: 'auto'}), 'a + b + c');
|
||||
assert.equal(math.parse('(a+b)-c').toString({parenthesis: 'auto'}), 'a + b - c');
|
||||
assert.equal(math.parse('a+(b-c)').toString({parenthesis: 'auto'}), 'a + b - c');
|
||||
|
||||
assert.equal(math.parse('(a*b)*c').toString({parenthesis: 'auto'}), 'a * b * c');
|
||||
assert.equal(math.parse('a*(b*c)').toString({parenthesis: 'auto'}), 'a * b * c');
|
||||
assert.equal(math.parse('(a*b)/c').toString({parenthesis: 'auto'}), 'a * b / c');
|
||||
assert.equal(math.parse('a*(b/c)').toString({parenthesis: 'auto'}), 'a * b / c');
|
||||
});
|
||||
|
||||
it ('should stringify left associative OperatorNodes that are not associative with another Node', function () {
|
||||
assert.equal(math.parse('(a-b)-c').toString({parenthesis: 'auto'}), 'a - b - c');
|
||||
assert.equal(math.parse('a-(b-c)').toString({parenthesis: 'auto'}), 'a - (b - c)');
|
||||
assert.equal(math.parse('(a-b)+c').toString({parenthesis: 'auto'}), 'a - b + c');
|
||||
assert.equal(math.parse('a-(b+c)').toString({parenthesis: 'auto'}), 'a - (b + c)');
|
||||
|
||||
assert.equal(math.parse('(a/b)/c').toString({parenthesis: 'auto'}), 'a / b / c');
|
||||
assert.equal(math.parse('a/(b/c)').toString({parenthesis: 'auto'}), 'a / (b / c)');
|
||||
assert.equal(math.parse('(a/b)*c').toString({parenthesis: 'auto'}), 'a / b * c');
|
||||
assert.equal(math.parse('a/(b*c)').toString({parenthesis: 'auto'}), 'a / (b * c)');
|
||||
});
|
||||
|
||||
it ('should stringify right associative OperatorNodes that are not associative with another Node', function () {
|
||||
assert.equal(math.parse('(a^b)^c').toString({parenthesis: 'auto'}), '(a ^ b) ^ c');
|
||||
assert.equal(math.parse('a^(b^c)').toString({parenthesis: 'auto'}), 'a ^ b ^ c');
|
||||
});
|
||||
|
||||
it ('should stringify unary OperatorNodes containing a binary OperatorNode', function () {
|
||||
assert.equal(math.parse('(a*b)!').toString(), '(a * b)!');
|
||||
assert.equal(math.parse('-(a*b)').toString(), '-(a * b)');
|
||||
assert.equal(math.parse('-(a+b)').toString(), '-(a + b)');
|
||||
});
|
||||
|
||||
it ('should stringify unary OperatorNodes containing a unary OperatorNode', function () {
|
||||
assert.equal(math.parse('(-a)!').toString({parenthesis: 'auto'}), '(-a)!');
|
||||
assert.equal(math.parse('-(a!)').toString({parenthesis: 'auto'}), '-a!');
|
||||
assert.equal(math.parse('-(-a)').toString({parenthesis: 'auto'}), '-(-a)');
|
||||
});
|
||||
});
|
||||
|
||||
it ('should stringify an OperatorNode with custom toString', function () {
|
||||
//Also checks if the custom functions get passed on to the children
|
||||
var customFunction = function (node, options) {
|
||||
if (node.type === 'OperatorNode') {
|
||||
return node.op + node.fn + '('
|
||||
+ node.args[0].toString(options)
|
||||
+ ', ' + node.args[1].toString(options) + ')';
|
||||
}
|
||||
else if (node.type === 'ConstantNode') {
|
||||
return 'const(' + node.value + ', ' + node.valueType + ')'
|
||||
}
|
||||
};
|
||||
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
|
||||
var n1 = new OperatorNode('+', 'add', [a, b]);
|
||||
var n2 = new OperatorNode('-', 'subtract', [a, b]);
|
||||
|
||||
assert.equal(n1.toString({handler: customFunction}), '+add(const(1, number), const(2, number))');
|
||||
assert.equal(n2.toString({handler: customFunction}), '-subtract(const(1, number), const(2, number))');
|
||||
});
|
||||
|
||||
it ('should stringify an OperatorNode with custom toString for a single operator', function () {
|
||||
//Also checks if the custom functions get passed on to the children
|
||||
var customFunction = function (node, options) {
|
||||
if ((node.type === 'OperatorNode') && (node.fn === 'add')) {
|
||||
return node.args[0].toString(options)
|
||||
+ node.op + node.fn + node.op +
|
||||
node.args[1].toString(options);
|
||||
}
|
||||
else if (node.type === 'ConstantNode') {
|
||||
return 'const(' + node.value + ', ' + node.valueType + ')'
|
||||
}
|
||||
};
|
||||
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
|
||||
var n = new OperatorNode('+', 'add', [a, b]);
|
||||
|
||||
assert.equal(n.toString({handler: customFunction}), 'const(1, number)+add+const(2, number)');
|
||||
});
|
||||
|
||||
it ('should respect the \'all\' parenthesis option', function () {
|
||||
assert.equal(math.parse('1+1+1').toString({parenthesis: 'all'}), '(1 + 1) + 1' );
|
||||
assert.equal(math.parse('1+1+1').toTex({parenthesis: 'all'}), '\\left(1+1\\right)+1' );
|
||||
});
|
||||
|
||||
it ('should correctly LaTeX fractions in \'all\' parenthesis mode', function () {
|
||||
assert.equal(math.parse('1/2/3').toTex({parenthesis: 'all'}), '\\frac{\\left(\\frac{1}{2}\\right)}{3}');
|
||||
});
|
||||
|
||||
it ('should LaTeX an OperatorNode', function () {
|
||||
var a = new ConstantNode(2);
|
||||
var b = new ConstantNode(3);
|
||||
var c = new ConstantNode(4);
|
||||
|
||||
var n = new OperatorNode('+', 'add', [a, b]);
|
||||
assert.equal(n.toTex(), '2+3');
|
||||
});
|
||||
|
||||
it ('should LaTeX an OperatorNode with factorial', function () {
|
||||
var a = new ConstantNode(2);
|
||||
var n = new OperatorNode('!', 'factorial', [a]);
|
||||
assert.equal(n.toTex(), '2!');
|
||||
});
|
||||
|
||||
it ('should LaTeX an OperatorNode with factorial of an OperatorNode', function () {
|
||||
var a = new ConstantNode(2);
|
||||
var b = new ConstantNode(3);
|
||||
|
||||
var sub = new OperatorNode('-', 'subtract', [a, b]);
|
||||
var add = new OperatorNode('+', 'add', [a, b]);
|
||||
var mult = new OperatorNode('*', 'multiply', [a, b]);
|
||||
var div = new OperatorNode('/', 'divide', [a, b]);
|
||||
|
||||
var n1= new OperatorNode('!', 'factorial', [sub] );
|
||||
var n2= new OperatorNode('!', 'factorial', [add] );
|
||||
var n3= new OperatorNode('!', 'factorial', [mult] );
|
||||
var n4= new OperatorNode('!', 'factorial', [div] );
|
||||
assert.equal(n1.toTex(), '\\left(2-3\\right)!');
|
||||
assert.equal(n2.toTex(), '\\left(2+3\\right)!');
|
||||
assert.equal(n3.toTex(), '\\left(2\\cdot3\\right)!');
|
||||
assert.equal(n4.toTex(), '\\frac{2}{3}!');
|
||||
});
|
||||
|
||||
it ('should LaTeX an OperatorNode with unary minus', function () {
|
||||
var a = new ConstantNode(2);
|
||||
var b = new ConstantNode(3);
|
||||
|
||||
var sub = new OperatorNode('-', 'subtract', [a, b]);
|
||||
var add = new OperatorNode('+', 'add', [a, b]);
|
||||
|
||||
var n1 = new OperatorNode('-', 'unaryMinus', [a]);
|
||||
var n2 = new OperatorNode('-', 'unaryMinus', [sub]);
|
||||
var n3 = new OperatorNode('-', 'unaryMinus', [add]);
|
||||
|
||||
assert.equal(n1.toTex(), '-2');
|
||||
assert.equal(n2.toTex(), '-\\left(2-3\\right)');
|
||||
assert.equal(n3.toTex(), '-\\left(2+3\\right)');
|
||||
});
|
||||
|
||||
it ('should LaTeX an OperatorNode that subtracts an OperatorNode', function() {
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(3);
|
||||
|
||||
var sub = new OperatorNode('-', 'subtract', [b, c]);
|
||||
var add = new OperatorNode('+', 'add', [b, c]);
|
||||
|
||||
var n1 = new OperatorNode('-', 'subtract', [a, sub]);
|
||||
var n2 = new OperatorNode('-', 'subtract', [a, add]);
|
||||
|
||||
assert.equal(n1.toTex(), '1-\\left(2-3\\right)');
|
||||
assert.equal(n2.toTex(), '1-\\left(2+3\\right)');
|
||||
});
|
||||
|
||||
it ('should LaTeX an OperatorNode with zero arguments', function () {
|
||||
var n = new OperatorNode('foo', 'foo', []);
|
||||
assert.equal(n.toTex(), '\\mathrm{foo}\\left(\\right)');
|
||||
});
|
||||
|
||||
it ('should LaTeX an OperatorNode with more than two operators', function () {
|
||||
var a = new ConstantNode(2);
|
||||
var b = new ConstantNode(3);
|
||||
var c = new ConstantNode(4);
|
||||
|
||||
var n = new OperatorNode('foo', 'foo', [a, b, c]);
|
||||
assert.equal(n.toTex(), '\\mathrm{foo}\\left(2,3,4\\right)');
|
||||
|
||||
});
|
||||
|
||||
it ('should LaTeX an OperatorNode with nested operator nodes', function () {
|
||||
var a = new ConstantNode(2);
|
||||
var b = new ConstantNode(3);
|
||||
var c = new ConstantNode(4);
|
||||
var d = new ConstantNode(5);
|
||||
|
||||
var n1 = new OperatorNode('+', 'add', [a, b]);
|
||||
var n2 = new OperatorNode('-', 'subtract', [c, d]);
|
||||
var n3 = new OperatorNode('*', 'multiply', [n1, n2]);
|
||||
|
||||
var m2 = new OperatorNode('*', 'multiply', [n1, c]);
|
||||
var m3 = new OperatorNode('-', 'subtract', [m2, d]);
|
||||
|
||||
assert.equal(n1.toTex(), '2+3');
|
||||
assert.equal(n2.toTex(), '4-5');
|
||||
assert.equal(n3.toTex(), '\\left(2+3\\right)\\cdot\\left(4-5\\right)');
|
||||
assert.equal(m3.toTex(), '\\left(2+3\\right)\\cdot4-5');
|
||||
});
|
||||
|
||||
it ('should LaTeX addition and multiplication with more than two operands', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var b = new SymbolNode('b');
|
||||
var c = new SymbolNode('c');
|
||||
|
||||
var add = new OperatorNode('+', 'add', [a, b, c]);
|
||||
var multiply = new OperatorNode('*', 'multiply', [a, b, c]);
|
||||
var implicitMultiply = new OperatorNode('*', 'multiply', [a, b, c], true);
|
||||
|
||||
assert.equal(add.toTex(), ' a+\\mathrm{b}+ c');
|
||||
assert.equal(multiply.toTex(), ' a\\cdot\\mathrm{b}\\cdot c');
|
||||
assert.equal(implicitMultiply.toTex(), ' a~\\mathrm{b}~ c');
|
||||
});
|
||||
|
||||
it ('should LaTeX addition and multiplication with more than two operands including OperatorNode', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var b = new SymbolNode('b');
|
||||
var c = new SymbolNode('c');
|
||||
var d = new SymbolNode('d');
|
||||
|
||||
var mult = new OperatorNode('*', 'multiply', [a,b]);
|
||||
var add = new OperatorNode('+', 'add', [a, b]);
|
||||
|
||||
var multipleMultWithMult = new OperatorNode('*', 'multiply', [c, mult, d]);
|
||||
var multipleMultWithAdd = new OperatorNode('*', 'multiply', [c, add, d]);
|
||||
var multipleAddWithMult = new OperatorNode('+', 'add', [c, mult, d]);
|
||||
var multipleAddWithAdd = new OperatorNode('+', 'add', [c, add, d]);
|
||||
|
||||
assert.equal(multipleMultWithMult.toTex(), ' c\\cdot a\\cdot\\mathrm{b}\\cdot d');
|
||||
assert.equal(multipleMultWithAdd.toTex(), ' c\\cdot\\left( a+\\mathrm{b}\\right)\\cdot d');
|
||||
assert.equal(multipleAddWithMult.toTex(), ' c+ a\\cdot\\mathrm{b}+ d');
|
||||
assert.equal(multipleAddWithAdd.toTex(), ' c+ a+\\mathrm{b}+ d');
|
||||
});
|
||||
|
||||
it ('should LaTeX an OperatorNode that contains an operatornode with more than two operands', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var b = new SymbolNode('b');
|
||||
var c = new SymbolNode('c');
|
||||
var d = new SymbolNode('d');
|
||||
|
||||
var mult = new OperatorNode('*', 'multiply', [a, b, c]);
|
||||
var add = new OperatorNode('+', 'add', [a, b, c]);
|
||||
|
||||
var addWithMult = new OperatorNode('+', 'add', [mult, d]);
|
||||
var addWithAdd = new OperatorNode('+', 'add', [add, d]);
|
||||
var multWithMult = new OperatorNode('*', 'multiply', [mult, d]);
|
||||
var multWithAdd = new OperatorNode('*', 'multiply', [add, d]);
|
||||
|
||||
assert.equal(addWithMult.toTex(), ' a\\cdot\\mathrm{b}\\cdot c+ d');
|
||||
assert.equal(addWithAdd.toTex(), ' a+\\mathrm{b}+ c+ d');
|
||||
assert.equal(multWithMult.toTex(), ' a\\cdot\\mathrm{b}\\cdot c\\cdot d');
|
||||
assert.equal(multWithAdd.toTex(), '\\left( a+\\mathrm{b}+ c\\right)\\cdot d');
|
||||
});
|
||||
|
||||
it('should LaTeX fractions with operators that are enclosed in parenthesis', function () {
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
|
||||
var add = new OperatorNode('+', 'add', [a,a]);
|
||||
var frac = new OperatorNode('/', 'divide', [add,b]);
|
||||
assert.equal(frac.toTex(), '\\frac{1+1}{2}');
|
||||
});
|
||||
|
||||
it ('should have an identifier', function () {
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
|
||||
var n = new OperatorNode('+', 'add', [a, b]);
|
||||
|
||||
assert.equal(n.getIdentifier(), 'OperatorNode:add');
|
||||
});
|
||||
|
||||
it ('should LaTeX an OperatorNode with custom toTex', function () {
|
||||
//Also checks if the custom functions get passed on to the children
|
||||
var customFunction = function (node, options) {
|
||||
if (node.type === 'OperatorNode') {
|
||||
return node.op + node.fn + '('
|
||||
+ node.args[0].toTex(options)
|
||||
+ ', ' + node.args[1].toTex(options) + ')';
|
||||
}
|
||||
else if (node.type === 'ConstantNode') {
|
||||
return 'const\\left(' + node.value + ', ' + node.valueType + '\\right)'
|
||||
}
|
||||
};
|
||||
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
|
||||
var n1 = new OperatorNode('+', 'add', [a, b]);
|
||||
var n2 = new OperatorNode('-', 'subtract', [a, b]);
|
||||
|
||||
assert.equal(n1.toTex({handler: customFunction}), '+add(const\\left(1, number\\right), const\\left(2, number\\right))');
|
||||
assert.equal(n2.toTex({handler: customFunction}), '-subtract(const\\left(1, number\\right), const\\left(2, number\\right))');
|
||||
});
|
||||
|
||||
it ('should LaTeX an OperatorNode with custom toTex for a single operator', function () {
|
||||
//Also checks if the custom functions get passed on to the children
|
||||
var customFunction = function (node, options) {
|
||||
if ((node.type === 'OperatorNode') && (node.fn === 'add')) {
|
||||
return node.args[0].toTex(options)
|
||||
+ node.op + node.fn + node.op +
|
||||
node.args[1].toTex(options);
|
||||
}
|
||||
else if (node.type === 'ConstantNode') {
|
||||
return 'const\\left(' + node.value + ', ' + node.valueType + '\\right)'
|
||||
}
|
||||
};
|
||||
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
|
||||
var n = new OperatorNode('+', 'add', [a, b]);
|
||||
|
||||
assert.equal(n.toTex({handler: customFunction}), 'const\\left(1, number\\right)+add+const\\left(2, number\\right)');
|
||||
});
|
||||
|
||||
it ('should LaTeX powers of fractions with parentheses', function () {
|
||||
var a = new ConstantNode(1);
|
||||
var frac = new OperatorNode('/', 'divide', [a,a]);
|
||||
var pow = new OperatorNode('^', 'pow', [frac, a]);
|
||||
|
||||
assert.equal(pow.toTex(), '\\left({\\frac{1}{1}}\\right)^{1}');
|
||||
});
|
||||
|
||||
it ('should LaTeX powers of conditions with parentheses', function () {
|
||||
var a = new ConstantNode(1);
|
||||
var cond = new ConditionalNode(a, a, a);
|
||||
var pow = new OperatorNode('^', 'pow', [cond, a]);
|
||||
|
||||
assert.equal(pow.toTex(), '\\left({\\begin{cases} {1}, &\\quad{\\text{if }\\;1}\\\\{1}, &\\quad{\\text{otherwise}}\\end{cases}}\\right)^{1}');
|
||||
});
|
||||
|
||||
it ('should LaTeX simple expressions in \'auto\' mode', function () {
|
||||
//this covers a bug that was triggered previously
|
||||
assert.equal(math.parse('1+(1+1)').toTex({parenthesis: 'auto'}), '1+1+1');
|
||||
});
|
||||
|
||||
it ('should stringify implicit multiplications', function () {
|
||||
var a = math.parse('4a');
|
||||
var b = math.parse('4 a');
|
||||
var c = math.parse('a b');
|
||||
var d = math.parse('2a b');
|
||||
var e = math.parse('a b c');
|
||||
var f = math.parse('(2+3)a');
|
||||
var g = math.parse('(2+3)2');
|
||||
var h = math.parse('2(3+4)');
|
||||
|
||||
assert.equal(a.toString(), a.toString({implicit: 'hide'}));
|
||||
assert.equal(a.toString({implicit: 'hide'}), '4 a');
|
||||
assert.equal(a.toString({implicit: 'show'}), '4 * a');
|
||||
|
||||
assert.equal(b.toString(), b.toString({implicit: 'hide'}));
|
||||
assert.equal(b.toString({implicit: 'hide'}), '4 a');
|
||||
assert.equal(b.toString({implicit: 'show'}), '4 * a');
|
||||
|
||||
assert.equal(c.toString(), c.toString({implicit: 'hide'}));
|
||||
assert.equal(c.toString({implicit: 'hide'}), 'a b');
|
||||
assert.equal(c.toString({implicit: 'show'}), 'a * b');
|
||||
|
||||
assert.equal(d.toString(), d.toString({implicit: 'hide'}));
|
||||
assert.equal(d.toString({implicit: 'hide'}), '2 a b');
|
||||
assert.equal(d.toString({implicit: 'show'}), '2 * a * b');
|
||||
|
||||
assert.equal(e.toString(), e.toString({implicit: 'hide'}));
|
||||
assert.equal(e.toString({implicit: 'hide'}), 'a b c');
|
||||
assert.equal(e.toString({implicit: 'show'}), 'a * b * c');
|
||||
|
||||
assert.equal(f.toString(), f.toString({implicit: 'hide'}));
|
||||
assert.equal(f.toString({implicit: 'hide'}), '(2 + 3) a');
|
||||
assert.equal(f.toString({implicit: 'show'}), '(2 + 3) * a');
|
||||
|
||||
assert.equal(g.toString(), g.toString({implicit: 'hide'}));
|
||||
assert.equal(g.toString({implicit: 'hide'}), '(2 + 3) 2');
|
||||
assert.equal(g.toString({implicit: 'show'}), '(2 + 3) * 2');
|
||||
|
||||
assert.equal(h.toString(), h.toString({implicit: 'hide'}));
|
||||
assert.equal(h.toString({implicit: 'hide'}), '2 (3 + 4)');
|
||||
assert.equal(h.toString({implicit: 'show'}), '2 * (3 + 4)');
|
||||
});
|
||||
|
||||
it ('should LaTeX implicit multiplications', function () {
|
||||
var a = math.parse('4a');
|
||||
var b = math.parse('4 a');
|
||||
var c = math.parse('a b');
|
||||
var d = math.parse('2a b');
|
||||
var e = math.parse('a b c');
|
||||
var f = math.parse('(2+3)a');
|
||||
var g = math.parse('(2+3)2');
|
||||
var h = math.parse('2(3+4)');
|
||||
|
||||
assert.equal(a.toTex(), a.toTex({implicit: 'hide'}));
|
||||
assert.equal(a.toTex({implicit: 'hide'}), '4~ a');
|
||||
assert.equal(a.toTex({implicit: 'show'}), '4\\cdot a');
|
||||
|
||||
assert.equal(b.toTex(), b.toTex({implicit: 'hide'}));
|
||||
assert.equal(b.toTex({implicit: 'hide'}), '4~ a');
|
||||
assert.equal(b.toTex({implicit: 'show'}), '4\\cdot a');
|
||||
|
||||
assert.equal(c.toTex(), c.toTex({implicit: 'hide'}));
|
||||
assert.equal(c.toTex({implicit: 'hide'}), ' a~\\mathrm{b}');
|
||||
assert.equal(c.toTex({implicit: 'show'}), ' a\\cdot\\mathrm{b}');
|
||||
|
||||
assert.equal(d.toTex(), d.toTex({implicit: 'hide'}));
|
||||
assert.equal(d.toTex({implicit: 'hide'}), '2~ a~\\mathrm{b}');
|
||||
assert.equal(d.toTex({implicit: 'show'}), '2\\cdot a\\cdot\\mathrm{b}');
|
||||
|
||||
assert.equal(e.toTex(), e.toTex({implicit: 'hide'}));
|
||||
assert.equal(e.toTex({implicit: 'hide'}), ' a~\\mathrm{b}~ c');
|
||||
assert.equal(e.toTex({implicit: 'show'}), ' a\\cdot\\mathrm{b}\\cdot c');
|
||||
|
||||
assert.equal(f.toTex(), f.toTex({implicit: 'hide'}));
|
||||
assert.equal(f.toTex({implicit: 'hide'}), '\\left(2+3\\right)~ a');
|
||||
assert.equal(f.toTex({implicit: 'show'}), '\\left(2+3\\right)\\cdot a');
|
||||
|
||||
assert.equal(g.toTex(), g.toTex({implicit: 'hide'}));
|
||||
assert.equal(g.toTex({implicit: 'hide'}), '\\left(2+3\\right)~2');
|
||||
assert.equal(g.toTex({implicit: 'show'}), '\\left(2+3\\right)\\cdot2');
|
||||
|
||||
assert.equal(h.toTex(), h.toTex({implicit: 'hide'}));
|
||||
assert.equal(h.toTex({implicit: 'hide'}), '2~\\left(3+4\\right)');
|
||||
assert.equal(h.toTex({implicit: 'show'}), '2\\cdot\\left(3+4\\right)');
|
||||
});
|
||||
});
|
||||
199
nodered/rootfs/data/node_modules/mathjs/test/expression/node/ParenthesisNode.test.js
generated
vendored
Normal file
199
nodered/rootfs/data/node_modules/mathjs/test/expression/node/ParenthesisNode.test.js
generated
vendored
Normal file
@@ -0,0 +1,199 @@
|
||||
// test SymbolNode
|
||||
var assert = require('assert');
|
||||
var approx = require('../../../tools/approx');
|
||||
var math = require('../../../index');
|
||||
var Node = math.expression.node.Node;
|
||||
var ConstantNode = math.expression.node.ConstantNode;
|
||||
var OperatorNode = math.expression.node.OperatorNode;
|
||||
var ParenthesisNode = math.expression.node.ParenthesisNode;
|
||||
|
||||
describe('ParenthesisNode', function() {
|
||||
|
||||
it ('should create a ParenthesisNode', function () {
|
||||
var a = new ConstantNode(1);
|
||||
|
||||
var n = new ParenthesisNode(a);
|
||||
assert(n instanceof ParenthesisNode);
|
||||
assert(n instanceof Node);
|
||||
assert.equal(n.type, 'ParenthesisNode');
|
||||
});
|
||||
|
||||
it ('should throw an error when calling without new operator', function () {
|
||||
var a = new ConstantNode(1);
|
||||
assert.throws(function () {ParenthesisNode(a)}, SyntaxError);
|
||||
});
|
||||
|
||||
it ('should throw an error when calling with wrong arguments', function () {
|
||||
assert.throws(function () {new ParenthesisNode()}, TypeError);
|
||||
assert.throws(function () {new ParenthesisNode(2)}, TypeError);
|
||||
});
|
||||
|
||||
it ('should compile a ParenthesisNode', function () {
|
||||
var a = new ConstantNode(1);
|
||||
var n = new ParenthesisNode(a);
|
||||
|
||||
assert.equal(n.compile().eval.toString(), a.compile().eval.toString());
|
||||
});
|
||||
|
||||
it ('should filter a ParenthesisNode', function () {
|
||||
var a = new ConstantNode(1);
|
||||
var n = new ParenthesisNode(a);
|
||||
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof ParenthesisNode;}), [n]);
|
||||
assert.deepEqual(n.filter(function (node) {return node.content instanceof ConstantNode;}), [n]);
|
||||
assert.deepEqual(n.filter(function (node) {
|
||||
return (typeof node.content !== 'undefined') && (node.content.value == '1');
|
||||
}), [n]);
|
||||
assert.deepEqual(n.filter(function (node) {
|
||||
return (typeof node.content !== 'undefined') && (node.content.type == 'ConstantNode');
|
||||
}), [n]);
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof ConstantNode;}), [a]);
|
||||
});
|
||||
|
||||
it ('should run forEach on a ParenthesisNode', function () {
|
||||
var count = 0;
|
||||
var a = new ConstantNode(1);
|
||||
|
||||
var n = new ParenthesisNode(a);
|
||||
n.forEach(function (node, path, _parent) {
|
||||
assert.equal(node.type, 'ConstantNode');
|
||||
assert.equal(path, 'content');
|
||||
assert.deepEqual(_parent, n);
|
||||
count++;
|
||||
});
|
||||
|
||||
assert.equal(count, 1);
|
||||
});
|
||||
|
||||
it ('should map a ParenthesisNode', function () {
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ParenthesisNode(a);
|
||||
|
||||
var count = 0;
|
||||
|
||||
var c = b.map(function (node, path, _parent) {
|
||||
count++;
|
||||
assert.equal(node.type, 'ConstantNode');
|
||||
assert.equal(node.value, 1);
|
||||
return new ConstantNode(2);
|
||||
});
|
||||
|
||||
assert.equal(count, 1);
|
||||
assert.equal(c.content.value, 2);
|
||||
});
|
||||
|
||||
it ('should transform a ParenthesisNode', function () {
|
||||
var c1 = new ConstantNode(1);
|
||||
var c2 = new ConstantNode(2);
|
||||
|
||||
var a = new ParenthesisNode(c1);
|
||||
var b = new ParenthesisNode(c2);
|
||||
|
||||
var c = a.transform(function (node) {
|
||||
return node instanceof ParenthesisNode && node.content.value == 1 ? b : node;
|
||||
});
|
||||
assert.deepEqual(c, b);
|
||||
|
||||
// no match should leave the constant as is
|
||||
var d = a.transform(function (node) {
|
||||
return node instanceof ParenthesisNode && node.name == 2 ? b : node;
|
||||
});
|
||||
assert.deepEqual(d, a);
|
||||
});
|
||||
|
||||
it ('should clone a ParenthesisNode', function () {
|
||||
var a = new ConstantNode(1);
|
||||
var n = new ParenthesisNode(a);
|
||||
var clone = n.clone();
|
||||
|
||||
assert(clone instanceof ParenthesisNode);
|
||||
assert.deepEqual(n, clone);
|
||||
assert.notStrictEqual(n, clone);
|
||||
assert.equal(n.content, clone.content);
|
||||
});
|
||||
|
||||
it ('test equality another Node', function () {
|
||||
var a = new ParenthesisNode(new ConstantNode(1));
|
||||
var b = new ParenthesisNode(new ConstantNode(1));
|
||||
var c = new ParenthesisNode(new ConstantNode(2));
|
||||
var d = new ConstantNode(2);
|
||||
|
||||
assert.strictEqual(a.equals(null), false);
|
||||
assert.strictEqual(a.equals(undefined), false);
|
||||
assert.strictEqual(a.equals(b), true);
|
||||
assert.strictEqual(a.equals(c), false);
|
||||
assert.strictEqual(a.equals(d), false);
|
||||
});
|
||||
|
||||
it ('should get the content of a ParenthesisNode', function () {
|
||||
var c = new math.expression.node.ConstantNode(1);
|
||||
var p1 = new math.expression.node.ParenthesisNode(c);
|
||||
var p2 = new math.expression.node.ParenthesisNode(p1);
|
||||
|
||||
assert.equal(p1.content, c);
|
||||
assert.equal(p1.getContent(), c);
|
||||
assert.deepEqual(p1.getContent(), c);
|
||||
assert.equal(p2.getContent(), c);
|
||||
assert.deepEqual(p2.getContent(), c);
|
||||
});
|
||||
|
||||
it ('should stringify a ParenthesisNode', function () {
|
||||
var a = new ConstantNode(1);
|
||||
var n = new ParenthesisNode(a);
|
||||
|
||||
assert.equal(n.toString(), '(1)');
|
||||
assert.equal(n.toString({}), '(1)');
|
||||
});
|
||||
|
||||
it ('should stringify a ParenthesisNode when not in keep mode', function () {
|
||||
var c = new math.expression.node.ConstantNode(1);
|
||||
|
||||
var p = new math.expression.node.ParenthesisNode(c);
|
||||
|
||||
assert.equal(p.toString({parenthesis: 'all'}), '1');
|
||||
assert.equal(p.toString({parenthesis: 'auto'}), '1');
|
||||
});
|
||||
|
||||
it ('should stringify a ParenthesisNode with custom toString', function () {
|
||||
var customFunction = function (node, options) {
|
||||
if (node.type === 'ParenthesisNode') {
|
||||
return '[' + node.content.toString(options) + ']';
|
||||
}
|
||||
};
|
||||
|
||||
var c = new math.expression.node.ConstantNode(1);
|
||||
var n = new math.expression.node.ParenthesisNode(c);
|
||||
|
||||
assert.equal(n.toString({handler: customFunction}), '[1]');
|
||||
});
|
||||
|
||||
it ('should LaTeX a ParenthesisNode', function () {
|
||||
var a = new ConstantNode(1);
|
||||
var n = new ParenthesisNode(a);
|
||||
|
||||
assert.equal(n.toTex(), '\\left(1\\right)');
|
||||
assert.equal(n.toTex({}), '\\left(1\\right)');
|
||||
});
|
||||
|
||||
it ('should LaTeX a ParenthesisNode when not in keep mode', function () {
|
||||
var c = new math.expression.node.ConstantNode(1);
|
||||
|
||||
var p = new math.expression.node.ParenthesisNode(c);
|
||||
|
||||
assert.equal(p.toTex({parenthesis: 'all'}), '1');
|
||||
assert.equal(p.toTex({parenthesis: 'auto'}), '1');
|
||||
});
|
||||
|
||||
it ('should LaTeX a ParenthesisNode with custom toTex', function () {
|
||||
var customFunction = function (node, options) {
|
||||
if (node.type === 'ParenthesisNode') {
|
||||
return '\\left[' + node.content.toTex(options) + '\\right]';
|
||||
}
|
||||
};
|
||||
|
||||
var c = new math.expression.node.ConstantNode(1);
|
||||
var n = new math.expression.node.ParenthesisNode(c);
|
||||
|
||||
assert.equal(n.toTex({handler: customFunction}), '\\left[1\\right]');
|
||||
});
|
||||
});
|
||||
376
nodered/rootfs/data/node_modules/mathjs/test/expression/node/RangeNode.test.js
generated
vendored
Normal file
376
nodered/rootfs/data/node_modules/mathjs/test/expression/node/RangeNode.test.js
generated
vendored
Normal file
@@ -0,0 +1,376 @@
|
||||
// test RangeNode
|
||||
var assert = require('assert');
|
||||
var approx = require('../../../tools/approx');
|
||||
var math = require('../../../index');
|
||||
var Node = math.expression.node.Node;
|
||||
var ConstantNode = math.expression.node.ConstantNode;
|
||||
var SymbolNode = math.expression.node.SymbolNode;
|
||||
var RangeNode = math.expression.node.RangeNode;
|
||||
var OperatorNode = math.expression.node.OperatorNode;
|
||||
|
||||
describe('RangeNode', function() {
|
||||
|
||||
it ('should create a RangeNode', function () {
|
||||
var start = new ConstantNode(0);
|
||||
var end = new ConstantNode(10);
|
||||
var n = new RangeNode(start, end);
|
||||
assert(n instanceof RangeNode);
|
||||
assert(n instanceof Node);
|
||||
assert.equal(n.type, 'RangeNode');
|
||||
});
|
||||
|
||||
it ('should have isRangeNode', function () {
|
||||
var start = new ConstantNode(0);
|
||||
var end = new ConstantNode(10);
|
||||
var node = new RangeNode(start, end);
|
||||
|
||||
assert(node.isRangeNode);
|
||||
});
|
||||
|
||||
it ('should throw an error when calling without new operator', function () {
|
||||
var start = new ConstantNode(0);
|
||||
var end = new ConstantNode(10);
|
||||
assert.throws(function () {RangeNode([start, end])}, SyntaxError);
|
||||
});
|
||||
|
||||
it ('should throw an error creating a RangeNode with wrong number or type of arguments', function () {
|
||||
var start = new ConstantNode(0);
|
||||
var end = new ConstantNode(10);
|
||||
|
||||
assert.throws(function () { new RangeNode(); }, TypeError);
|
||||
assert.throws(function () { new RangeNode(start); }, TypeError);
|
||||
assert.throws(function () { new RangeNode([]); }, TypeError);
|
||||
assert.throws(function () { new RangeNode(start, end, start, end); }, Error);
|
||||
assert.throws(function () { new RangeNode(0, 10); }, TypeError);
|
||||
});
|
||||
|
||||
it ('should compile a RangeNode', function () {
|
||||
var start = new ConstantNode(0);
|
||||
var end = new ConstantNode(10);
|
||||
var step = new ConstantNode(2);
|
||||
var n = new RangeNode(start, end, step);
|
||||
|
||||
var expr = n.compile();
|
||||
assert.deepEqual(expr.eval(), math.matrix([0, 2, 4, 6, 8, 10]));
|
||||
});
|
||||
|
||||
it ('should filter a RangeNode', function () {
|
||||
var start = new ConstantNode(0);
|
||||
var end = new ConstantNode(10);
|
||||
var step = new ConstantNode(2);
|
||||
var n = new RangeNode(start, end, step);
|
||||
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof RangeNode}), [n]);
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof SymbolNode}), []);
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof ConstantNode}), [start, end, step]);
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof ConstantNode && node.value == '2'}), [step]);
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof ConstantNode && node.value == '4'}), []);
|
||||
});
|
||||
|
||||
it ('should run forEach on a RangeNode', function () {
|
||||
var start = new ConstantNode(0);
|
||||
var end = new ConstantNode(10);
|
||||
var step = new ConstantNode(2);
|
||||
var n = new RangeNode(start, end, step);
|
||||
|
||||
var nodes = [];
|
||||
var paths = [];
|
||||
n.forEach(function (node, path, parent) {
|
||||
nodes.push(node);
|
||||
paths.push(path);
|
||||
assert.strictEqual(parent, n);
|
||||
});
|
||||
|
||||
assert.equal(nodes.length, 3);
|
||||
assert.strictEqual(nodes[0], start);
|
||||
assert.strictEqual(nodes[1], end);
|
||||
assert.strictEqual(nodes[2], step);
|
||||
assert.deepEqual(paths, ['start', 'end', 'step']);
|
||||
});
|
||||
|
||||
it ('should map a RangeNode', function () {
|
||||
var start = new ConstantNode(0);
|
||||
var end = new ConstantNode(10);
|
||||
var step = new ConstantNode(2);
|
||||
var n = new RangeNode(start, end, step);
|
||||
|
||||
var nodes = [];
|
||||
var paths = [];
|
||||
var e = new ConstantNode(3);
|
||||
var f = n.map(function (node, path, parent) {
|
||||
nodes.push(node);
|
||||
paths.push(path);
|
||||
assert.strictEqual(parent, n);
|
||||
|
||||
return node instanceof ConstantNode && node.value == '0' ? e : node;
|
||||
});
|
||||
|
||||
assert.equal(nodes.length, 3);
|
||||
assert.strictEqual(nodes[0], start);
|
||||
assert.strictEqual(nodes[1], end);
|
||||
assert.strictEqual(nodes[2], step);
|
||||
assert.deepEqual(paths, ['start', 'end', 'step']);
|
||||
|
||||
assert.notStrictEqual(f, n);
|
||||
assert.deepEqual(f.start, e);
|
||||
assert.deepEqual(f.end, end);
|
||||
assert.deepEqual(f.step, step);
|
||||
});
|
||||
|
||||
it ('should throw an error when the map callback does not return a node', function () {
|
||||
var start = new ConstantNode(0);
|
||||
var end = new ConstantNode(10);
|
||||
var step = new ConstantNode(2);
|
||||
var n = new RangeNode(start, end, step);
|
||||
|
||||
assert.throws(function () {
|
||||
n.map(function () {});
|
||||
}, /Callback function must return a Node/)
|
||||
});
|
||||
|
||||
it ('should transform a RangeNodes start', function () {
|
||||
var start = new ConstantNode(0);
|
||||
var end = new ConstantNode(10);
|
||||
var step = new ConstantNode(2);
|
||||
var n = new RangeNode(start, end, step);
|
||||
|
||||
var e = new ConstantNode(3);
|
||||
var f = n.transform(function (node) {
|
||||
return node instanceof ConstantNode && node.value == '0' ? e : node;
|
||||
});
|
||||
|
||||
assert.notStrictEqual(f, n);
|
||||
assert.deepEqual(f.start, e);
|
||||
assert.deepEqual(f.end, end);
|
||||
assert.deepEqual(f.step, step);
|
||||
});
|
||||
|
||||
it ('should transform a RangeNodes end', function () {
|
||||
var start = new ConstantNode(0);
|
||||
var end = new ConstantNode(10);
|
||||
var step = new ConstantNode(2);
|
||||
var n = new RangeNode(start, end, step);
|
||||
|
||||
var e = new ConstantNode(3);
|
||||
var f = n.transform(function (node) {
|
||||
return node instanceof ConstantNode && node.value == '10' ? e : node;
|
||||
});
|
||||
|
||||
assert.notStrictEqual(f, n);
|
||||
assert.deepEqual(f.start, start);
|
||||
assert.deepEqual(f.end, e);
|
||||
assert.deepEqual(f.step, step);
|
||||
});
|
||||
|
||||
it ('should transform a RangeNodes step', function () {
|
||||
var start = new ConstantNode(0);
|
||||
var end = new ConstantNode(10);
|
||||
var step = new ConstantNode(2);
|
||||
var n = new RangeNode(start, end, step);
|
||||
|
||||
var e = new ConstantNode(3);
|
||||
var f = n.transform(function (node) {
|
||||
return node instanceof ConstantNode && node.value == '2' ? e : node;
|
||||
});
|
||||
|
||||
assert.notStrictEqual(f, n);
|
||||
assert.deepEqual(f.start, start);
|
||||
assert.deepEqual(f.end, end);
|
||||
assert.deepEqual(f.step, e);
|
||||
});
|
||||
|
||||
it ('should transform a RangeNodes without step', function () {
|
||||
var start = new ConstantNode(0);
|
||||
var end = new ConstantNode(10);
|
||||
var n = new RangeNode(start, end);
|
||||
|
||||
var e = new ConstantNode(3);
|
||||
var f = n.transform(function (node) {
|
||||
return node instanceof ConstantNode && node.value == '10' ? e : node;
|
||||
});
|
||||
|
||||
assert.notStrictEqual(f, n);
|
||||
assert.deepEqual(f.start, start);
|
||||
assert.deepEqual(f.end, e);
|
||||
});
|
||||
|
||||
it ('should transform a RangeNode itself', function () {
|
||||
var start = new ConstantNode(0);
|
||||
var end = new ConstantNode(10);
|
||||
var step = new ConstantNode(2);
|
||||
var n = new RangeNode(start, end, step);
|
||||
|
||||
var e = new ConstantNode(5);
|
||||
var f = n.transform(function (node) {
|
||||
return node instanceof RangeNode ? e : node;
|
||||
});
|
||||
|
||||
assert.deepEqual(f, e);
|
||||
});
|
||||
|
||||
it ('should clone a RangeNode', function () {
|
||||
var start = new ConstantNode(0);
|
||||
var end = new ConstantNode(10);
|
||||
var step = new ConstantNode(2);
|
||||
var c = new RangeNode(start, end, step);
|
||||
|
||||
var d = c.clone();
|
||||
|
||||
assert.deepEqual(d, c);
|
||||
assert.notStrictEqual(d, c);
|
||||
assert.strictEqual(d.start, c.start);
|
||||
assert.strictEqual(d.end, c.end);
|
||||
assert.strictEqual(d.step, c.step);
|
||||
});
|
||||
|
||||
it ('should clone a RangeNode without step', function () {
|
||||
var start = new ConstantNode(0);
|
||||
var end = new ConstantNode(10);
|
||||
var c = new RangeNode(start, end);
|
||||
|
||||
var d = c.clone();
|
||||
|
||||
assert(d instanceof RangeNode);
|
||||
assert.deepEqual(d, c);
|
||||
assert.notStrictEqual(d, c);
|
||||
assert.strictEqual(d.start, c.start);
|
||||
assert.strictEqual(d.end, c.end);
|
||||
assert.strictEqual(d.step, c.step);
|
||||
assert.strictEqual(d.step, null);
|
||||
});
|
||||
|
||||
it ('test equality another Node', function () {
|
||||
assert.strictEqual(createRangeNode(2, 4).equals(createRangeNode(2, 4)), true);
|
||||
assert.strictEqual(createRangeNode(2, 4).equals(createRangeNode(2, 5)), false);
|
||||
assert.strictEqual(createRangeNode(2, 4).equals(createRangeNode(2, 4, 1)), false);
|
||||
assert.strictEqual(createRangeNode(2, 4).equals(createRangeNode(2, 4, -1)), false);
|
||||
assert.strictEqual(createRangeNode(2, 4, -1).equals(createRangeNode(2, 4, -1)), true);
|
||||
assert.strictEqual(createRangeNode(2, 4, -1).equals(null), false);
|
||||
assert.strictEqual(createRangeNode(2, 4, -1).equals(undefined), false);
|
||||
assert.strictEqual(createRangeNode(2, 4, -1).equals(new SymbolNode('a')), false);
|
||||
assert.strictEqual(createRangeNode(2, 4, -1).equals(new SymbolNode('a')), false);
|
||||
});
|
||||
|
||||
it ('should stringify a RangeNode without step', function () {
|
||||
var start = new ConstantNode(0);
|
||||
var end = new ConstantNode(10);
|
||||
var n = new RangeNode(start, end);
|
||||
|
||||
assert.equal(n.toString(), '0:10');
|
||||
});
|
||||
|
||||
it ('should stringify a RangeNode with step', function () {
|
||||
var start = new ConstantNode(0);
|
||||
var end = new ConstantNode(10);
|
||||
var step = new ConstantNode(2);
|
||||
var n = new RangeNode(start, end, step);
|
||||
|
||||
assert.equal(n.toString(), '0:2:10');
|
||||
});
|
||||
|
||||
it ('should stringify a RangeNode with an OperatorNode', function () {
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
|
||||
var o1 = new OperatorNode('+', 'add', [a, b]);
|
||||
var o2 = new OperatorNode('<', 'smaller', [a, b]);
|
||||
|
||||
var n = new RangeNode(o1, o1, o2);
|
||||
|
||||
assert.equal(n.toString(), '1 + 2:(1 < 2):1 + 2');
|
||||
});
|
||||
|
||||
it ('should stringify a RangeNode with a RangeNode', function () {
|
||||
var start1 = new ConstantNode(0);
|
||||
var end1 = new ConstantNode(10);
|
||||
var step2 = new ConstantNode(2);
|
||||
var end2 = new ConstantNode(100);
|
||||
|
||||
var start2 = new RangeNode(start1, end1);
|
||||
var n = new RangeNode(start2, end2, step2);
|
||||
|
||||
assert.equal(n.toString(), '(0:10):2:100');
|
||||
});
|
||||
|
||||
it ('should stringify a RangeNode with custom toString', function () {
|
||||
//Also checks if the custom functions get passed on to the children
|
||||
var customFunction = function (node, options) {
|
||||
if (node.type === 'RangeNode') {
|
||||
return 'from ' + node.start.toString(options)
|
||||
+ ' to ' + node.end.toString(options)
|
||||
+ ' with steps of ' + node.step.toString(options);
|
||||
}
|
||||
else if (node.type === 'ConstantNode') {
|
||||
return 'const(' + node.value + ', ' + node.valueType + ')'
|
||||
}
|
||||
};
|
||||
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(3);
|
||||
|
||||
var n = new RangeNode(a, b, c);
|
||||
|
||||
assert.equal(n.toString({handler: customFunction}), 'from const(1, number) to const(2, number) with steps of const(3, number)');
|
||||
});
|
||||
|
||||
it ('should respect the \'all\' parenthesis option', function () {
|
||||
assert.equal(math.parse('1:2:3').toString({parenthesis: 'all'}), '(1):(2):(3)');
|
||||
assert.equal(math.parse('1:2:3').toTex({parenthesis: 'all'}), '\\left(1\\right):\\left(2\\right):\\left(3\\right)');
|
||||
});
|
||||
|
||||
it ('should LaTeX a RangeNode without step', function () {
|
||||
var start = new ConstantNode(0);
|
||||
var end = new ConstantNode(10);
|
||||
var n = new RangeNode(start, end);
|
||||
|
||||
assert.equal(n.toTex(), '0:10');
|
||||
});
|
||||
|
||||
it ('should LaTeX a RangeNode with step', function () {
|
||||
var start = new ConstantNode(0);
|
||||
var end = new ConstantNode(10);
|
||||
var step = new ConstantNode(2);
|
||||
var n = new RangeNode(start, end, step);
|
||||
|
||||
assert.equal(n.toTex(), '0:2:10');
|
||||
});
|
||||
|
||||
it ('should LaTeX a RangeNode with custom toTex', function () {
|
||||
//Also checks if the custom functions get passed on to the children
|
||||
var customFunction = function (node, options) {
|
||||
if (node.type === 'RangeNode') {
|
||||
return 'from ' + node.start.toTex(options)
|
||||
+ ' to ' + node.end.toTex(options)
|
||||
+ ' with steps of ' + node.step.toTex(options);
|
||||
}
|
||||
else if (node.type === 'ConstantNode') {
|
||||
return 'const\\left(' + node.value + ', ' + node.valueType + '\\right)'
|
||||
}
|
||||
};
|
||||
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
var c = new ConstantNode(3);
|
||||
|
||||
var n = new RangeNode(a, b, c);
|
||||
|
||||
assert.equal(n.toTex({handler: customFunction}), 'from const\\left(1, number\\right) to const\\left(2, number\\right) with steps of const\\left(3, number\\right)');
|
||||
});
|
||||
|
||||
/**
|
||||
* Helper function to create a RangeNode
|
||||
* @param {number} start
|
||||
* @param {number} end
|
||||
* @param {number} [step]
|
||||
* @return {RangeNode}
|
||||
*/
|
||||
function createRangeNode(start, end, step) {
|
||||
if (step === undefined) {
|
||||
return new RangeNode(new ConstantNode(start), new ConstantNode(end));
|
||||
}
|
||||
else {
|
||||
return new RangeNode(new ConstantNode(start), new ConstantNode(end), new ConstantNode(step));
|
||||
}
|
||||
}
|
||||
});
|
||||
167
nodered/rootfs/data/node_modules/mathjs/test/expression/node/SymbolNode.test.js
generated
vendored
Normal file
167
nodered/rootfs/data/node_modules/mathjs/test/expression/node/SymbolNode.test.js
generated
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
// test SymbolNode
|
||||
var assert = require('assert');
|
||||
var approx = require('../../../tools/approx');
|
||||
var math = require('../../../index');
|
||||
var Node = math.expression.node.Node;
|
||||
var ConstantNode = math.expression.node.ConstantNode;
|
||||
var SymbolNode = math.expression.node.SymbolNode;
|
||||
var OperatorNode = math.expression.node.OperatorNode;
|
||||
|
||||
describe('SymbolNode', function() {
|
||||
|
||||
it ('should create a SymbolNode', function () {
|
||||
var n = new SymbolNode('sqrt');
|
||||
assert(n instanceof SymbolNode);
|
||||
assert(n instanceof Node);
|
||||
assert.equal(n.type, 'SymbolNode');
|
||||
});
|
||||
|
||||
it ('should have isSymbolNode', function () {
|
||||
var node = new SymbolNode('a');
|
||||
assert(node.isSymbolNode);
|
||||
});
|
||||
|
||||
it ('should throw an error when calling without new operator', function () {
|
||||
assert.throws(function () {SymbolNode('sqrt')}, SyntaxError);
|
||||
});
|
||||
|
||||
it ('should throw an error when calling with wrong arguments', function () {
|
||||
assert.throws(function () {new SymbolNode()}, TypeError);
|
||||
assert.throws(function () {new SymbolNode(2)}, TypeError);
|
||||
});
|
||||
|
||||
it ('should throw an error when evaluating an undefined symbol', function () {
|
||||
var scope = {};
|
||||
var s = new SymbolNode('foo');
|
||||
assert.throws(function () {s.compile().eval(scope)}, Error);
|
||||
});
|
||||
|
||||
it ('should compile a SymbolNode', function () {
|
||||
var s = new SymbolNode('a');
|
||||
|
||||
var expr = s.compile();
|
||||
var scope = {a: 5};
|
||||
assert.equal(expr.eval(scope), 5);
|
||||
assert.throws(function () {expr.eval({})}, Error);
|
||||
|
||||
var s2 = new SymbolNode('sqrt');
|
||||
var expr2 = s2.compile();
|
||||
var scope2 = {};
|
||||
assert.strictEqual(expr2.eval(scope2), math.sqrt);
|
||||
});
|
||||
|
||||
it ('should filter a SymbolNode', function () {
|
||||
var n = new SymbolNode('x');
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof SymbolNode}), [n]);
|
||||
assert.deepEqual(n.filter(function (node) {return node.name == 'x'}), [n]);
|
||||
assert.deepEqual(n.filter(function (node) {return node.name == 'q'}), []);
|
||||
assert.deepEqual(n.filter(function (node) {return node instanceof ConstantNode}), []);
|
||||
});
|
||||
|
||||
it ('should run forEach on a SymbolNode', function () {
|
||||
var a = new SymbolNode('a');
|
||||
a.forEach(function () {
|
||||
assert.ok(false, 'should not execute, symbol has no childs')
|
||||
});
|
||||
});
|
||||
|
||||
it ('should map a SymbolNode', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var c = new SymbolNode('c');
|
||||
var b = a.map(function () {
|
||||
assert.ok(false, 'should not execute, symbol has no childs')
|
||||
});
|
||||
|
||||
assert.notStrictEqual(b, a);
|
||||
assert.deepEqual(b, a);
|
||||
});
|
||||
|
||||
it ('should transform a SymbolNode', function () {
|
||||
var a = new SymbolNode('x');
|
||||
var b = new SymbolNode('y');
|
||||
var c = a.transform(function (node) {
|
||||
return node instanceof SymbolNode && node.name == 'x' ? b : node;
|
||||
});
|
||||
assert.deepEqual(c, b);
|
||||
|
||||
// no match should leave the symbol as is
|
||||
var d = a.transform(function (node) {
|
||||
return node instanceof SymbolNode && node.name == 'q' ? b : node;
|
||||
});
|
||||
assert.deepEqual(d, a);
|
||||
});
|
||||
|
||||
it ('should clone a SymbolNode', function () {
|
||||
var a = new SymbolNode('x');
|
||||
var b = a.clone();
|
||||
|
||||
assert(b instanceof SymbolNode);
|
||||
assert.deepEqual(a, b);
|
||||
assert.notStrictEqual(a, b);
|
||||
assert.equal(a.name, b.name);
|
||||
});
|
||||
|
||||
it ('test equality another Node', function () {
|
||||
var a = new SymbolNode('a');
|
||||
var b = new SymbolNode('b');
|
||||
var aEqual = new SymbolNode('a');
|
||||
var aFake = {
|
||||
name: 'a'
|
||||
};
|
||||
|
||||
assert.strictEqual(a.equals(null), false);
|
||||
assert.strictEqual(a.equals(undefined), false);
|
||||
assert.strictEqual(a.equals(aEqual), true);
|
||||
assert.strictEqual(a.equals(b), false);
|
||||
assert.strictEqual(a.equals(aFake), false);
|
||||
assert.strictEqual(a.equals(new ConstantNode(2)), false);
|
||||
});
|
||||
|
||||
it ('should stringify a SymbolNode', function () {
|
||||
var s = new SymbolNode('foo');
|
||||
|
||||
assert.equal(s.toString(), 'foo');
|
||||
});
|
||||
|
||||
it ('should stringigy a SymbolNode with custom toString', function () {
|
||||
//Also checks if the custom functions get passed on to the children
|
||||
var customFunction = function (node, options) {
|
||||
if (node.type === 'SymbolNode') {
|
||||
return 'symbol(' + node.name + ')';
|
||||
}
|
||||
};
|
||||
|
||||
var n = new SymbolNode('a');
|
||||
|
||||
assert.equal(n.toString({handler: customFunction}), 'symbol(a)');
|
||||
});
|
||||
|
||||
it ('should LaTeX a SymbolNode', function () {
|
||||
var s = new SymbolNode('foo');
|
||||
|
||||
assert.equal(s.toTex(), ' foo');
|
||||
});
|
||||
|
||||
it ('should LaTeX a SymbolNode with custom toTex', function () {
|
||||
//Also checks if the custom functions get passed on to the children
|
||||
var customFunction = function (node, options) {
|
||||
if (node.type === 'SymbolNode') {
|
||||
return 'symbol(' + node.name + ')';
|
||||
}
|
||||
};
|
||||
|
||||
var n = new SymbolNode('a');
|
||||
|
||||
assert.equal(n.toTex({handler: customFunction}), 'symbol(a)');
|
||||
});
|
||||
|
||||
it ('should LaTeX a SymbolNode without breaking \\cdot', function () {
|
||||
var a = new ConstantNode(1);
|
||||
var b = new SymbolNode('Epsilon');
|
||||
|
||||
var mult = new OperatorNode('*', 'multiply', [a,b]);
|
||||
|
||||
assert.equal(mult.toTex(), '1\\cdot E');
|
||||
});
|
||||
|
||||
});
|
||||
11
nodered/rootfs/data/node_modules/mathjs/test/expression/node/index.test.js
generated
vendored
Normal file
11
nodered/rootfs/data/node_modules/mathjs/test/expression/node/index.test.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
// test the contents of index.js
|
||||
var assert = require('assert');
|
||||
var index = require('../../../lib/expression/node/index');
|
||||
|
||||
describe('node/index', function() {
|
||||
|
||||
it('should contain all nodes', function() {
|
||||
assert.equal(index.length, 16);
|
||||
});
|
||||
|
||||
});
|
||||
114
nodered/rootfs/data/node_modules/mathjs/test/expression/operators.test.js
generated
vendored
Normal file
114
nodered/rootfs/data/node_modules/mathjs/test/expression/operators.test.js
generated
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
var assert = require('assert');
|
||||
|
||||
var math = require('../../index');
|
||||
var operators = require('../../lib/expression/operators');
|
||||
var OperatorNode = math.expression.node.OperatorNode;
|
||||
var AssignmentNode = math.expression.node.AssignmentNode;
|
||||
var SymbolNode = math.expression.node.SymbolNode;
|
||||
var ConstantNode = math.expression.node.ConstantNode;
|
||||
var Node = math.expression.node.Node;
|
||||
var ParenthesisNode = math.expression.node.ParenthesisNode;
|
||||
|
||||
describe('operators', function () {
|
||||
it('should return the precedence of a node', function () {
|
||||
var a = new ConstantNode(1);
|
||||
var b = new ConstantNode(2);
|
||||
|
||||
var n1 = new AssignmentNode(new SymbolNode('a'), a);
|
||||
var n2 = new OperatorNode('or', 'or', [a, b]);
|
||||
|
||||
assert.equal(operators.getPrecedence(n1, 'keep'), 0);
|
||||
assert.equal(operators.getPrecedence(n2, 'keep'), 2);
|
||||
});
|
||||
|
||||
it('should return null if precedence is not defined for a node', function () {
|
||||
var n = new Node();
|
||||
|
||||
assert.equal(operators.getPrecedence(n, 'keep'), null);
|
||||
});
|
||||
|
||||
it ('should return the precedence of a ParenthesisNode', function () {
|
||||
var c = new ConstantNode(1);
|
||||
|
||||
var op = new OperatorNode('or', 'or', [c, c]);
|
||||
|
||||
var p = new ParenthesisNode(op);
|
||||
|
||||
assert.equal(operators.getPrecedence(p, 'all'), operators.getPrecedence(op, 'all'));
|
||||
assert.equal(operators.getPrecedence(p, 'auto'), operators.getPrecedence(op, 'all'));
|
||||
assert.equal(operators.getPrecedence(p, 'keep'), null);
|
||||
});
|
||||
|
||||
it('should return the associativity of a node', function () {
|
||||
var a = new ConstantNode(1);
|
||||
|
||||
var n1 = new OperatorNode('+', 'add', [a, a]);
|
||||
var n2 = new OperatorNode('^', 'pow', [a, a]);
|
||||
var n3 = new OperatorNode('-', 'unaryMinus', [a]);
|
||||
var n4 = new OperatorNode('!', 'factorial', [a]);
|
||||
|
||||
assert.equal(operators.getAssociativity(n1, 'keep'), 'left');
|
||||
assert.equal(operators.getAssociativity(n2, 'keep'), 'right');
|
||||
assert.equal(operators.getAssociativity(n3, 'keep'), 'right');
|
||||
assert.equal(operators.getAssociativity(n4, 'keep'), 'left');
|
||||
});
|
||||
|
||||
it ('should return the associativity of a ParenthesisNode', function () {
|
||||
var c = new ConstantNode(1);
|
||||
|
||||
var op = new OperatorNode('or', 'or', [c, c]);
|
||||
|
||||
var p = new ParenthesisNode(op);
|
||||
|
||||
assert.equal(operators.getAssociativity(p, 'all'), operators.getAssociativity(op, 'keep'));
|
||||
assert.equal(operators.getAssociativity(p, 'auto'), operators.getAssociativity(op, 'keep'));
|
||||
assert.equal(operators.getAssociativity(p, 'keep'), null);
|
||||
});
|
||||
|
||||
it('should return null if associativity is not defined for a node', function () {
|
||||
var a = new ConstantNode(1);
|
||||
|
||||
var n1 = new Node();
|
||||
var n2 = new AssignmentNode(new SymbolNode('a'), a);
|
||||
|
||||
assert.equal(operators.getAssociativity(n1, 'keep'), null);
|
||||
assert.equal(operators.getAssociativity(n2, 'keep'), null);
|
||||
});
|
||||
|
||||
it('should return if a Node is associative with another Node', function () {
|
||||
var a = new ConstantNode(1);
|
||||
|
||||
var n1 = new OperatorNode('+', 'add', [a, a]);
|
||||
var n2 = new OperatorNode('-', 'subtract', [a, a]);
|
||||
|
||||
assert.equal(operators.isAssociativeWith(n1, n1, 'keep'), true);
|
||||
assert.equal(operators.isAssociativeWith(n1, n2, 'keep'), true);
|
||||
assert.equal(operators.isAssociativeWith(n2, n2, 'keep'), false);
|
||||
assert.equal(operators.isAssociativeWith(n2, n1, 'keep'), false);
|
||||
});
|
||||
|
||||
it('should return null if the associativity between two Nodes is not defined', function () {
|
||||
var a = new ConstantNode(1);
|
||||
|
||||
var n1 = new Node();
|
||||
var n2 = new AssignmentNode(new SymbolNode('a'), a);
|
||||
|
||||
assert.equal(operators.isAssociativeWith(n1, n1, 'keep'), null);
|
||||
assert.equal(operators.isAssociativeWith(n1, n2, 'keep'), null);
|
||||
assert.equal(operators.isAssociativeWith(n2, n2, 'keep'), null);
|
||||
assert.equal(operators.isAssociativeWith(n2, n1, 'keep'), null);
|
||||
});
|
||||
|
||||
it ('should return if a ParenthesisNode is associative with another Node', function () {
|
||||
var a = new ConstantNode(1);
|
||||
|
||||
var add = new OperatorNode('+', 'add', [a, a]);
|
||||
var sub = new OperatorNode('-', 'subtract', [a, a]);
|
||||
|
||||
var p = new ParenthesisNode(add);
|
||||
|
||||
assert.equal(operators.isAssociativeWith(p, sub, 'all'), true);
|
||||
assert.equal(operators.isAssociativeWith(p, sub, 'auto'), true);
|
||||
assert.equal(operators.isAssociativeWith(p, sub, 'keep'), null);
|
||||
});
|
||||
});
|
||||
2044
nodered/rootfs/data/node_modules/mathjs/test/expression/parse.test.js
generated
vendored
Normal file
2044
nodered/rootfs/data/node_modules/mathjs/test/expression/parse.test.js
generated
vendored
Normal file
@@ -0,0 +1,2044 @@
|
||||
// test parse
|
||||
var assert = require('assert');
|
||||
var approx = require('../../tools/approx');
|
||||
var math = require('../../index');
|
||||
var ArgumentsError = require('../../lib/error/ArgumentsError');
|
||||
var parse = math.expression.parse;
|
||||
var ConditionalNode = math.expression.node.ConditionalNode;
|
||||
var OperatorNode = math.expression.node.OperatorNode;
|
||||
var RangeNode = math.expression.node.RangeNode;
|
||||
var Complex = math.type.Complex;
|
||||
var Matrix = math.type.Matrix;
|
||||
var Range = math.type.Range;
|
||||
var Unit = math.type.Unit;
|
||||
var ResultSet = math.type.ResultSet;
|
||||
|
||||
/**
|
||||
* Helper function to parse an expression and immediately evaluate its results
|
||||
* @param {String} expr
|
||||
* @param {Object} [scope]
|
||||
* @return {*} result
|
||||
*/
|
||||
function parseAndEval(expr, scope) {
|
||||
return parse(expr).eval(scope);
|
||||
}
|
||||
|
||||
describe('parse', function() {
|
||||
|
||||
it('should parse a single expression', function() {
|
||||
approx.equal(parse('2 + 6 / 3').compile().eval(), 4);
|
||||
});
|
||||
|
||||
it('should parse an empty expression', function() {
|
||||
assert.strictEqual(parse('').compile().eval(), undefined);
|
||||
assert.strictEqual(parse('\n').compile().eval(), undefined);
|
||||
assert.strictEqual(parse('\n\n').compile().eval(), undefined);
|
||||
assert.strictEqual(parse('\n \n').compile().eval(), undefined);
|
||||
assert.strictEqual(parse('#foo\n').compile().eval(), undefined);
|
||||
assert.strictEqual(parse('#foo\n#bar\n').compile().eval(), undefined);
|
||||
});
|
||||
|
||||
it('should parse an array with expressions', function() {
|
||||
var scope = {};
|
||||
assert.deepEqual(parse(['a=3', 'b=4', 'a*b']).map(function (node) {
|
||||
return node.compile().eval(scope);
|
||||
}), [3, 4, 12]);
|
||||
});
|
||||
|
||||
it('should parse a matrix with expressions', function() {
|
||||
var scope = {};
|
||||
assert.deepEqual(parse(math.matrix(['a=3', 'b=4', 'a*b'])).map(function (node) {
|
||||
return node.compile().eval(scope);
|
||||
}), math.matrix([3, 4, 12]));
|
||||
});
|
||||
|
||||
it('should parse an array with an empty expression', function() {
|
||||
assert.deepEqual(parse(['']).map(function (node) {
|
||||
return node.compile().eval();
|
||||
}), [undefined]);
|
||||
});
|
||||
|
||||
it('should parse an array with an empty expression', function() {
|
||||
assert.deepEqual(parse(math.matrix([''])).map(function (node) {
|
||||
return node.compile().eval();
|
||||
}), math.matrix([undefined]));
|
||||
});
|
||||
|
||||
it('should parse unicode characters', function() {
|
||||
// http://unicode-table.com/en
|
||||
var scope = {};
|
||||
|
||||
math.eval('\u00E9 = 2', scope); // Latin Small Letter E with Acute
|
||||
assert.strictEqual(scope['\u00E9'], 2);
|
||||
|
||||
math.eval('\u03A6 = 3', scope); // Greek Capital Letter Phi
|
||||
assert.strictEqual(scope['\u03A6'], 3);
|
||||
|
||||
math.eval('\u03A9 = 4', scope); // Greek Capital Letter Omega
|
||||
assert.strictEqual(scope['\u03A9'], 4);
|
||||
|
||||
math.eval('\u2126 = 4', scope); // Letter-like character Ohm
|
||||
assert.strictEqual(scope['\u2126'], 4);
|
||||
|
||||
math.eval('k\u00F6ln = 5', scope); // Combination of latin and unicode
|
||||
assert.strictEqual(scope['k\u00F6ln'], 5);
|
||||
|
||||
// test unicode characters in the astral plane (surrogate pairs
|
||||
math.eval('\uD835\uDD38 = 1', scope); // double struck capital A
|
||||
assert.strictEqual(scope['\uD835\uDD38'], 1);
|
||||
|
||||
// should not allow the "holes"
|
||||
assert.throws(function () {
|
||||
math.eval('\uD835\uDCA3 = 1', scope);
|
||||
})
|
||||
|
||||
});
|
||||
|
||||
describe('multiline', function () {
|
||||
|
||||
it('should parse multiline expressions', function() {
|
||||
assert.deepEqual(parse('a=3\nb=4\na*b').compile().eval(), new ResultSet([3, 4, 12]));
|
||||
assert.deepEqual(parse('b = 43; b * 4').compile().eval(), new ResultSet([172]));
|
||||
});
|
||||
|
||||
it('should skip empty lines in multiline expressions', function() {
|
||||
assert.deepEqual(parse('\n;\n2 * 4\n').compile().eval(), new ResultSet([8]));
|
||||
});
|
||||
|
||||
it('should spread operators over multiple lines', function() {
|
||||
assert.deepEqual(parse('2+\n3').compile().eval(), 5);
|
||||
assert.deepEqual(parse('2+\n\n3').compile().eval(), 5);
|
||||
assert.deepEqual(parse('2*\n3').compile().eval(), 6);
|
||||
assert.deepEqual(parse('2^\n3').compile().eval(), 8);
|
||||
assert.deepEqual(parse('2==\n3').compile().eval(), false);
|
||||
assert.deepEqual(parse('2*-\n3').compile().eval(), -6);
|
||||
});
|
||||
|
||||
it('should parse multiple function assignments', function() {
|
||||
var scope = {};
|
||||
parse('f(x)=x*2;g(x)=x*3').compile().eval(scope);
|
||||
assert.equal(scope.f(2), 4);
|
||||
assert.equal(scope.g(2), 6);
|
||||
|
||||
var scope2 = {};
|
||||
parse('a=2;f(x)=x^a;').compile().eval(scope2);
|
||||
assert.equal(scope2.a, 2);
|
||||
assert.equal(scope2.f(3), 9);
|
||||
});
|
||||
|
||||
it ('should correctly scope a function variable if also used outside the function', function () {
|
||||
var scope = {};
|
||||
var res = parse('x=2;f(x)=x^2;x').compile().eval(scope); // x should be x=2, not x of the function
|
||||
|
||||
assert.deepEqual(res, {entries: [2]});
|
||||
assert.equal(scope.x, 2);
|
||||
assert.equal(scope.f(3), 9);
|
||||
});
|
||||
|
||||
it('should spread a function over multiple lines', function() {
|
||||
assert.deepEqual(parse('add(\n4\n,\n2\n)').compile().eval(), 6);
|
||||
});
|
||||
|
||||
it('should spread contents of parameters over multiple lines', function() {
|
||||
assert.deepEqual(parse('(\n4\n+\n2\n)').compile().eval(), 6);
|
||||
});
|
||||
|
||||
it('should spread a function assignment over multiple lines', function() {
|
||||
assert.deepEqual(typeof parse('f(\nx\n,\ny\n)=\nx+\ny').compile().eval(), 'function');
|
||||
});
|
||||
|
||||
it('should spread a variable assignment over multiple lines', function() {
|
||||
assert.deepEqual(parse('x=\n2').compile().eval(), 2);
|
||||
});
|
||||
|
||||
it('should spread a matrix over multiple lines', function() {
|
||||
assert.deepEqual(parse('[\n1\n,\n2\n]').compile().eval(), math.matrix([1, 2]));
|
||||
});
|
||||
|
||||
it('should spread a range over multiple lines', function() {
|
||||
assert.deepEqual(parse('2:\n4').compile().eval(), math.matrix([2,3,4]));
|
||||
assert.deepEqual(parse('2:\n2:\n6').compile().eval(), math.matrix([2,4,6]));
|
||||
});
|
||||
|
||||
it('should spread an index over multiple lines', function() {
|
||||
assert.deepEqual(parse('a[\n1\n,\n1\n]').compile().eval({a: [[1,2],[3,4]]}), 1);
|
||||
|
||||
var scope = {a: [[1,2],[3,4]]};
|
||||
assert.deepEqual(parse('a[\n1\n,\n1\n]=\n100').compile().eval(scope), 100);
|
||||
assert.deepEqual(scope, {a: [[100,2],[3,4]]})
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('should throw an error when scope contains a reserved keyword', function() {
|
||||
var scope = {
|
||||
end: 2
|
||||
};
|
||||
assert.throws(function () {
|
||||
parse('2+3').compile().eval(scope);
|
||||
}, /Scope contains an illegal symbol/);
|
||||
});
|
||||
|
||||
it('should give informative syntax errors', function() {
|
||||
assert.throws(function () {parse('2 +');}, /Unexpected end of expression \(char 4\)/);
|
||||
assert.throws(function () {parse('2 + 3 + *');}, /Value expected \(char 9\)/);
|
||||
});
|
||||
|
||||
it('should throw an error if called with wrong number of arguments', function() {
|
||||
assert.throws(function () {parse();}, ArgumentsError);
|
||||
assert.throws(function () {parse(1,2,3);}, ArgumentsError);
|
||||
assert.throws(function () {parse([1, 2]);}, TypeError);
|
||||
});
|
||||
|
||||
it('should throw an error if called with a wrong type of argument', function() {
|
||||
assert.throws(function () {parse(23);}, TypeError);
|
||||
assert.throws(function () {parse(math.unit('5cm'));}, TypeError);
|
||||
assert.throws(function () {parse(new Complex(2,3));}, TypeError);
|
||||
assert.throws(function () {parse(true);}, TypeError);
|
||||
});
|
||||
|
||||
it('should throw an error in case of unsupported characters', function() {
|
||||
assert.throws(function () {parse('2\u00A1');}, /Syntax error in part "\u00A1"/);
|
||||
});
|
||||
|
||||
describe('comments', function () {
|
||||
|
||||
it('should skip comments', function() {
|
||||
assert.equal(parseAndEval('2 + 3 # - 4'), 5);
|
||||
});
|
||||
|
||||
it('should skip comments in a ResultSet', function() {
|
||||
assert.deepEqual(parseAndEval('2 + 3 # - 4\n6-2'), new ResultSet([5, 4]));
|
||||
});
|
||||
|
||||
it('should fill in the property comment of a Node', function() {
|
||||
assert.equal(parse('2 + 3').comment, '');
|
||||
|
||||
assert.equal(parse('2 + 3 # hello').comment, '# hello');
|
||||
assert.equal(parse(' # hi').comment, '# hi');
|
||||
|
||||
var blockNode = parse('2 # foo\n3 # bar');
|
||||
assert.equal(blockNode.blocks.length, 2);
|
||||
assert.equal(blockNode.blocks[0].node.comment, '# foo');
|
||||
assert.equal(blockNode.blocks[1].node.comment, '# bar');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('number', function () {
|
||||
|
||||
it('should parse valid numbers', function() {
|
||||
assert.equal(parseAndEval('0'), 0);
|
||||
assert.equal(parseAndEval('3'), 3);
|
||||
assert.equal(parseAndEval('3.2'), 3.2);
|
||||
assert.equal(parseAndEval('3.'), 3);
|
||||
assert.equal(parseAndEval('3. '), 3);
|
||||
assert.equal(parseAndEval('3.\t'), 3);
|
||||
assert.equal(parseAndEval('003.2'), 3.2);
|
||||
assert.equal(parseAndEval('003.200'), 3.2);
|
||||
assert.equal(parseAndEval('.2'), 0.2);
|
||||
assert.equal(parseAndEval('3e2'), 300);
|
||||
assert.equal(parseAndEval('300e2'), 30000);
|
||||
assert.equal(parseAndEval('300e+2'), 30000);
|
||||
assert.equal(parseAndEval('300e-2'), 3);
|
||||
assert.equal(parseAndEval('300E-2'), 3);
|
||||
assert.equal(parseAndEval('3.2e2'), 320);
|
||||
});
|
||||
|
||||
it('should parse a number followed by e', function() {
|
||||
approx.equal(parseAndEval('2e'), 2 * Math.E);
|
||||
});
|
||||
|
||||
it('should throw an error with invalid numbers', function() {
|
||||
assert.throws(function () {parseAndEval('.'); }, /Value expected/);
|
||||
assert.throws(function () {parseAndEval('3.2.2'); }, SyntaxError);
|
||||
assert.throws(function () {parseAndEval('3.2e2.2'); }, SyntaxError);
|
||||
|
||||
assert.throws(function () {parseAndEval('3e0.5'); }, /Digit expected, got "."/);
|
||||
assert.throws(function () {parseAndEval('3e.5'); }, /Digit expected, got "."/);
|
||||
assert.throws(function () {parseAndEval('-3e0.5'); }, /Digit expected, got "."/);
|
||||
assert.throws(function () {parseAndEval('-3e.5'); }, /Digit expected, got "."/);
|
||||
assert.throws(function () {parseAndEval('3e-0.5'); }, /Digit expected, got "."/);
|
||||
assert.throws(function () {parseAndEval('3e-.5'); }, /Digit expected, got "."/);
|
||||
assert.throws(function () {parseAndEval('-3e-0.5'); }, /Digit expected, got "."/);
|
||||
assert.throws(function () {parseAndEval('-3e-.5'); }, /Digit expected, got "."/);
|
||||
|
||||
assert.throws(function () {parseAndEval('2e+a'); }, /Digit expected, got "a"/);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('bignumber', function () {
|
||||
|
||||
it('should parse bignumbers', function() {
|
||||
assert.deepEqual(parseAndEval('bignumber(0.1)'), math.bignumber(0.1));
|
||||
assert.deepEqual(parseAndEval('bignumber("1.2e500")'), math.bignumber('1.2e500'));
|
||||
});
|
||||
|
||||
it('should output bignumbers if default number type is bignumber', function() {
|
||||
var bigmath = math.create({
|
||||
number: 'BigNumber'
|
||||
});
|
||||
|
||||
assert.deepEqual(bigmath.parse('0.1').compile().eval(), bigmath.bignumber(0.1));
|
||||
assert.deepEqual(bigmath.parse('1.2e5000').compile().eval(), bigmath.bignumber('1.2e5000'));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('fraction', function () {
|
||||
|
||||
it('should output fractions if default number type is fraction', function() {
|
||||
var fmath = math.create({
|
||||
number: 'Fraction'
|
||||
});
|
||||
|
||||
assert(fmath.parse('0.1').compile().eval() instanceof math.type.Fraction);
|
||||
assert.equal(fmath.parse('1/3').compile().eval().toString(), '0.(3)');
|
||||
assert.equal(fmath.parse('0.1+0.2').compile().eval().toString(), '0.3');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('string', function () {
|
||||
|
||||
it('should parse a string', function() {
|
||||
assert.deepEqual(parseAndEval('"hello"'), "hello");
|
||||
assert.deepEqual(parseAndEval(' "hi" '), "hi");
|
||||
});
|
||||
|
||||
it('should parse a with escaped characters', function() {
|
||||
assert.deepEqual(parseAndEval('"line end\\nnext"'), 'line end\nnext');
|
||||
assert.deepEqual(parseAndEval('"line end\\n"'), 'line end\n');
|
||||
assert.deepEqual(parseAndEval('"tab\\tnext"'), 'tab\tnext');
|
||||
assert.deepEqual(parseAndEval('"tab\\t"'), 'tab\t');
|
||||
assert.deepEqual(parseAndEval('"escaped backslash\\\\next"'), 'escaped backslash\\next');
|
||||
assert.deepEqual(parseAndEval('"escaped backslash\\\\"'), 'escaped backslash\\');
|
||||
});
|
||||
|
||||
it('should throw an error with invalid strings', function() {
|
||||
assert.throws(function () {parseAndEval('"hi'); }, SyntaxError);
|
||||
assert.throws(function () {parseAndEval(' hi" '); }, Error);
|
||||
});
|
||||
|
||||
it('should get a string subset', function() {
|
||||
var scope = {};
|
||||
assert.deepEqual(parseAndEval('c="hello"', scope), "hello");
|
||||
assert.deepEqual(parseAndEval('c[2:4]', scope), "ell");
|
||||
assert.deepEqual(parseAndEval('c[5:-1:1]', scope), "olleh");
|
||||
assert.deepEqual(parseAndEval('c[end-2:-1:1]', scope), "leh");
|
||||
assert.deepEqual(parseAndEval('"hello"[2:4]', scope), "ell");
|
||||
});
|
||||
|
||||
it('should set a string subset', function() {
|
||||
var scope = {};
|
||||
assert.deepEqual(parseAndEval('c="hello"', scope), "hello");
|
||||
assert.deepEqual(parseAndEval('c[1] = "H"', scope), "H");
|
||||
assert.deepEqual(scope.c, "Hello");
|
||||
assert.deepEqual(parseAndEval('c', scope), "Hello");
|
||||
assert.deepEqual(parseAndEval('c[6:11] = " world"', scope), " world");
|
||||
assert.deepEqual(scope.c, "Hello world");
|
||||
assert.deepEqual(parseAndEval('c[end] = "D"', scope), "D");
|
||||
assert.deepEqual(scope.c, "Hello worlD");
|
||||
});
|
||||
|
||||
it('should set a string subset on an object', function() {
|
||||
var scope = { a: {} };
|
||||
assert.deepEqual(parseAndEval('a.c="hello"', scope), "hello");
|
||||
assert.deepEqual(parseAndEval('a.c[1] = "H"', scope), "H");
|
||||
assert.deepEqual(scope.a, {c: "Hello"});
|
||||
assert.deepEqual(parseAndEval('a.c', scope), "Hello");
|
||||
assert.deepEqual(parseAndEval('a.c[6:11] = " world"', scope), " world");
|
||||
assert.deepEqual(scope.a, {c: "Hello world"});
|
||||
assert.deepEqual(parseAndEval('a.c', scope), "Hello world");
|
||||
assert.deepEqual(scope.a, {c: "Hello world"});
|
||||
assert.deepEqual(parseAndEval('a.c[end] = "D"', scope), "D");
|
||||
assert.deepEqual(scope.a, {c: "Hello worlD"});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('unit', function () {
|
||||
|
||||
it('should parse units', function() {
|
||||
assert.deepEqual(parseAndEval('5cm'), new Unit(5, 'cm'));
|
||||
assert.ok(parseAndEval('5cm') instanceof Unit);
|
||||
});
|
||||
|
||||
it('should correctly parse negative temperatures', function () {
|
||||
approx.deepEqual(parseAndEval('-6 celsius'), new Unit(-6, 'celsius'));
|
||||
approx.deepEqual(parseAndEval('--6 celsius'), new Unit(6, 'celsius'));
|
||||
approx.deepEqual(parseAndEval('-6 celsius to fahrenheit'),
|
||||
new Unit(21.2, 'fahrenheit').to('fahrenheit'));
|
||||
});
|
||||
|
||||
it('should convert units', function() {
|
||||
var scope = {};
|
||||
approx.deepEqual(parseAndEval('(5.08 cm * 1000) to inch', scope),
|
||||
math.unit(2000, 'inch').to('inch'));
|
||||
approx.deepEqual(parseAndEval('a = (5.08 cm * 1000) to mm', scope),
|
||||
math.unit(50800, 'mm').to('mm'));
|
||||
approx.deepEqual(parseAndEval('a to inch', scope),
|
||||
math.unit(2000, 'inch').to('inch'));
|
||||
|
||||
approx.deepEqual(parseAndEval('10 celsius to fahrenheit'),
|
||||
math.unit(50, 'fahrenheit').to('fahrenheit'));
|
||||
approx.deepEqual(parseAndEval('20 celsius to fahrenheit'),
|
||||
math.unit(68, 'fahrenheit').to('fahrenheit'));
|
||||
approx.deepEqual(parseAndEval('50 fahrenheit to celsius'),
|
||||
math.unit(10, 'celsius').to('celsius'));
|
||||
});
|
||||
|
||||
it('should evaluate operator "to" with correct precedence ', function () {
|
||||
approx.deepEqual(parseAndEval('5.08 cm * 1000 to inch'),
|
||||
new Unit(2000, 'inch').to('inch'));
|
||||
});
|
||||
|
||||
it('should evaluate operator "in" (alias of "to") ', function () {
|
||||
approx.deepEqual(parseAndEval('5.08 cm in inch'),
|
||||
new Unit(2, 'inch').to('inch'));
|
||||
});
|
||||
|
||||
it('should evaluate unit "in" (should not conflict with operator "in")', function () {
|
||||
approx.deepEqual(parseAndEval('2 in'), new Unit(2, 'in'));
|
||||
approx.deepEqual(parseAndEval('5.08 cm in in'), new Unit(2, 'in').to('in'));
|
||||
approx.deepEqual(parseAndEval('5 in in in'), new Unit(5, 'in').to('in'));
|
||||
approx.deepEqual(parseAndEval('2 in to meter'), new Unit(2, 'inch').to('meter'));
|
||||
approx.deepEqual(parseAndEval('2 in in meter'), new Unit(2, 'inch').to('meter'));
|
||||
approx.deepEqual(parseAndEval('a in inch', {a: new Unit(5.08, 'cm')}), new Unit(2, 'inch').to('inch'));
|
||||
approx.deepEqual(parseAndEval('(2+3) in'), new Unit(5, 'in'));
|
||||
approx.deepEqual(parseAndEval('a in', {a: 5}), new Unit(5, 'in'));
|
||||
approx.deepEqual(parseAndEval('0.5in + 1.5in to cm'), new Unit(5.08, 'cm').to('cm'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('complex', function () {
|
||||
|
||||
it('should parse complex values', function () {
|
||||
assert.deepEqual(parseAndEval('i'), new Complex(0,1));
|
||||
assert.deepEqual(parseAndEval('2+3i'), new Complex(2,3));
|
||||
assert.deepEqual(parseAndEval('2+3*i'), new Complex(2,3));
|
||||
assert.deepEqual(parseAndEval('1/2i'), new Complex(0, 0.5));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('matrix', function () {
|
||||
|
||||
it('should parse a matrix', function() {
|
||||
assert.ok(parseAndEval('[1,2;3,4]') instanceof Matrix);
|
||||
|
||||
var m = parseAndEval('[1,2,3;4,5,6]');
|
||||
assert.deepEqual(m.size(), [2,3]);
|
||||
assert.deepEqual(m, math.matrix([[1,2,3],[4,5,6]]));
|
||||
|
||||
var b = parseAndEval('[5, 6; 1, 1]');
|
||||
assert.deepEqual(b.size(), [2,2]);
|
||||
assert.deepEqual(b, math.matrix([[5,6],[1,1]]));
|
||||
|
||||
// from 1 to n dimensions
|
||||
assert.deepEqual(parseAndEval('[ ]'), math.matrix([]));
|
||||
assert.deepEqual(parseAndEval('[1,2,3]'), math.matrix([1,2,3]));
|
||||
assert.deepEqual(parseAndEval('[1;2;3]'), math.matrix([[1],[2],[3]]));
|
||||
assert.deepEqual(parseAndEval('[[1,2],[3,4]]'), math.matrix([[1,2],[3,4]]));
|
||||
assert.deepEqual(parseAndEval('[[[1],[2]],[[3],[4]]]'), math.matrix([[[1],[2]],[[3],[4]]]));
|
||||
});
|
||||
|
||||
it('should parse an empty matrix', function() {
|
||||
assert.deepEqual(parseAndEval('[]'), math.matrix([]));
|
||||
});
|
||||
|
||||
it('should get a matrix subset', function() {
|
||||
var scope = {
|
||||
a: math.matrix([
|
||||
[1,2,3],
|
||||
[4,5,6],
|
||||
[7,8,9]
|
||||
])
|
||||
};
|
||||
assert.deepEqual(parseAndEval('a[2, :]', scope), math.matrix([[4,5,6]]));
|
||||
assert.deepEqual(parseAndEval('a[2, :2]', scope), math.matrix([[4,5]]));
|
||||
assert.deepEqual(parseAndEval('a[2, :end-1]', scope), math.matrix([[4,5]]));
|
||||
assert.deepEqual(parseAndEval('a[2, 2:]', scope), math.matrix([[5,6]]));
|
||||
assert.deepEqual(parseAndEval('a[2, 2:3]', scope), math.matrix([[5,6]]));
|
||||
assert.deepEqual(parseAndEval('a[2, 1:2:3]', scope), math.matrix([[4,6]]));
|
||||
assert.deepEqual(parseAndEval('a[:, 2]', scope), math.matrix([[2],[5],[8]]));
|
||||
assert.deepEqual(parseAndEval('a[:2, 2]', scope), math.matrix([[2],[5]]));
|
||||
assert.deepEqual(parseAndEval('a[:end-1, 2]', scope), math.matrix([[2],[5]]));
|
||||
assert.deepEqual(parseAndEval('a[2:, 2]', scope), math.matrix([[5],[8]]));
|
||||
assert.deepEqual(parseAndEval('a[2:3, 2]', scope), math.matrix([[5],[8]]));
|
||||
assert.deepEqual(parseAndEval('a[1:2:3, 2]', scope), math.matrix([[2],[8]]));
|
||||
});
|
||||
|
||||
it('should get a matrix subset of a matrix subset', function() {
|
||||
var scope = {
|
||||
a: math.matrix([
|
||||
[1,2,3],
|
||||
[4,5,6],
|
||||
[7,8,9]
|
||||
])
|
||||
};
|
||||
assert.deepEqual(parseAndEval('a[2, :][1,1]', scope), 4);
|
||||
});
|
||||
|
||||
it('should parse matrix resizings', function() {
|
||||
var scope = {};
|
||||
assert.deepEqual(parseAndEval('a = []', scope), math.matrix([]));
|
||||
assert.deepEqual(parseAndEval('a[1:3,1] = [1;2;3]', scope), math.matrix([[1],[2],[3]]));
|
||||
assert.deepEqual(parseAndEval('a[:,2] = [4;5;6]', scope), math.matrix([[4],[5],[6]]));
|
||||
assert.deepEqual(scope.a, math.matrix([[1,4],[2,5],[3,6]]));
|
||||
|
||||
assert.deepEqual(parseAndEval('a = []', scope), math.matrix([]));
|
||||
assert.strictEqual(parseAndEval('a[1,3] = 3', scope), 3);
|
||||
assert.deepEqual(scope.a, math.matrix([[0,0,3]]));
|
||||
assert.deepEqual(parseAndEval('a[2,:] = [[4,5,6]]', scope), math.matrix([[4,5,6]]));
|
||||
assert.deepEqual(scope.a, math.matrix([[0,0,3],[4,5,6]]));
|
||||
|
||||
assert.deepEqual(parseAndEval('a = []', scope), math.matrix([]));
|
||||
assert.strictEqual(parseAndEval('a[3,1] = 3', scope), 3);
|
||||
assert.deepEqual(scope.a, math.matrix([[0],[0],[3]]));
|
||||
assert.deepEqual(parseAndEval('a[:,2] = [4;5;6]', scope), math.matrix([[4],[5],[6]]));
|
||||
assert.deepEqual(scope.a, math.matrix([[0,4],[0,5],[3,6]]));
|
||||
|
||||
assert.deepEqual(parseAndEval('a = []', scope), math.matrix([]));
|
||||
assert.deepEqual(parseAndEval('a[1,1:3] = [[1,2,3]]', scope), math.matrix([[1,2,3]]));
|
||||
assert.deepEqual(scope.a, math.matrix([[1,2,3]]));
|
||||
assert.deepEqual(parseAndEval('a[2,:] = [[4,5,6]]', scope), math.matrix([[4,5,6]]));
|
||||
assert.deepEqual(scope.a, math.matrix([[1,2,3],[4,5,6]]));
|
||||
});
|
||||
|
||||
it('should get/set the matrix correctly', function() {
|
||||
var scope = {};
|
||||
parseAndEval('a=[1,2;3,4]', scope);
|
||||
parseAndEval('a[1,1] = 100', scope);
|
||||
assert.deepEqual(scope.a.size(), [2,2]);
|
||||
assert.deepEqual(scope.a, math.matrix([[100,2],[3,4]]));
|
||||
parseAndEval('a[2:3,2:3] = [10,11;12,13]', scope);
|
||||
assert.deepEqual(scope.a.size(), [3,3]);
|
||||
assert.deepEqual(scope.a, math.matrix([[100, 2, 0],[3,10,11],[0,12,13]]));
|
||||
var a = scope.a;
|
||||
// note: after getting subset, uninitialized elements are replaced by elements with an undefined value
|
||||
assert.deepEqual(a.subset(math.index(new Range(0,3), new Range(0,2))), math.matrix([[100,2],[3,10],[0,12]]));
|
||||
assert.deepEqual(parseAndEval('a[1:3,1:2]', scope), math.matrix([[100,2],[3,10],[0,12]]));
|
||||
|
||||
scope.b = [[1,2],[3,4]];
|
||||
assert.deepEqual(parseAndEval('b[1,:]', scope), [[1, 2]]);
|
||||
});
|
||||
|
||||
it('should get/set the matrix correctly for 3d matrices', function() {
|
||||
var scope = {};
|
||||
assert.deepEqual(parseAndEval('f=[1,2;3,4]', scope), math.matrix([[1,2],[3,4]]));
|
||||
assert.deepEqual(parseAndEval('size(f)', scope), math.matrix([2,2]));
|
||||
|
||||
parseAndEval('f[:,:,2]=[5,6;7,8]', scope);
|
||||
assert.deepEqual(scope.f, math.matrix([
|
||||
[
|
||||
[1,5],
|
||||
[2,6]
|
||||
],
|
||||
[
|
||||
[3,7],
|
||||
[4,8]
|
||||
]
|
||||
]));
|
||||
|
||||
assert.deepEqual(parseAndEval('size(f)', scope), math.matrix([2,2,2]));
|
||||
assert.deepEqual(parseAndEval('f[:,:,1]', scope), math.matrix([[[1],[2]],[[3],[4]]]));
|
||||
assert.deepEqual(parseAndEval('f[:,:,2]', scope), math.matrix([[[5],[6]],[[7],[8]]]));
|
||||
assert.deepEqual(parseAndEval('f[:,2,:]', scope), math.matrix([[[2,6]],[[4,8]]]));
|
||||
assert.deepEqual(parseAndEval('f[2,:,:]', scope), math.matrix([[[3,7],[4,8]]]));
|
||||
|
||||
parseAndEval('a=diag([1,2,3,4])', scope);
|
||||
assert.deepEqual(parseAndEval('a[3:end, 3:end]', scope), math.matrix([[3,0],[0,4]]));
|
||||
parseAndEval('a[3:end, 2:end]=9*ones(2,3)', scope);
|
||||
assert.deepEqual(scope.a, math.matrix([
|
||||
[1,0,0,0],
|
||||
[0,2,0,0],
|
||||
[0,9,9,9],
|
||||
[0,9,9,9]
|
||||
]));
|
||||
assert.deepEqual(parseAndEval('a[2:end-1, 2:end-1]', scope), math.matrix([[2,0],[9,9]]));
|
||||
});
|
||||
|
||||
it('should merge nested matrices', function() {
|
||||
var scope = {};
|
||||
parseAndEval('a=[1,2;3,4]', scope);
|
||||
|
||||
});
|
||||
|
||||
it('should parse matrix concatenations', function() {
|
||||
var scope = {};
|
||||
parseAndEval('a=[1,2;3,4]', scope);
|
||||
parseAndEval('b=[5,6;7,8]', scope);
|
||||
assert.deepEqual(parseAndEval('c=concat(a,b)', scope), math.matrix([[1,2,5,6],[3,4,7,8]]));
|
||||
assert.deepEqual(parseAndEval('c=concat(a,b,1)', scope), math.matrix([[1,2],[3,4],[5,6],[7,8]]));
|
||||
assert.deepEqual(parseAndEval('c=concat(concat(a,b), concat(b,a), 1)', scope), math.matrix([[1,2,5,6],[3,4,7,8],[5,6,1,2],[7,8,3,4]]));
|
||||
assert.deepEqual(parseAndEval('c=concat([[1,2]], [[3,4]], 1)', scope), math.matrix([[1,2],[3,4]]));
|
||||
assert.deepEqual(parseAndEval('c=concat([[1,2]], [[3,4]], 2)', scope), math.matrix([[1,2,3,4]]));
|
||||
assert.deepEqual(parseAndEval('c=concat([[1]], [2;3], 1)', scope), math.matrix([[1],[2],[3]]));
|
||||
assert.deepEqual(parseAndEval('d=1:3', scope), math.matrix([1,2,3]));
|
||||
assert.deepEqual(parseAndEval('concat(d,d)', scope), math.matrix([1,2,3,1,2,3]));
|
||||
assert.deepEqual(parseAndEval('e=1+d', scope), math.matrix([2,3,4]));
|
||||
assert.deepEqual(parseAndEval('size(e)', scope), math.matrix([3]));
|
||||
assert.deepEqual(parseAndEval('concat(e,e)', scope), math.matrix([2,3,4,2,3,4]));
|
||||
assert.deepEqual(parseAndEval('[[],[]]', scope), math.matrix([[],[]]));
|
||||
assert.deepEqual(parseAndEval('[[],[]]', scope).size(), [2, 0]);
|
||||
assert.deepEqual(parseAndEval('size([[],[]])', scope), math.matrix([2, 0]));
|
||||
});
|
||||
|
||||
it('should execute map on an array with one based indices', function () {
|
||||
var logs = [];
|
||||
var scope = {
|
||||
A: [1,2,3],
|
||||
callback: function (value, index, matrix) {
|
||||
assert.strictEqual(matrix, scope.A);
|
||||
// note: we don't copy index, index should be a new Array for every call of callback
|
||||
logs.push([value, index]);
|
||||
return value + 1;
|
||||
}
|
||||
};
|
||||
var res = math.eval('map(A, callback)', scope);
|
||||
assert.deepEqual(res, [2,3,4]);
|
||||
|
||||
assert.deepEqual(logs, [[1, [1]], [2, [2]], [3, [3]]]);
|
||||
});
|
||||
|
||||
it('should execute map on a Matrix with one based indices', function () {
|
||||
var logs = [];
|
||||
var scope = {
|
||||
A: math.matrix([1,2,3]),
|
||||
callback: function (value, index, matrix) {
|
||||
assert.strictEqual(matrix, scope.A);
|
||||
// note: we don't copy index, index should be a new Array for every call of callback
|
||||
logs.push([value, index]);
|
||||
return value + 1;
|
||||
}
|
||||
};
|
||||
var res = math.eval('map(A, callback)', scope);
|
||||
assert.deepEqual(res, math.matrix([2,3,4]));
|
||||
|
||||
assert.deepEqual(logs, [[1, [1]], [2, [2]], [3, [3]]]);
|
||||
});
|
||||
|
||||
it('should execute forEach on an array with one based indices', function () {
|
||||
var logs = [];
|
||||
var scope = {
|
||||
A: [1,2,3],
|
||||
callback: function (value, index, matrix) {
|
||||
assert.strictEqual(matrix, scope.A);
|
||||
// note: we don't copy index, index should be a new Array for every call of callback
|
||||
logs.push([value, index]);
|
||||
}
|
||||
};
|
||||
math.eval('forEach(A, callback)', scope);
|
||||
|
||||
assert.deepEqual(logs, [[1, [1]], [2, [2]], [3, [3]]]);
|
||||
});
|
||||
|
||||
it('should execute forEach on a Matrix with one based indices', function () {
|
||||
var logs = [];
|
||||
var scope = {
|
||||
A: math.matrix([1,2,3]),
|
||||
callback: function (value, index, matrix) {
|
||||
assert.strictEqual(matrix, scope.A);
|
||||
// note: we don't copy index, index should be a new Array for every call of callback
|
||||
logs.push([value, index]);
|
||||
}
|
||||
};
|
||||
math.eval('forEach(A, callback)', scope);
|
||||
|
||||
assert.deepEqual(logs, [[1, [1]], [2, [2]], [3, [3]]]);
|
||||
});
|
||||
|
||||
it('should disable arrays as range in a matrix index', function () {
|
||||
var scope = {
|
||||
a: [[1,2,3],[4,5,6]]
|
||||
};
|
||||
|
||||
assert.throws(function () {
|
||||
parseAndEval('a[2, 2+3i]', scope);
|
||||
}, /TypeError: Dimension must be an Array, Matrix, number, string, or Range/);
|
||||
});
|
||||
|
||||
it('should throw an error for invalid matrix', function() {
|
||||
assert.throws(function () {parseAndEval('[1, 2');}, /End of matrix ] expected/);
|
||||
assert.throws(function () {parseAndEval('[1; 2');}, /End of matrix ] expected/);
|
||||
});
|
||||
|
||||
it('should throw an error when matrix rows mismatch', function() {
|
||||
assert.throws(function () {parseAndEval('[1, 2; 1, 2, 3]');}, /Column dimensions mismatch/);
|
||||
});
|
||||
|
||||
it('should throw an error for invalid matrix subsets', function() {
|
||||
var scope = {a: [1,2,3]};
|
||||
assert.throws(function () {parseAndEval('a[1', scope);}, /Parenthesis ] expected/);
|
||||
});
|
||||
|
||||
it('should throw an error for invalid matrix concatenations', function() {
|
||||
var scope = {};
|
||||
assert.throws(function () {parseAndEval('c=concat(a, [1,2,3])', scope);});
|
||||
});
|
||||
});
|
||||
|
||||
describe('objects', function () {
|
||||
|
||||
it('should get an object property', function () {
|
||||
assert.deepEqual(parseAndEval('obj["foo"]', {obj: {foo: 2}}), 2);
|
||||
});
|
||||
|
||||
it('should get a nested object property', function () {
|
||||
assert.deepEqual(parseAndEval('obj["foo"]["bar"]', {obj: {foo: {bar: 2}}}), 2);
|
||||
});
|
||||
|
||||
it('should get a nested matrix subset from an object property', function () {
|
||||
assert.deepEqual(parseAndEval('obj.foo[2]', {obj: {foo: [1,2,3]}}), 2);
|
||||
assert.deepEqual(parseAndEval('obj.foo[end]', {obj: {foo: [1,2,3]}}), 3);
|
||||
assert.deepEqual(parseAndEval('obj.foo[2][3]', {obj: {foo: ['hello', 'world']}}), 'r');
|
||||
assert.deepEqual(parseAndEval('obj.foo[2][end]', {obj: {foo: ['hello', 'world']}}), 'd');
|
||||
assert.deepEqual(parseAndEval('obj.foo[1].bar', {obj: {foo: [{bar:4}]}}), 4);
|
||||
});
|
||||
|
||||
it('should set an object property', function () {
|
||||
var scope = {obj: {a:3}};
|
||||
var res = parseAndEval('obj["b"] = 2', scope);
|
||||
assert.strictEqual(res, 2);
|
||||
assert.deepEqual(scope, {obj: {a: 3, b: 2}});
|
||||
});
|
||||
|
||||
it('should set a nested object property', function () {
|
||||
var scope = {obj: {foo: {}}};
|
||||
var res = parseAndEval('obj["foo"]["bar"] = 2', scope);
|
||||
assert.strictEqual(res, 2);
|
||||
assert.deepEqual(scope, {obj: {foo: {bar: 2}}});
|
||||
});
|
||||
|
||||
it('should throw an error when trying to apply a matrix index as object property', function () {
|
||||
var scope = {a: {}};
|
||||
assert.throws(function () {
|
||||
parseAndEval('a[2] = 6', scope);
|
||||
}, /Cannot apply a numeric index as object property/);
|
||||
});
|
||||
|
||||
it('should set a nested matrix subset from an object property (1)', function () {
|
||||
var scope = {obj: {foo: [1,2,3]}};
|
||||
assert.deepEqual(parseAndEval('obj.foo[2] = 6', scope), 6);
|
||||
assert.deepEqual(scope, {obj: {foo: [1,6,3]}});
|
||||
|
||||
assert.deepEqual(parseAndEval('obj.foo[end] = 8', scope), 8);
|
||||
assert.deepEqual(scope, {obj: {foo: [1,6,8]}});
|
||||
});
|
||||
|
||||
it('should set a nested matrix subset from an object property (2)', function () {
|
||||
var scope = {obj: {foo: [{bar:4}]}};
|
||||
assert.deepEqual(parseAndEval('obj.foo[1].bar = 6', scope), 6);
|
||||
assert.deepEqual(scope, {obj: {foo: [{bar: 6}]}});
|
||||
});
|
||||
|
||||
it('should set a nested matrix subset from an object property (3)', function () {
|
||||
var scope = {obj: {foo: [{bar:{}}]}};
|
||||
assert.deepEqual(parseAndEval('obj.foo[1].bar.baz = 6', scope), 6);
|
||||
assert.deepEqual(scope, {obj: {foo: [{bar: {baz:6}}]}});
|
||||
});
|
||||
|
||||
it('should set a nested matrix subset from an object property (4)', function () {
|
||||
var scope = {obj: {foo: ['hello', 'world']}};
|
||||
assert.deepEqual(parseAndEval('obj.foo[1][end] = "a"', scope), 'a');
|
||||
assert.deepEqual(scope, {obj: {foo: ['hella', 'world']}});
|
||||
assert.deepEqual(parseAndEval('obj.foo[end][end] = "!"', scope), '!');
|
||||
assert.deepEqual(scope, {obj: {foo: ['hella', 'worl!']}});
|
||||
});
|
||||
|
||||
// TODO: test whether 1-based IndexErrors are thrown
|
||||
|
||||
it('should get an object property with dot notation', function () {
|
||||
assert.deepEqual(parseAndEval('obj.foo', {obj: {foo: 2}}), 2);
|
||||
});
|
||||
|
||||
it('should get an object property from an object inside parentheses', function () {
|
||||
assert.deepEqual(parseAndEval('(obj).foo', {obj: {foo: 2}}), 2);
|
||||
});
|
||||
|
||||
it('should get a nested object property with dot notation', function () {
|
||||
assert.deepEqual(parseAndEval('obj.foo.bar', {obj: {foo: {bar: 2}}}), 2);
|
||||
});
|
||||
|
||||
it('should invoke a function in an object', function () {
|
||||
var scope = {
|
||||
obj: {
|
||||
fn: function (x) {
|
||||
return x * x;
|
||||
}
|
||||
}
|
||||
};
|
||||
assert.deepEqual(parseAndEval('obj.fn(2)', scope), 4);
|
||||
assert.deepEqual(parseAndEval('obj["fn"](2)', scope), 4);
|
||||
});
|
||||
|
||||
it('should invoke a function returned by a function', function () {
|
||||
var scope = {
|
||||
theAnswer: function () {
|
||||
return function () {
|
||||
return 42;
|
||||
};
|
||||
},
|
||||
partialAdd: function (a) {
|
||||
return function (b) {
|
||||
return a + b;
|
||||
};
|
||||
}
|
||||
};
|
||||
assert.deepEqual(parseAndEval('theAnswer()()', scope), 42);
|
||||
assert.deepEqual(parseAndEval('partialAdd(2)(3)', scope), 5);
|
||||
});
|
||||
|
||||
it('should invoke a function which is a property of a function', function () {
|
||||
function f () {
|
||||
return '42'
|
||||
}
|
||||
f.foo = function () {
|
||||
return 'bar'
|
||||
}
|
||||
|
||||
assert.deepEqual(parseAndEval('f.foo()', {f: f}), 'bar');
|
||||
});
|
||||
|
||||
it('should invoke a function on an object with the right context', function () {
|
||||
approx.equal(parseAndEval('(2.54 cm).toNumeric("inch")'), 1);
|
||||
assert.deepEqual(parseAndEval('bignumber(2).plus(3)'), math.bignumber(5));
|
||||
assert.deepEqual(parseAndEval('bignumber(2)["plus"](3)'), math.bignumber(5));
|
||||
});
|
||||
|
||||
it('should invoke toString on some object', function () {
|
||||
assert.strictEqual(parseAndEval('(3).toString()'), '3');
|
||||
});
|
||||
|
||||
it('should get nested object property with mixed dot- and index-notation', function () {
|
||||
assert.deepEqual(parseAndEval('obj.foo["bar"].baz', {obj: {foo: {bar: {baz: 2}}}}), 2);
|
||||
assert.deepEqual(parseAndEval('obj["foo"].bar["baz"]', {obj: {foo: {bar: {baz: 2}}}}), 2);
|
||||
});
|
||||
|
||||
it('should set an object property with dot notation', function () {
|
||||
var scope = {obj: {}};
|
||||
parseAndEval('obj.foo = 2', scope);
|
||||
assert.deepEqual(scope, {obj: {foo: 2}});
|
||||
});
|
||||
|
||||
it('should set a nested object property with dot notation', function () {
|
||||
var scope = {obj: {foo: {}}};
|
||||
parseAndEval('obj.foo.bar = 2', scope);
|
||||
assert.deepEqual(scope, {obj: {foo: {bar: 2}}});
|
||||
});
|
||||
|
||||
it('should throw an error in case of invalid property with dot notation', function () {
|
||||
assert.throws(function () {parseAndEval('obj. +foo')}, /SyntaxError: Property name expected after dot \(char 6\)/);
|
||||
assert.throws(function () {parseAndEval('obj.["foo"]')}, /SyntaxError: Property name expected after dot \(char 5\)/);
|
||||
});
|
||||
|
||||
it('should create an empty object', function () {
|
||||
assert.deepEqual(parseAndEval('{}'), {});
|
||||
});
|
||||
|
||||
it('should create an object with quoted keys', function () {
|
||||
assert.deepEqual(parseAndEval('{"a":2+3,"b":"foo"}'), {a: 5, b: 'foo'});
|
||||
});
|
||||
|
||||
it('should create an object with unquoted keys', function () {
|
||||
assert.deepEqual(parseAndEval('{a:2+3,b:"foo"}'), {a: 5, b: 'foo'});
|
||||
});
|
||||
|
||||
it('should create an object with child object', function () {
|
||||
assert.deepEqual(parseAndEval('{a:{b:2}}'), {a:{b:2}})
|
||||
});
|
||||
|
||||
it('should get a property from a just created object', function () {
|
||||
assert.deepEqual(parseAndEval('{foo:2}["foo"]'), 2);
|
||||
});
|
||||
|
||||
it('should parse an object containing a function assignment', function () {
|
||||
var obj = parseAndEval('{f: f(x)=x^2}');
|
||||
assert.deepEqual(Object.keys(obj), ['f']);
|
||||
assert.equal(obj.f(2), 4);
|
||||
});
|
||||
|
||||
it('should parse an object containing a variable assignment', function () {
|
||||
var scope = {};
|
||||
assert.deepEqual(parseAndEval('{f: a=42}', scope), {f: 42});
|
||||
assert.strictEqual(scope.a, 42);
|
||||
});
|
||||
|
||||
it('should throw an exception in case of invalid object key', function () {
|
||||
assert.throws(function () {parseAndEval('{a b: 2}')}, /SyntaxError: Colon : expected after object key \(char 4\)/);
|
||||
assert.throws(function () {parseAndEval('{a: }')}, /SyntaxError: Value expected \(char 5\)/);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('boolean', function () {
|
||||
|
||||
it('should parse boolean values', function () {
|
||||
assert.equal(parseAndEval('true'), true);
|
||||
assert.equal(parseAndEval('false'), false);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('constants', function () {
|
||||
|
||||
it('should parse constants', function() {
|
||||
assert.deepEqual(parseAndEval('i'), new Complex(0, 1));
|
||||
approx.equal(parseAndEval('pi'), Math.PI);
|
||||
approx.equal(parseAndEval('e'), Math.E);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('variables', function () {
|
||||
|
||||
it('should parse valid variable assignments', function() {
|
||||
var scope = {};
|
||||
assert.equal(parseAndEval('a = 0.75', scope), 0.75);
|
||||
assert.equal(parseAndEval('a + 2', scope), 2.75);
|
||||
assert.equal(parseAndEval('a = 2', scope), 2);
|
||||
assert.equal(parseAndEval('a + 2', scope), 4);
|
||||
approx.equal(parseAndEval('pi * 2', scope), 6.283185307179586);
|
||||
});
|
||||
|
||||
it('should throw an error on undefined symbol', function() {
|
||||
assert.throws(function() {parseAndEval('qqq + 2'); });
|
||||
});
|
||||
|
||||
it('should throw an error on invalid assignments', function() {
|
||||
//assert.throws(function () {parseAndEval('sin(2) = 0.75')}, SyntaxError); // TODO: should this throw an exception?
|
||||
assert.throws(function () {parseAndEval('sin + 2 = 3');}, SyntaxError);
|
||||
});
|
||||
|
||||
it('should parse nested assignments', function() {
|
||||
var scope = [];
|
||||
assert.equal(parseAndEval('c = d = (e = 4.5)', scope), 4.5);
|
||||
assert.equal(scope.c, 4.5);
|
||||
assert.equal(scope.d, 4.5);
|
||||
assert.equal(scope.e, 4.5);
|
||||
assert.deepEqual(parseAndEval('a = [1,2,f=3]', scope), math.matrix([1,2,3]));
|
||||
assert.equal(scope.f, 3);
|
||||
assert.equal(parseAndEval('2 + (g = 3 + 4)', scope), 9);
|
||||
assert.equal(scope.g, 7);
|
||||
});
|
||||
|
||||
it('should parse variable assignment inside a function call', function() {
|
||||
var scope = {};
|
||||
assert.deepEqual(parseAndEval('sqrt(x=4)', scope), 2);
|
||||
assert.deepEqual(scope, { x:4 });
|
||||
});
|
||||
|
||||
it('should parse variable assignment inside an accessor', function () {
|
||||
var scope = {A: [10,20,30]};
|
||||
assert.deepEqual(parseAndEval('A[x=2]', scope), 20);
|
||||
assert.deepEqual(scope, { A:[10,20,30], x:2 });
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('functions', function () {
|
||||
|
||||
it('should parse functions', function() {
|
||||
assert.equal(parseAndEval('sqrt(4)'), 2);
|
||||
assert.equal(parseAndEval('sqrt(6+3)'), 3);
|
||||
assert.equal(parseAndEval('atan2(2,2)'), 0.7853981633974483);
|
||||
assert.deepEqual(parseAndEval('sqrt(-4)'), new Complex(0, 2));
|
||||
assert.equal(parseAndEval('abs(-4.2)'), 4.2);
|
||||
assert.equal(parseAndEval('add(2, 3)'), 5);
|
||||
approx.deepEqual(parseAndEval('1+exp(pi*i)'), new Complex(0, 0));
|
||||
assert.equal(parseAndEval('unequal(2, 3)'), true);
|
||||
});
|
||||
|
||||
it('should get a subset of a matrix returned by a function', function() {
|
||||
var scope = {
|
||||
test: function () {
|
||||
return [1,2,3,4];
|
||||
}
|
||||
};
|
||||
assert.equal(parseAndEval('test()[2]', scope), 2);
|
||||
});
|
||||
|
||||
it('should parse functions without parameters', function() {
|
||||
assert.equal(parseAndEval('r()', {r: function() {return 2;}}), 2);
|
||||
});
|
||||
|
||||
it('should parse function assignments', function() {
|
||||
var scope = {};
|
||||
parseAndEval('x=100', scope); // for testing scoping of the function variables
|
||||
assert.equal(parseAndEval('f(x) = x^2', scope).syntax, 'f(x)');
|
||||
assert.equal(parseAndEval('f(3)', scope), 9);
|
||||
assert.equal(scope.f(3), 9);
|
||||
assert.equal(scope.x, 100);
|
||||
assert.equal(parseAndEval('g(x, y) = x^y', scope).syntax, 'g(x, y)');
|
||||
assert.equal(parseAndEval('g(4,5)', scope), 1024);
|
||||
assert.equal(scope.g(4,5), 1024);
|
||||
});
|
||||
|
||||
it ('should correctly evaluate variables in assigned functions', function () {
|
||||
var scope = {};
|
||||
assert.equal(parseAndEval('a = 3', scope), 3);
|
||||
assert.equal(parseAndEval('f(x) = a * x', scope).syntax, 'f(x)');
|
||||
assert.equal(parseAndEval('f(2)', scope), 6);
|
||||
assert.equal(parseAndEval('a = 5', scope), 5);
|
||||
assert.equal(parseAndEval('f(2)', scope), 10);
|
||||
assert.equal(parseAndEval('g(x) = x^q', scope).syntax, 'g(x)');
|
||||
assert.equal(parseAndEval('q = 4/2', scope), 2);
|
||||
assert.equal(parseAndEval('g(3)', scope), 9);
|
||||
});
|
||||
|
||||
it('should throw an error for undefined variables in an assigned function', function() {
|
||||
var scope = {};
|
||||
assert.equal(parseAndEval('g(x) = x^q', scope).syntax, 'g(x)');
|
||||
assert.throws(function () {
|
||||
parseAndEval('g(3)', scope);
|
||||
}, function (err) {
|
||||
return (err instanceof Error) && (err.toString() == 'Error: Undefined symbol q');
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw an error on invalid left hand side of a function assignment', function() {
|
||||
assert.throws(function () {
|
||||
var scope = {};
|
||||
parseAndEval('g(x, 2) = x^2', scope);
|
||||
}, SyntaxError);
|
||||
|
||||
assert.throws(function () {
|
||||
var scope = {};
|
||||
parseAndEval('2(x, 2) = x^2', scope);
|
||||
}, SyntaxError);
|
||||
});
|
||||
});
|
||||
|
||||
describe ('parentheses', function () {
|
||||
it('should parse parentheses overriding the default precedence', function () {
|
||||
approx.equal(parseAndEval('2 - (2 - 2)'), 2);
|
||||
approx.equal(parseAndEval('2 - ((2 - 2) - 2)'), 4);
|
||||
approx.equal(parseAndEval('3 * (2 + 3)'), 15);
|
||||
approx.equal(parseAndEval('(2 + 3) * 3'), 15);
|
||||
});
|
||||
|
||||
it('should throw an error in case of unclosed parentheses', function () {
|
||||
assert.throws(function () {parseAndEval('3 * (1 + 2');}, /Parenthesis \) expected/);
|
||||
});
|
||||
});
|
||||
|
||||
describe ('operators', function () {
|
||||
|
||||
it('should parse operations', function() {
|
||||
approx.equal(parseAndEval('(2+3)/4'), 1.25);
|
||||
approx.equal(parseAndEval('2+3/4'), 2.75);
|
||||
assert.equal(parse('0 + 2').toString(), '0 + 2');
|
||||
});
|
||||
|
||||
it('should parse add +', function() {
|
||||
assert.equal(parseAndEval('2 + 3'), 5);
|
||||
assert.equal(parseAndEval('2 + 3 + 4'), 9);
|
||||
assert.equal(parseAndEval('2.+3'), 5); // test whether the decimal mark isn't confused
|
||||
});
|
||||
|
||||
it('should parse divide /', function() {
|
||||
assert.equal(parseAndEval('4 / 2'), 2);
|
||||
assert.equal(parseAndEval('8 / 2 / 2'), 2);
|
||||
});
|
||||
|
||||
it('should parse dotDivide ./', function() {
|
||||
assert.equal(parseAndEval('4./2'), 2);
|
||||
assert.deepEqual(parseAndEval('4./[2,4]'), math.matrix([2,1]));
|
||||
assert.equal(parseAndEval('4 ./ 2'), 2);
|
||||
assert.equal(parseAndEval('8 ./ 2 / 2'), 2);
|
||||
|
||||
assert.deepEqual(parseAndEval('[1,2,3] ./ [1,2,3]'), math.matrix([1,1,1]));
|
||||
});
|
||||
|
||||
it('should parse dotMultiply .*', function() {
|
||||
approx.deepEqual(parseAndEval('2.*3'), 6);
|
||||
approx.deepEqual(parseAndEval('2e3.*3'), 6e3);
|
||||
approx.deepEqual(parseAndEval('2 .* 3'), 6);
|
||||
approx.deepEqual(parseAndEval('4 .* 2'), 8);
|
||||
approx.deepEqual(parseAndEval('8 .* 2 .* 2'), 32);
|
||||
assert.deepEqual(parseAndEval('a=3; a.*4'), new ResultSet([12]));
|
||||
|
||||
assert.deepEqual(parseAndEval('[1,2,3] .* [1,2,3]'), math.matrix([1,4,9]));
|
||||
});
|
||||
|
||||
it('should parse dotPower .^', function() {
|
||||
approx.deepEqual(parseAndEval('2.^3'), 8);
|
||||
approx.deepEqual(parseAndEval('2 .^ 3'), 8);
|
||||
approx.deepEqual(parseAndEval('-2.^2'), -4); // -(2^2)
|
||||
approx.deepEqual(parseAndEval('2.^3.^4'), 2.41785163922926e+24); // 2^(3^4)
|
||||
|
||||
assert.deepEqual(parseAndEval('[2,3] .^ [2,3]'), math.matrix([4,27]));
|
||||
});
|
||||
|
||||
it('should parse equal ==', function() {
|
||||
assert.strictEqual(parseAndEval('2 == 3'), false);
|
||||
assert.strictEqual(parseAndEval('2 == 2'), true);
|
||||
assert.deepEqual(parseAndEval('[2,3] == [2,4]'), math.matrix([true, false]));
|
||||
});
|
||||
|
||||
it('should parse larger >', function() {
|
||||
assert.equal(parseAndEval('2 > 3'), false);
|
||||
assert.equal(parseAndEval('2 > 2'), false);
|
||||
assert.equal(parseAndEval('2 > 1'), true);
|
||||
});
|
||||
|
||||
it('should parse largerEq >=', function() {
|
||||
assert.equal(parseAndEval('2 >= 3'), false);
|
||||
assert.equal(parseAndEval('2 >= 2'), true);
|
||||
assert.equal(parseAndEval('2 >= 1'), true);
|
||||
});
|
||||
|
||||
it('should parse mod %', function() {
|
||||
approx.equal(parseAndEval('8 % 3'), 2);
|
||||
});
|
||||
|
||||
it('should parse operator mod', function() {
|
||||
approx.equal(parseAndEval('8 mod 3'), 2);
|
||||
});
|
||||
|
||||
it('should parse multiply *', function() {
|
||||
approx.equal(parseAndEval('4 * 2'), 8);
|
||||
approx.equal(parseAndEval('8 * 2 * 2'), 32);
|
||||
});
|
||||
|
||||
it('should parse implicit multiplication', function() {
|
||||
assert.equal(parseAndEval('4a', {a:2}), 8);
|
||||
assert.equal(parseAndEval('4 a', {a:2}), 8);
|
||||
assert.equal(parseAndEval('a b', {a: 2, b: 4}), 8);
|
||||
assert.equal(parseAndEval('2a b', {a: 2, b: 4}), 16);
|
||||
assert.equal(parseAndEval('2a * b', {a: 2, b: 4}), 16);
|
||||
assert.equal(parseAndEval('2a / b', {a: 2, b: 4}), 1);
|
||||
assert.equal(parseAndEval('a b c', {a: 2, b: 4, c: 6}), 48);
|
||||
assert.equal(parseAndEval('a b*c', {a: 2, b: 4, c: 6}), 48);
|
||||
assert.equal(parseAndEval('a*b c', {a: 2, b: 4, c: 6}), 48);
|
||||
assert.equal(parseAndEval('a/b c', {a: 4, b: 2, c: 6}), 12);
|
||||
|
||||
assert.equal(parseAndEval('1/2a', {a:2}), 1);
|
||||
assert.equal(parseAndEval('8/2a/2', {a:2}), 4);
|
||||
assert.equal(parseAndEval('8/2a*2', {a:2}), 16);
|
||||
assert.equal(parseAndEval('4*2a', {a:2}), 16);
|
||||
assert.equal(parseAndEval('3!10'), 60);
|
||||
|
||||
assert.equal(parseAndEval('(2+3)a', {a:2}), 10);
|
||||
assert.equal(parseAndEval('(2+3)2'), 10);
|
||||
assert.equal(parseAndEval('(2)(3)+4'), 10);
|
||||
assert.equal(parseAndEval('2(3+4)'), 14);
|
||||
assert.equal(parseAndEval('(2+3)-2'), 3); // no implicit multiplication, just a unary minus
|
||||
assert.equal(parseAndEval('a(2+3)', {a: function() {return 42;}}), 42); // function call
|
||||
assert.equal(parseAndEval('a.b(2+3)', {a: {b: function() {return 42;}}}), 42); // function call
|
||||
assert.equal(parseAndEval('(2+3)(4+5)'), 45); // implicit multiplication
|
||||
assert.equal(parseAndEval('(2+3)(4+5)(3-1)'), 90); // implicit multiplication
|
||||
|
||||
assert.equal(parseAndEval('(2a)^3', {a:2}), 64);
|
||||
assert.equal(parseAndEval('2a^3', {a:2}), 16);
|
||||
assert.equal(parseAndEval('2(a)^3', {a:2}), 16);
|
||||
assert.equal(parseAndEval('(2)a^3', {a:2}), 16);
|
||||
assert.equal(parseAndEval('2^3a', {a:2}), 16);
|
||||
assert.equal(parseAndEval('2^3(a)', {a:2}), 16);
|
||||
assert.equal(parseAndEval('2^(3)(a)', {a:2}), 16);
|
||||
assert.equal(parseAndEval('sqrt(2a)', {a:2}), 2);
|
||||
|
||||
assert.deepEqual(parseAndEval('[2, 3] 2'), math.matrix([4, 6]));
|
||||
assert.deepEqual(parseAndEval('[2, 3] a', {a:2}), math.matrix([4, 6]));
|
||||
assert.deepEqual(parseAndEval('A [2,2]', {A: [[1,2], [3,4]]}), 4); // index
|
||||
assert.deepEqual(parseAndEval('(A) [2,2]', {A: [[1,2], [3,4]]}), 4); // index
|
||||
|
||||
assert.deepEqual(parseAndEval('[1,2;3,4] [2,2]'), 4); // index
|
||||
assert.deepEqual(parseAndEval('([1,2;3,4])[2,2]'), 4); // index
|
||||
assert.throws(function () {parseAndEval('2[1,2,3]')}, /Unexpected operator/);// index
|
||||
});
|
||||
|
||||
it('should tell the OperatorNode about implicit multiplications', function() {
|
||||
assert.equal(parse('2 + 3').implicit, false);
|
||||
assert.equal(parse('4 * a').implicit, false);
|
||||
|
||||
assert.equal(parse('4a').implicit, true);
|
||||
assert.equal(parse('4 a').implicit, true);
|
||||
assert.equal(parse('a b').implicit, true);
|
||||
assert.equal(parse('2a b').implicit, true);
|
||||
assert.equal(parse('a b c').implicit, true);
|
||||
|
||||
assert.equal(parse('(2+3)a').implicit, true);
|
||||
assert.equal(parse('(2+3)2').implicit, true);
|
||||
assert.equal(parse('2(3+4)').implicit, true);
|
||||
});
|
||||
|
||||
it('should correctly order consecutive multiplications and implicit multiplications', function() {
|
||||
var node = parse('9km*3km');
|
||||
assert.equal(node.toString({parenthesis: 'all'}), '((9 km) * 3) km');
|
||||
});
|
||||
|
||||
it('should throw an error when having an implicit multiplication between two numbers', function() {
|
||||
assert.throws(function () { math.parse('2 3'); }, /Unexpected part "3"/);
|
||||
assert.throws(function () { math.parse('2 * 3 4'); }, /Unexpected part "4"/);
|
||||
assert.throws(function () { math.parse('2 * 3 4 * 5'); }, /Unexpected part "4"/);
|
||||
assert.throws(function () { math.parse('2 / 3 4 5'); }, /Unexpected part "4"/);
|
||||
assert.throws(function () { math.parse('2 + 3 4'); }, /Unexpected part "4"/);
|
||||
assert.throws(function () { math.parse('-2 2'); }, /Unexpected part "2"/);
|
||||
assert.throws(function () { math.parse('+3 3'); }, /Unexpected part "3"/);
|
||||
assert.throws(function () { math.parse('2^3 4'); }, /Unexpected part "4"/);
|
||||
});
|
||||
|
||||
it('should parse pow ^', function() {
|
||||
approx.equal(parseAndEval('2^3'), 8);
|
||||
approx.equal(parseAndEval('-2^2'), -4); // -(2^2)
|
||||
approx.equal(parseAndEval('2^3^4'), 2.41785163922926e+24); // 2^(3^4)
|
||||
});
|
||||
|
||||
it('should parse smaller <', function() {
|
||||
assert.strictEqual(parseAndEval('2 < 3'), true);
|
||||
assert.strictEqual(parseAndEval('2 < 2'), false);
|
||||
assert.strictEqual(parseAndEval('2 < 1'), false);
|
||||
});
|
||||
|
||||
it('should parse smallerEq <=', function() {
|
||||
assert.strictEqual(parseAndEval('2 <= 3'), true);
|
||||
assert.strictEqual(parseAndEval('2 <= 2'), true);
|
||||
assert.strictEqual(parseAndEval('2 <= 1'), false);
|
||||
});
|
||||
|
||||
it('should parse bitwise and &', function() {
|
||||
assert.strictEqual(parseAndEval('2 & 6'), 2);
|
||||
assert.strictEqual(parseAndEval('5 & 3'), 1);
|
||||
assert.strictEqual(parseAndEval('true & true'), 1);
|
||||
assert.strictEqual(parseAndEval('true & false'), 0);
|
||||
assert.strictEqual(parseAndEval('false & true'), 0);
|
||||
assert.strictEqual(parseAndEval('false & false'), 0);
|
||||
});
|
||||
|
||||
it('should parse bitwise xor ^|', function() {
|
||||
assert.strictEqual(parseAndEval('2 ^| 6'), 4);
|
||||
assert.strictEqual(parseAndEval('5 ^| 3'), 6);
|
||||
assert.strictEqual(parseAndEval('true ^| true'), 0);
|
||||
assert.strictEqual(parseAndEval('true ^| false'), 1);
|
||||
assert.strictEqual(parseAndEval('false ^| true'), 1);
|
||||
assert.strictEqual(parseAndEval('false ^| false'), 0);
|
||||
});
|
||||
|
||||
it('should parse bitwise or |', function() {
|
||||
assert.strictEqual(parseAndEval('2 | 6'), 6);
|
||||
assert.strictEqual(parseAndEval('5 | 3'), 7);
|
||||
assert.strictEqual(parseAndEval('true | true'), 1);
|
||||
assert.strictEqual(parseAndEval('true | false'), 1);
|
||||
assert.strictEqual(parseAndEval('false | true'), 1);
|
||||
assert.strictEqual(parseAndEval('false | false'), 0);
|
||||
});
|
||||
|
||||
it('should parse bitwise left shift <<', function() {
|
||||
assert.strictEqual(parseAndEval('23 << 1'), 46);
|
||||
});
|
||||
|
||||
it('should parse bitwise right arithmetic shift >>', function() {
|
||||
assert.strictEqual(parseAndEval('32 >> 4'), 2);
|
||||
assert.strictEqual(parseAndEval('-12 >> 2'), -3);
|
||||
});
|
||||
|
||||
it('should parse bitwise right logical shift >>>', function() {
|
||||
assert.strictEqual(parseAndEval('32 >>> 4'), 2);
|
||||
assert.strictEqual(parseAndEval('-12 >>> 2'), 1073741821);
|
||||
});
|
||||
|
||||
it('should parse logical and', function() {
|
||||
assert.strictEqual(parseAndEval('2 and 6'), true);
|
||||
assert.strictEqual(parseAndEval('2 and 0'), false);
|
||||
assert.strictEqual(parseAndEval('true and true'), true);
|
||||
assert.strictEqual(parseAndEval('true and false'), false);
|
||||
assert.strictEqual(parseAndEval('false and true'), false);
|
||||
assert.strictEqual(parseAndEval('false and false'), false);
|
||||
});
|
||||
|
||||
it('should parse logical xor', function() {
|
||||
assert.strictEqual(parseAndEval('2 xor 6'), false);
|
||||
assert.strictEqual(parseAndEval('2 xor 0'), true);
|
||||
assert.strictEqual(parseAndEval('true xor true'), false);
|
||||
assert.strictEqual(parseAndEval('true xor false'), true);
|
||||
assert.strictEqual(parseAndEval('false xor true'), true);
|
||||
assert.strictEqual(parseAndEval('false xor false'), false);
|
||||
});
|
||||
|
||||
it('should parse logical or', function() {
|
||||
assert.strictEqual(parseAndEval('2 or 6'), true);
|
||||
assert.strictEqual(parseAndEval('2 or 0'), true);
|
||||
assert.strictEqual(parseAndEval('true or true'), true);
|
||||
assert.strictEqual(parseAndEval('true or false'), true);
|
||||
assert.strictEqual(parseAndEval('false or true'), true);
|
||||
assert.strictEqual(parseAndEval('false or false'), false);
|
||||
});
|
||||
|
||||
it('should parse logical not', function() {
|
||||
assert.strictEqual(parseAndEval('not 2'), false);
|
||||
assert.strictEqual(parseAndEval('not not 2'), true);
|
||||
assert.strictEqual(parseAndEval('not not not 2'), false);
|
||||
assert.strictEqual(parseAndEval('not true'), false);
|
||||
|
||||
assert.strictEqual(parseAndEval('4*not 2'), 0);
|
||||
assert.strictEqual(parseAndEval('4 * not 2'), 0);
|
||||
assert.strictEqual(parseAndEval('4-not 2'), 4);
|
||||
assert.strictEqual(parseAndEval('4 - not 2'), 4);
|
||||
assert.strictEqual(parseAndEval('4+not 2'), 4);
|
||||
assert.strictEqual(parseAndEval('4 + not 2'), 4);
|
||||
|
||||
assert.strictEqual(parseAndEval('10+not not 3'), 11);
|
||||
});
|
||||
|
||||
it('should parse minus -', function() {
|
||||
assert.equal(parseAndEval('4 - 2'), 2);
|
||||
assert.equal(parseAndEval('8 - 2 - 2'), 4);
|
||||
});
|
||||
|
||||
it('should parse unary minus -', function() {
|
||||
assert.equal(parseAndEval('-2'), -2);
|
||||
assert.equal(parseAndEval('--2'), 2);
|
||||
assert.equal(parseAndEval('---2'), -2);
|
||||
|
||||
assert.equal(parseAndEval('4*-2'), -8);
|
||||
assert.equal(parseAndEval('4 * -2'), -8);
|
||||
assert.equal(parseAndEval('4+-2'), 2);
|
||||
assert.equal(parseAndEval('4 + -2'), 2);
|
||||
assert.equal(parseAndEval('4--2'), 6);
|
||||
assert.equal(parseAndEval('4 - -2'), 6);
|
||||
|
||||
assert.equal(parseAndEval('5-3'), 2);
|
||||
assert.equal(parseAndEval('5--3'), 8);
|
||||
assert.equal(parseAndEval('5---3'), 2);
|
||||
assert.equal(parseAndEval('5+---3'), 2);
|
||||
assert.equal(parseAndEval('5----3'), 8);
|
||||
assert.equal(parseAndEval('5+--(2+1)'), 8);
|
||||
});
|
||||
|
||||
it('should parse unary +', function() {
|
||||
assert.equal(parseAndEval('+2'), 2);
|
||||
assert.equal(parseAndEval('++2'), 2);
|
||||
assert.equal(parseAndEval('+++2'), 2);
|
||||
assert.equal(parseAndEval('+true'), 1);
|
||||
|
||||
assert.equal(parseAndEval('4*+2'), 8);
|
||||
assert.equal(parseAndEval('4 * +2'), 8);
|
||||
assert.equal(parseAndEval('4-+2'), 2);
|
||||
assert.equal(parseAndEval('4 - +2'), 2);
|
||||
assert.equal(parseAndEval('4++2'), 6);
|
||||
assert.equal(parseAndEval('4 + +2'), 6);
|
||||
|
||||
assert.equal(parseAndEval('5+3'), 8);
|
||||
assert.equal(parseAndEval('5++3'), 8);
|
||||
});
|
||||
|
||||
it('should parse unary ~', function() {
|
||||
assert.equal(parseAndEval('~2'), -3);
|
||||
assert.equal(parseAndEval('~~2'), 2);
|
||||
assert.equal(parseAndEval('~~~2'), -3);
|
||||
assert.equal(parseAndEval('~true'), -2);
|
||||
|
||||
assert.equal(parseAndEval('4*~2'), -12);
|
||||
assert.equal(parseAndEval('4 * ~2'), -12);
|
||||
assert.equal(parseAndEval('4-~2'), 7);
|
||||
assert.equal(parseAndEval('4 - ~2'), 7);
|
||||
assert.equal(parseAndEval('4+~2'), 1);
|
||||
assert.equal(parseAndEval('4 + ~2'), 1);
|
||||
|
||||
assert.equal(parseAndEval('10+~~3'), 13);
|
||||
});
|
||||
|
||||
it('should parse unary plus and minus +, -', function() {
|
||||
assert.equal(parseAndEval('-+2'), -2);
|
||||
assert.equal(parseAndEval('-+-2'), 2);
|
||||
assert.equal(parseAndEval('+-+-2'), 2);
|
||||
assert.equal(parseAndEval('+-2'), -2);
|
||||
assert.equal(parseAndEval('+-+2'), -2);
|
||||
assert.equal(parseAndEval('-+-+2'), 2);
|
||||
});
|
||||
|
||||
it('should parse unary plus and bitwise not +, ~', function() {
|
||||
assert.equal(parseAndEval('~+2'), -3);
|
||||
assert.equal(parseAndEval('~+~2'), 2);
|
||||
assert.equal(parseAndEval('+~+~2'), 2);
|
||||
assert.equal(parseAndEval('+~2'), -3);
|
||||
assert.equal(parseAndEval('+~+2'), -3);
|
||||
assert.equal(parseAndEval('~+~+2'), 2);
|
||||
});
|
||||
|
||||
it('should parse unary minus and bitwise not -, ~', function() {
|
||||
assert.equal(parseAndEval('~-2'), 1);
|
||||
assert.equal(parseAndEval('~-~2'), -4);
|
||||
assert.equal(parseAndEval('-~-~2'), 4);
|
||||
assert.equal(parseAndEval('-~2'), 3);
|
||||
assert.equal(parseAndEval('-~-2'), -1);
|
||||
assert.equal(parseAndEval('~-~-2'), 0);
|
||||
});
|
||||
|
||||
it('should parse unary plus + and logical not', function() {
|
||||
assert.equal(parseAndEval('not+2'), false);
|
||||
assert.equal(parseAndEval('not + not 2'), true);
|
||||
assert.equal(parseAndEval('+not+not 2'), 1);
|
||||
assert.equal(parseAndEval('+ not 2'), 0);
|
||||
assert.equal(parseAndEval('+ not +2'), 0);
|
||||
assert.equal(parseAndEval('not + not +2'), true);
|
||||
});
|
||||
|
||||
it('should parse bitwise not ~ and logical not', function() {
|
||||
assert.equal(parseAndEval('~not 2'), -1);
|
||||
assert.equal(parseAndEval('~not~2'), -1);
|
||||
assert.equal(parseAndEval('not~not~2'), false);
|
||||
assert.equal(parseAndEval('not~2'), false);
|
||||
assert.equal(parseAndEval('not~not 2'), false);
|
||||
assert.equal(parseAndEval('~not~not 2'), -1);
|
||||
});
|
||||
|
||||
it('should parse unary minus and logical not', function() {
|
||||
assert.equal(parseAndEval('not-2'), false);
|
||||
assert.equal(parseAndEval('not-not 2'), true);
|
||||
assert.equal(parseAndEval('-not-not 2'), -1);
|
||||
assert.equal(parseAndEval('-not 2'), -0);
|
||||
assert.equal(parseAndEval('-not-2'), -0);
|
||||
assert.equal(parseAndEval('not-not-2'), true);
|
||||
});
|
||||
|
||||
it('should parse unequal !=', function() {
|
||||
assert.strictEqual(parseAndEval('2 != 3'), true);
|
||||
assert.strictEqual(parseAndEval('2 != 2'), false);
|
||||
assert.deepEqual(parseAndEval('[2,3] != [2,4]'), math.matrix([false, true]));
|
||||
});
|
||||
|
||||
it('should parse conditional expression a ? b : c', function() {
|
||||
assert.equal(parseAndEval('2 ? true : false'), true);
|
||||
assert.equal(parseAndEval('0 ? true : false'), false);
|
||||
assert.equal(parseAndEval('false ? true : false'), false);
|
||||
|
||||
assert.equal(parseAndEval('2 > 0 ? 1 : 2 < 0 ? -1 : 0'), 1);
|
||||
assert.equal(parseAndEval('(2 > 0 ? 1 : 2 < 0) ? -1 : 0'), -1);
|
||||
assert.equal(parseAndEval('-2 > 0 ? 1 : -2 < 0 ? -1 : 0'), -1);
|
||||
assert.equal(parseAndEval('0 > 0 ? 1 : 0 < 0 ? -1 : 0'), 0);
|
||||
});
|
||||
|
||||
it('should lazily evaluate conditional expression a ? b : c', function() {
|
||||
var scope = {};
|
||||
math.parse('true ? (a = 2) : (b = 2)').compile().eval(scope);
|
||||
assert.deepEqual(scope, {a: 2});
|
||||
});
|
||||
|
||||
it('should throw an error when false part of conditional expression is missing', function() {
|
||||
assert.throws(function() {parseAndEval('2 ? true');}, /False part of conditional expression expected/);
|
||||
});
|
||||
|
||||
it('should parse : (range)', function() {
|
||||
assert.ok(parseAndEval('2:5') instanceof Matrix);
|
||||
assert.deepEqual(parseAndEval('2:5'), math.matrix([2,3,4,5]));
|
||||
assert.deepEqual(parseAndEval('10:-2:0'), math.matrix([10,8,6,4,2,0]));
|
||||
assert.deepEqual(parseAndEval('2:4.0'), math.matrix([2,3,4]));
|
||||
assert.deepEqual(parseAndEval('2:4.5'), math.matrix([2,3,4]));
|
||||
assert.deepEqual(parseAndEval('2:4.1'), math.matrix([2,3,4]));
|
||||
assert.deepEqual(parseAndEval('2:3.9'), math.matrix([2,3]));
|
||||
assert.deepEqual(parseAndEval('2:3.5'), math.matrix([2,3]));
|
||||
assert.deepEqual(parseAndEval('3:-1:0.5'), math.matrix([3,2,1]));
|
||||
assert.deepEqual(parseAndEval('3:-1:0.5'), math.matrix([3,2,1]));
|
||||
assert.deepEqual(parseAndEval('3:-1:0.1'), math.matrix([3,2,1]));
|
||||
assert.deepEqual(parseAndEval('3:-1:-0.1'), math.matrix([3,2,1,0]));
|
||||
});
|
||||
|
||||
it('should parse to', function() {
|
||||
approx.deepEqual(parseAndEval('2.54 cm to inch'), math.unit(1, 'inch').to('inch'));
|
||||
approx.deepEqual(parseAndEval('2.54 cm + 2 inch to foot'), math.unit(0.25, 'foot').to('foot'));
|
||||
});
|
||||
|
||||
it('should parse in', function() {
|
||||
approx.deepEqual(parseAndEval('2.54 cm in inch'), math.unit(1, 'inch').to('inch'));
|
||||
});
|
||||
|
||||
it('should parse factorial !', function() {
|
||||
assert.deepEqual(parseAndEval('5!'), 120);
|
||||
assert.deepEqual(parseAndEval('[1,2,3,4]!'), math.matrix([1,2,6,24]));
|
||||
assert.deepEqual(parseAndEval('4!+2'), 26);
|
||||
assert.deepEqual(parseAndEval('4!-2'), 22);
|
||||
assert.deepEqual(parseAndEval('4!*2'), 48);
|
||||
assert.deepEqual(parseAndEval('3!!'), 720);
|
||||
assert.deepEqual(parseAndEval('[1,2;3,1]!\'!'), math.matrix([[1, 720], [2, 1]]));
|
||||
assert.deepEqual(parseAndEval('[4,5]![2]'), 120); // index [2]
|
||||
});
|
||||
|
||||
it('should parse transpose \'', function() {
|
||||
assert.deepEqual(parseAndEval('23\''), 23);
|
||||
assert.deepEqual(parseAndEval('[1,2,3;4,5,6]\''), math.matrix([[1,4],[2,5],[3,6]]));
|
||||
assert.ok(parseAndEval('[1,2,3;4,5,6]\'') instanceof Matrix);
|
||||
assert.deepEqual(parseAndEval('[1:5]'), math.matrix([[1,2,3,4,5]]));
|
||||
assert.deepEqual(parseAndEval('[1:5]\''), math.matrix([[1],[2],[3],[4],[5]]));
|
||||
assert.deepEqual(parseAndEval('size([1:5])'), math.matrix([1, 5]));
|
||||
assert.deepEqual(parseAndEval('[1,2;3,4]\''), math.matrix([[1,3],[2,4]]));
|
||||
});
|
||||
|
||||
describe('operator precedence', function() {
|
||||
it('should respect precedence of plus and minus', function () {
|
||||
assert.equal(parseAndEval('4-2+3'), 5);
|
||||
assert.equal(parseAndEval('4-(2+3)'), -1);
|
||||
assert.equal(parseAndEval('4-2-3'), -1);
|
||||
assert.equal(parseAndEval('4-(2-3)'), 5);
|
||||
});
|
||||
|
||||
it('should respect precedence of plus/minus and multiply/divide', function () {
|
||||
assert.equal(parseAndEval('2+3*4'), 14);
|
||||
assert.equal(parseAndEval('2*3+4'), 10);
|
||||
});
|
||||
|
||||
it('should respect precedence of plus/minus and pow', function () {
|
||||
assert.equal(parseAndEval('2+3^2'), 11);
|
||||
assert.equal(parseAndEval('3^2+2'), 11);
|
||||
assert.equal(parseAndEval('8-2^2'), 4);
|
||||
assert.equal(parseAndEval('4^2-2'), 14);
|
||||
});
|
||||
|
||||
it('should respect precedence of multiply/divide and pow', function () {
|
||||
assert.equal(parseAndEval('2*3^2'), 18);
|
||||
assert.equal(parseAndEval('3^2*2'), 18);
|
||||
assert.equal(parseAndEval('8/2^2'), 2);
|
||||
assert.equal(parseAndEval('4^2/2'), 8);
|
||||
});
|
||||
|
||||
it('should respect precedence of pow', function () {
|
||||
assert.equal(parseAndEval('2^3'), 8);
|
||||
assert.equal(parseAndEval('2^3^4'), Math.pow(2, Math.pow(3, 4)));
|
||||
assert.equal(parseAndEval('1.5^1.5^1.5'), parseAndEval('1.5^(1.5^1.5)'));
|
||||
assert.equal(parseAndEval('1.5^1.5^1.5^1.5'), parseAndEval('1.5^(1.5^(1.5^1.5))'));
|
||||
});
|
||||
|
||||
it('should respect precedence of unary operations and pow', function () {
|
||||
assert.equal(parseAndEval('-3^2'), -9);
|
||||
assert.equal(parseAndEval('(-3)^2'), 9);
|
||||
assert.equal(parseAndEval('2^-2'), 0.25);
|
||||
assert.equal(parseAndEval('2^(-2)'), 0.25);
|
||||
|
||||
assert.equal(parseAndEval('+3^2'), 9);
|
||||
assert.equal(parseAndEval('(+3)^2'), 9);
|
||||
assert.equal(parseAndEval('2^(+2)'), 4);
|
||||
|
||||
assert.equal(parseAndEval('~3^2'), -10);
|
||||
assert.equal(parseAndEval('(~3)^2'), 16);
|
||||
assert.equal(parseAndEval('2^~2'), 0.125);
|
||||
assert.equal(parseAndEval('2^(~2)'), 0.125);
|
||||
|
||||
assert.equal(parseAndEval('not 3^2'), false);
|
||||
assert.equal(parseAndEval('(not 3)^2'), 0);
|
||||
assert.equal(parseAndEval('2^not 2'), 1);
|
||||
assert.equal(parseAndEval('2^(not 2)'), 1);
|
||||
});
|
||||
|
||||
it('should respect precedence of factorial and pow', function () {
|
||||
assert.equal(parseAndEval('2^3!'), 64);
|
||||
assert.equal(parseAndEval('2^(3!)'), 64);
|
||||
assert.equal(parseAndEval('3!^2'), 36);
|
||||
});
|
||||
|
||||
it('should respect precedence of factorial and unary operations', function () {
|
||||
assert.equal(parseAndEval('-4!'), -24);
|
||||
assert.equal(parseAndEval('-(4!)'), -24);
|
||||
|
||||
assert.equal(parseAndEval('3!+2'), 8);
|
||||
assert.equal(parseAndEval('(3!)+2'), 8);
|
||||
assert.equal(parseAndEval('+4!'), 24);
|
||||
|
||||
assert.equal(parseAndEval('~4!+1'), -24);
|
||||
assert.equal(parseAndEval('~(4!)+1'), -24);
|
||||
|
||||
assert.equal(parseAndEval('not 4!'), false);
|
||||
assert.equal(parseAndEval('not not 4!'), true);
|
||||
assert.equal(parseAndEval('not(4!)'), false);
|
||||
assert.equal(parseAndEval('(not 4!)'), false);
|
||||
assert.equal(parseAndEval('(not 4)!'), 1);
|
||||
});
|
||||
|
||||
it('should respect precedence of transpose', function () {
|
||||
var node = math.parse('a + b\'');
|
||||
assert(node instanceof OperatorNode);
|
||||
assert.equal(node.op, '+');
|
||||
assert.equal(node.args[0].toString(), 'a');
|
||||
assert.equal(node.args[1].toString(), 'b\'');
|
||||
});
|
||||
|
||||
it('should respect precedence of transpose (2)', function () {
|
||||
var node = math.parse('a ^ b\'');
|
||||
assert(node instanceof OperatorNode);
|
||||
assert.equal(node.op, '^');
|
||||
assert.equal(node.args[0].toString(), 'a');
|
||||
assert.equal(node.args[1].toString(), 'b\'');
|
||||
});
|
||||
|
||||
it('should respect precedence of conditional operator and other operators', function () {
|
||||
assert.equal(parseAndEval('2 > 3 ? true : false'), false);
|
||||
assert.equal(parseAndEval('2 == 3 ? true : false'), false);
|
||||
assert.equal(parseAndEval('3 ? 2 + 4 : 2 - 1'), 6);
|
||||
assert.deepEqual(parseAndEval('3 ? true : false; 22'), new ResultSet([22]));
|
||||
assert.deepEqual(parseAndEval('3 ? 5cm to m : 5cm in mm'), new Unit(5, 'cm').to('m'));
|
||||
assert.deepEqual(parseAndEval('2 == 4-2 ? [1,2] : false'), math.matrix([1,2]));
|
||||
assert.deepEqual(parseAndEval('false ? 1:2:6'), math.matrix([2,3,4,5,6]));
|
||||
});
|
||||
|
||||
it('should respect precedence between left/right shift and relational operators', function () {
|
||||
assert.strictEqual(parseAndEval('32 >> 4 == 2'), true);
|
||||
assert.strictEqual(parseAndEval('2 == 32 >> 4'), true);
|
||||
assert.strictEqual(parseAndEval('2 << 2 == 8'), true);
|
||||
assert.strictEqual(parseAndEval('8 == 2 << 2'), true);
|
||||
});
|
||||
|
||||
it('should respect precedence between relational operators and bitwise and', function () {
|
||||
assert.strictEqual(parseAndEval('2 == 3 & 1'), 0);
|
||||
assert.strictEqual(parseAndEval('3 & 1 == 2'), 0);
|
||||
assert.strictEqual(parseAndEval('2 == (3 & 1)'), false);
|
||||
});
|
||||
|
||||
it('should respect precedence between bitwise or | and logical and', function () {
|
||||
assert.strictEqual(parseAndEval('2 | 2 and 4'), true);
|
||||
assert.strictEqual(parseAndEval('4 and 2 | 2'), true);
|
||||
});
|
||||
|
||||
it('should respect precedence between bitwise xor ^| and bitwise or |', function () {
|
||||
assert.strictEqual(parseAndEval('4 ^| 6 | 2'), 2);
|
||||
assert.strictEqual(parseAndEval('2 | 4 ^| 6'), 2);
|
||||
assert.strictEqual(parseAndEval('(2 | 4) ^| 6'), 0);
|
||||
});
|
||||
|
||||
it('should respect precedence between bitwise and & and bitwise or |', function () {
|
||||
assert.strictEqual(parseAndEval('4 & 3 | 12'), 12);
|
||||
assert.strictEqual(parseAndEval('12 | 4 & 3'), 12);
|
||||
assert.strictEqual(parseAndEval('(12 | 4) & 3'), 0);
|
||||
});
|
||||
|
||||
it('should respect precedence between logical and and or', function () {
|
||||
assert.strictEqual(parseAndEval('false and true or true'), true);
|
||||
assert.strictEqual(parseAndEval('false and (true or true)'), false);
|
||||
assert.strictEqual(parseAndEval('true or true and false'), true);
|
||||
assert.strictEqual(parseAndEval('(true or true) and false'), false);
|
||||
});
|
||||
|
||||
it('should respect precedence of conditional operator and logical or', function () {
|
||||
var node = math.parse('1 or 0 ? 2 or 3 : 0 or 0');
|
||||
assert(node instanceof ConditionalNode);
|
||||
assert.equal(node.condition.toString(), '1 or 0');
|
||||
assert.equal(node.trueExpr.toString(), '2 or 3');
|
||||
assert.equal(node.falseExpr.toString(), '0 or 0');
|
||||
assert.strictEqual(node.compile().eval(), true);
|
||||
});
|
||||
|
||||
it('should respect precedence of conditional operator and relational operators', function () {
|
||||
var node = math.parse('a == b ? a > b : a < b');
|
||||
assert(node instanceof ConditionalNode);
|
||||
assert.equal(node.condition.toString(), 'a == b');
|
||||
assert.equal(node.trueExpr.toString(), 'a > b');
|
||||
assert.equal(node.falseExpr.toString(), 'a < b');
|
||||
});
|
||||
|
||||
it('should respect precedence of conditional operator and range operator', function () {
|
||||
var node = math.parse('a ? b : c : d');
|
||||
assert(node instanceof ConditionalNode);
|
||||
assert.equal(node.condition.toString(), 'a');
|
||||
assert.equal(node.trueExpr.toString(), 'b');
|
||||
assert.equal(node.falseExpr.toString(), 'c:d');
|
||||
});
|
||||
|
||||
it('should respect precedence of conditional operator and range operator (2)', function () {
|
||||
var node = math.parse('a ? (b : c) : (d : e)');
|
||||
assert(node instanceof ConditionalNode);
|
||||
assert.equal(node.condition.toString(), 'a');
|
||||
assert.equal(node.trueExpr.toString(), '(b:c)');
|
||||
assert.equal(node.falseExpr.toString(), '(d:e)');
|
||||
});
|
||||
|
||||
it('should respect precedence of conditional operator and range operator (2)', function () {
|
||||
var node = math.parse('a ? (b ? c : d) : (e ? f : g)');
|
||||
assert(node instanceof ConditionalNode);
|
||||
assert.equal(node.condition.toString(), 'a');
|
||||
assert.equal(node.trueExpr.toString(), '(b ? c : d)');
|
||||
assert.equal(node.falseExpr.toString(), '(e ? f : g)');
|
||||
});
|
||||
|
||||
it('should respect precedence of range operator and relational operators', function () {
|
||||
var node = math.parse('a:b == c:d');
|
||||
assert(node instanceof OperatorNode);
|
||||
assert.equal(node.args[0].toString(), 'a:b');
|
||||
assert.equal(node.args[1].toString(), 'c:d');
|
||||
});
|
||||
|
||||
it('should respect precedence of range operator and operator plus and minus', function () {
|
||||
var node = math.parse('a + b : c - d');
|
||||
assert(node instanceof RangeNode);
|
||||
assert.equal(node.start.toString(), 'a + b');
|
||||
assert.equal(node.end.toString(), 'c - d');
|
||||
});
|
||||
|
||||
it('should respect precedence of "to" operator and relational operators', function () {
|
||||
var node = math.parse('a == b to c');
|
||||
assert(node instanceof OperatorNode);
|
||||
assert.equal(node.args[0].toString(), 'a');
|
||||
assert.equal(node.args[1].toString(), 'b to c');
|
||||
});
|
||||
|
||||
it('should respect precedence of "to" operator and relational operators (2)', function () {
|
||||
var node = math.parse('a to b == c');
|
||||
assert(node instanceof OperatorNode);
|
||||
assert.equal(node.args[0].toString(), 'a to b');
|
||||
assert.equal(node.args[1].toString(), 'c');
|
||||
});
|
||||
|
||||
// TODO: extensively test operator precedence
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
describe('functions', function () {
|
||||
it('should evaluate function "mod"', function () {
|
||||
approx.equal(parseAndEval('mod(8, 3)'), 2);
|
||||
|
||||
});
|
||||
|
||||
it('should evaluate function "to" ', function () {
|
||||
approx.deepEqual(parseAndEval('to(5.08 cm * 1000, inch)'),
|
||||
math.unit(2000, 'inch').to('inch'));
|
||||
});
|
||||
|
||||
it('should evaluate function "sort" with a custom sort function', function () {
|
||||
var scope = {};
|
||||
parseAndEval('sortByLength(a, b) = size(a)[1] - size(b)[1]', scope);
|
||||
assert.deepEqual(parseAndEval('sort(["Langdon", "Tom", "Sara"], sortByLength)', scope),
|
||||
math.matrix(["Tom", "Sara", "Langdon"]));
|
||||
});
|
||||
|
||||
it('should evaluate function "filter" with a custom test function', function () {
|
||||
var scope = {};
|
||||
parseAndEval('isPositive(x) = x > 0', scope);
|
||||
assert.deepEqual(parseAndEval('filter([6, -2, -1, 4, 3], isPositive)', scope),
|
||||
math.matrix([6, 4, 3]));
|
||||
});
|
||||
|
||||
it('should evaluate function "filter" with a custom test equation', function () {
|
||||
assert.deepEqual(parseAndEval('filter([6, -2, -1, 4, 3], x > 0)'),
|
||||
math.matrix([6, 4, 3]));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('bignumber', function () {
|
||||
var bigmath = math.create({
|
||||
number: 'BigNumber'
|
||||
});
|
||||
var BigNumber = bigmath.type.BigNumber;
|
||||
|
||||
it('should parse numbers as bignumber', function() {
|
||||
assert.deepEqual(bigmath.bignumber('2.3'), new BigNumber('2.3'));
|
||||
assert.deepEqual(bigmath.eval('2.3'), new BigNumber('2.3'));
|
||||
assert.deepEqual(bigmath.eval('2.3e+500'), new BigNumber('2.3e+500'));
|
||||
});
|
||||
|
||||
it('should evaluate functions supporting bignumbers', function() {
|
||||
assert.deepEqual(bigmath.eval('0.1 + 0.2'), new BigNumber('0.3'));
|
||||
});
|
||||
|
||||
it('should evaluate functions supporting bignumbers', function() {
|
||||
assert.deepEqual(bigmath.eval('add(0.1, 0.2)'), new BigNumber('0.3'));
|
||||
});
|
||||
|
||||
it('should work with mixed numbers and bignumbers', function() {
|
||||
approx.equal(bigmath.eval('pi + 1'), 4.141592653589793);
|
||||
});
|
||||
|
||||
it('should evaluate functions not supporting bignumbers', function() {
|
||||
approx.equal(bigmath.eval('sin(0.1)'), 0.09983341664682815);
|
||||
});
|
||||
|
||||
it('should create a range from bignumbers', function() {
|
||||
assert.deepEqual(bigmath.eval('4:6'),
|
||||
bigmath.matrix([new BigNumber(4), new BigNumber(5), new BigNumber(6)]));
|
||||
assert.deepEqual(bigmath.eval('0:2:4'),
|
||||
bigmath.matrix([new BigNumber(0), new BigNumber(2), new BigNumber(4)]));
|
||||
});
|
||||
|
||||
it('should create a matrix with bignumbers', function() {
|
||||
assert.deepEqual(bigmath.eval('[0.1, 0.2]'),
|
||||
bigmath.matrix([new BigNumber(0.1), new BigNumber(0.2)]));
|
||||
});
|
||||
|
||||
it('should get an element from a matrix with bignumbers', function() {
|
||||
var scope = {};
|
||||
assert.deepEqual(bigmath.eval('a=[0.1, 0.2]', scope),
|
||||
bigmath.matrix([new BigNumber(0.1), new BigNumber(0.2)]));
|
||||
|
||||
assert.deepEqual(bigmath.eval('a[1]', scope), new BigNumber(0.1));
|
||||
assert.deepEqual(bigmath.eval('a[:]', scope),
|
||||
bigmath.matrix([new BigNumber(0.1), new BigNumber(0.2)]));
|
||||
assert.deepEqual(bigmath.eval('a[1:2]', scope),
|
||||
bigmath.matrix([new BigNumber(0.1), new BigNumber(0.2)]));
|
||||
});
|
||||
|
||||
it('should replace elements in a matrix with bignumbers', function() {
|
||||
var scope = {};
|
||||
assert.deepEqual(bigmath.eval('a=[0.1, 0.2]', scope),
|
||||
bigmath.matrix([new BigNumber(0.1), new BigNumber(0.2)]));
|
||||
|
||||
bigmath.eval('a[1] = 0.3', scope);
|
||||
assert.deepEqual(scope.a, bigmath.matrix([new BigNumber(0.3), new BigNumber(0.2)]));
|
||||
bigmath.eval('a[:] = [0.5, 0.6]', scope);
|
||||
assert.deepEqual(scope.a, bigmath.matrix([new BigNumber(0.5), new BigNumber(0.6)]));
|
||||
bigmath.eval('a[1:2] = [0.7, 0.8]', scope);
|
||||
assert.deepEqual(scope.a, bigmath.matrix([new BigNumber(0.7), new BigNumber(0.8)]));
|
||||
});
|
||||
|
||||
it('should work with complex numbers (downgrades bignumbers to number)', function() {
|
||||
assert.deepEqual(bigmath.eval('3i'), new Complex(0, 3));
|
||||
assert.deepEqual(bigmath.eval('2 + 3i'), new Complex(2, 3));
|
||||
assert.deepEqual(bigmath.eval('2 * i'), new Complex(0, 2));
|
||||
});
|
||||
|
||||
it('should work with units', function() {
|
||||
assert.deepEqual(bigmath.eval('2 cm'), new Unit(new BigNumber(2), 'cm'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('scope', function () {
|
||||
|
||||
it('should use a given scope for assignments', function() {
|
||||
var scope = {
|
||||
a: 3,
|
||||
b: 4
|
||||
};
|
||||
assert.deepEqual(parse('a*b').compile().eval(scope), 12);
|
||||
assert.deepEqual(parse('c=5').compile().eval(scope), 5);
|
||||
assert.deepEqual(parse('f(x) = x^a').compile().eval(scope).syntax, 'f(x)');
|
||||
|
||||
|
||||
assert.deepEqual(Object.keys(scope).length, 4);
|
||||
assert.deepEqual(scope.a, 3);
|
||||
assert.deepEqual(scope.b, 4);
|
||||
assert.deepEqual(scope.c, 5);
|
||||
assert.deepEqual(typeof scope.f, 'function');
|
||||
|
||||
assert.equal(scope.f(3), 27);
|
||||
scope.a = 2;
|
||||
assert.equal(scope.f(3), 9);
|
||||
scope.hello = function (name) {
|
||||
return 'hello, ' + name + '!';
|
||||
};
|
||||
assert.deepEqual(parse('hello("jos")').compile().eval(scope), 'hello, jos!');
|
||||
});
|
||||
|
||||
it('should parse undefined symbols, defining symbols, and removing symbols', function() {
|
||||
var scope = {};
|
||||
var n = parse('q');
|
||||
assert.throws(function () { n.compile().eval(scope); });
|
||||
parse('q=33').compile().eval(scope);
|
||||
assert.equal(n.compile().eval(scope), 33);
|
||||
delete scope.q;
|
||||
assert.throws(function () { n.compile().eval(scope); });
|
||||
|
||||
n = parse('qq[1,1]=33');
|
||||
assert.throws(function () { n.compile().eval(scope); });
|
||||
parse('qq=[1,2;3,4]').compile().eval(scope);
|
||||
n.compile().eval(scope);
|
||||
assert.deepEqual(scope.qq, math.matrix([[33,2],[3,4]]));
|
||||
parse('qq=[4]').compile().eval(scope);
|
||||
n.compile().eval(scope);
|
||||
assert.deepEqual(scope.qq, math.matrix([[33]]));
|
||||
delete scope.qq;
|
||||
assert.throws(function () { n.compile().eval(scope); });
|
||||
});
|
||||
|
||||
it('should evaluate a symbol with value null or undefined', function () {
|
||||
assert.equal(parse('a').compile().eval({a: null}), null);
|
||||
assert.equal(parse('a').compile().eval({a: undefined}), undefined);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('errors', function () {
|
||||
|
||||
it('should return IndexErrors with one based indices', function () {
|
||||
// functions throw a zero-based error
|
||||
assert.throws(function () {math.subset([1,2,3], math.index(4));}, /Index out of range \(4 > 2\)/);
|
||||
assert.throws(function () {math.subset([1,2,3], math.index(-2));}, /Index out of range \(-2 < 0\)/);
|
||||
|
||||
// evaluation via parser throws one-based error
|
||||
assert.throws(function () {math.eval('A[4]', {A:[1,2,3]});}, /Index out of range \(4 > 3\)/);
|
||||
assert.throws(function () {math.eval('A[-2]', {A: [1,2,3]});}, /IndexError: Index out of range \(-2 < 1\)/);
|
||||
});
|
||||
|
||||
it('should return DimensionErrors with one based indices (subset)', function () {
|
||||
// TODO: it would be more clear when all errors where DimensionErrors
|
||||
|
||||
// functions throw a zero-based error
|
||||
assert.throws(function () {math.subset([1,2,3], math.index(1,1));}, /DimensionError: Dimension mismatch \(2 != 1\)/);
|
||||
|
||||
// evaluation via parser throws one-based error
|
||||
assert.throws(function () {math.eval('A[1,1]', {A: [1,2,3]});}, /DimensionError: Dimension mismatch \(2 != 1\)/);
|
||||
});
|
||||
|
||||
it('should return DimensionErrors with one based indices (concat)', function () {
|
||||
// TODO: it would be more clear when all errors where DimensionErrors
|
||||
|
||||
// functions throw a zero-based error
|
||||
assert.throws(function () {math.concat([1,2], [[3,4]]);}, /DimensionError: Dimension mismatch \(1 != 2\)/);
|
||||
assert.throws(function () {math.concat([[1,2]], [[3,4]], 2);}, /IndexError: Index out of range \(2 > 1\)/);
|
||||
assert.throws(function () {math.concat([[1,2]], [[3,4]], -1);}, /IndexError: Index out of range \(-1 < 0\)/);
|
||||
|
||||
// evaluation via parser throws one-based error
|
||||
assert.throws(function () {math.eval('concat([1,2], [[3,4]])');}, /DimensionError: Dimension mismatch \(1 != 2\)/);
|
||||
assert.throws(function () {math.eval('concat([[1,2]], [[3,4]], 3)');}, /IndexError: Index out of range \(3 > 2\)/);
|
||||
assert.throws(function () {math.eval('concat([[1,2]], [[3,4]], 0)');}, /IndexError: Index out of range \(0 < 1\)/);
|
||||
});
|
||||
|
||||
it('should return DimensionErrors with one based indices (max)', function () {
|
||||
// TODO: it would be more clear when all errors where DimensionErrors
|
||||
|
||||
// functions throw a zero-based error
|
||||
// TODO
|
||||
|
||||
// evaluation via parser throws one-based error
|
||||
assert.deepEqual(math.eval('max([[1,2], [3,4]])'), 4);
|
||||
assert.deepEqual(math.eval('max([[1,2], [3,4]], 1)'), math.matrix([3, 4]));
|
||||
assert.deepEqual(math.eval('max([[1,2], [3,4]], 2)'), math.matrix([2, 4]));
|
||||
assert.throws(function () {math.eval('max([[1,2], [3,4]], 3)');}, /IndexError: Index out of range \(3 > 2\)/);
|
||||
assert.throws(function () {math.eval('max([[1,2], [3,4]], 0)');}, /IndexError: Index out of range \(0 < 1\)/);
|
||||
});
|
||||
|
||||
it('should return DimensionErrors with one based indices (min)', function () {
|
||||
// TODO: it would be more clear when all errors where DimensionErrors
|
||||
|
||||
// functions throw a zero-based error
|
||||
// TODO
|
||||
|
||||
// evaluation via parser throws one-based error
|
||||
assert.deepEqual(math.eval('min([[1,2], [3,4]])'), 1);
|
||||
assert.deepEqual(math.eval('min([[1,2], [3,4]], 1)'), math.matrix([1, 2]));
|
||||
assert.deepEqual(math.eval('min([[1,2], [3,4]], 2)'), math.matrix([1, 3]));
|
||||
assert.throws(function () {math.eval('min([[1,2], [3,4]], 3)');}, /IndexError: Index out of range \(3 > 2\)/);
|
||||
assert.throws(function () {math.eval('min([[1,2], [3,4]], 0)');}, /IndexError: Index out of range \(0 < 1\)/);
|
||||
});
|
||||
|
||||
it('should return DimensionErrors with one based indices (mean)', function () {
|
||||
// TODO: it would be more clear when all errors where DimensionErrors
|
||||
|
||||
// functions throw a zero-based error
|
||||
// TODO
|
||||
|
||||
// evaluation via parser throws one-based error
|
||||
assert.deepEqual(math.eval('mean([[1,2], [3,4]])'), 2.5);
|
||||
assert.deepEqual(math.eval('mean([[1,2], [3,4]], 1)'), math.matrix([2, 3]));
|
||||
assert.deepEqual(math.eval('mean([[1,2], [3,4]], 2)'), math.matrix([1.5, 3.5]));
|
||||
assert.throws(function () {math.eval('mean([[1,2], [3,4]], 3)');}, /IndexError: Index out of range \(3 > 2\)/);
|
||||
assert.throws(function () {math.eval('mean([[1,2], [3,4]], 0)');}, /IndexError: Index out of range \(0 < 1\)/);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('node tree', function () {
|
||||
|
||||
// TODO: test parsing into a node tree
|
||||
|
||||
it('should correctly stringify a node tree', function() {
|
||||
assert.equal(parse('0').toString(), '0');
|
||||
assert.equal(parse('"hello"').toString(), '"hello"');
|
||||
assert.equal(parse('[1, 2 + 3i, 4]').toString(), '[1, 2 + 3 i, 4]');
|
||||
assert.equal(parse('1/2a').toString(), '1 / 2 a');
|
||||
});
|
||||
|
||||
it('should correctly stringify an index with dot notation', function() {
|
||||
assert.equal(parse('A[2]').toString(), 'A[2]');
|
||||
assert.equal(parse('a["b"]').toString(), 'a["b"]');
|
||||
assert.equal(parse('a.b').toString(), 'a.b');
|
||||
});
|
||||
|
||||
describe('custom nodes', function () {
|
||||
// define a custom node
|
||||
function CustomNode (args) {
|
||||
this.args = args;
|
||||
}
|
||||
CustomNode.prototype = new math.expression.node.Node();
|
||||
CustomNode.prototype.toString = function () {
|
||||
return 'CustomNode';
|
||||
};
|
||||
CustomNode.prototype._compile = function (defs) {
|
||||
var strArgs = [];
|
||||
this.args.forEach(function (arg) {
|
||||
strArgs.push(arg.toString());
|
||||
});
|
||||
return '"CustomNode(' + strArgs.join(', ') + ')"';
|
||||
};
|
||||
CustomNode.prototype.forEach = function (callback) {
|
||||
// we don't have childs
|
||||
};
|
||||
|
||||
var options = {
|
||||
nodes: {
|
||||
custom: CustomNode
|
||||
}
|
||||
};
|
||||
|
||||
it('should parse custom nodes', function() {
|
||||
var node = parse('custom(x, (2+x), sin(x))', options);
|
||||
assert.equal(node.compile().eval(), 'CustomNode(x, (2 + x), sin(x))');
|
||||
});
|
||||
|
||||
it('should parse custom nodes without parameters', function() {
|
||||
var node = parse('custom()', options);
|
||||
assert.equal(node.compile().eval(), 'CustomNode()');
|
||||
assert.equal(node.filter(function (node) {return node instanceof CustomNode;}).length, 1);
|
||||
|
||||
var node2 = parse('custom', options);
|
||||
assert.equal(node2.compile().eval(), 'CustomNode()');
|
||||
assert.equal(node2.filter(function (node) {return node instanceof CustomNode;}).length, 1);
|
||||
});
|
||||
|
||||
it('should throw an error on syntax errors in using custom nodes', function() {
|
||||
assert.throws(function () {parse('custom(x', options);}, /Parenthesis \) expected/);
|
||||
assert.throws(function () {parse('custom(x, ', options);}, /Unexpected end of expression/);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe ('expose test functions', function () {
|
||||
it('should expose isAlpha', function() {
|
||||
assert.ok('should expose isAlpha', typeof math.expression.parse.isAlpha === 'function')
|
||||
});
|
||||
|
||||
it('should expose isValidLatinOrGreek', function() {
|
||||
assert.ok('should expose isAlpha', typeof math.expression.parse.isValidLatinOrGreek === 'function')
|
||||
});
|
||||
|
||||
it('should expose isValidMathSymbol', function() {
|
||||
assert.ok('should expose isAlpha', typeof math.expression.parse.isValidMathSymbol === 'function')
|
||||
});
|
||||
|
||||
it('should expose isWhitespace', function() {
|
||||
assert.ok('should expose isAlpha', typeof math.expression.parse.isWhitespace === 'function')
|
||||
});
|
||||
|
||||
it('should expose isDecimalMark', function() {
|
||||
assert.ok('should expose isAlpha', typeof math.expression.parse.isDecimalMark === 'function')
|
||||
});
|
||||
|
||||
it('should expose isDigitDot', function() {
|
||||
assert.ok('should expose isAlpha', typeof math.expression.parse.isDigitDot === 'function')
|
||||
});
|
||||
|
||||
it('should expose isDigit', function() {
|
||||
assert.ok('should expose isAlpha', typeof math.expression.parse.isDigit === 'function')
|
||||
});
|
||||
|
||||
it('should allow overriding isAlpha', function() {
|
||||
var originalIsAlpha = math.expression.parse.isAlpha;
|
||||
|
||||
// override isAlpha with one accepting $ characters too
|
||||
math.expression.parse.isAlpha = function (c, cPrev, cNext) {
|
||||
return /^[a-zA-Z_$]$/.test(c)
|
||||
};
|
||||
|
||||
const node = math.expression.parse('$foo');
|
||||
const result = node.eval({$foo: 42});
|
||||
assert.equal(result, 42);
|
||||
|
||||
// restore original isAlpha
|
||||
math.expression.parse.isAlpha = originalIsAlpha
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user