mathjs/test/function/expression/parse.test.js

313 lines
11 KiB
JavaScript

// test parse
var assert = require('assert'),
approx = require('../../../tools/approx.js'),
math = require('../../../index.js');
describe('parse', function() {
it('should parse constants', function() {
assert.ok(math.parse('pi') instanceof math.expression.node.Node);
assert.equal(math.parse('pi').eval(), Math.PI);
});
it('should parse arithmetic operations', function() {
assert.equal(math.parse('(2+3)/4').eval(), 1.25);
assert.equal(math.parse('0 + 2').toString(), 'ans = 0 + 2');
});
it('should parse functions', function() {
assert.equal(math.parse('sqrt(-4)').eval().toString(), '2i');
});
it('should parse a series of expressions', function() {
assert.deepEqual(math.parse(['a=3', 'b=4', 'a*b']).map(function (node) {
return node.eval();
}), [3, 4, 12]);
assert.deepEqual(math.parse(math.matrix(['a=3', 'b=4', 'a*b'])).map(function (node) {
return node.eval();
}), math.matrix([3, 4, 12]));
});
it('should parse multiple expressions', function() {
assert.deepEqual(math.parse('a=3\nb=4\na*b').eval(), [3, 4, 12]);
assert.deepEqual(math.parse('b = 43; b * 4').eval(), [172]);
});
it('should parse a custom function', function() {
assert.deepEqual(math.parse('function f(x) = a * x; a=2; f(4)').eval(), [8]);
});
it('should throw an error if called with wrong number of arguments', function() {
assert.throws(function () {math.parse()}, SyntaxError);
assert.throws(function () {math.parse(1,2,3)}, SyntaxError);
});
it('should throw an error if called with a number', function() {
assert.throws(function () {math.parse(23)}, TypeError);
});
it('should throw an error if called with a unit', function() {
assert.throws(function () {math.parse(math.unit('5cm'))}, TypeError);
});
it('should throw an error if called with a complex number', function() {
assert.throws(function () {math.parse(new math.type.Complex(2,3))}, TypeError);
});
it('should throw an error if called with a boolean', function() {
assert.throws(function () {math.parse(true)}, TypeError);
});
it('should handle the given scope', function() {
var scope = {
a: 3,
b: 4
};
assert.deepEqual(math.parse('a*b', scope).eval(), 12);
assert.deepEqual(math.parse('c=5', scope).eval(), 5);
assert.deepEqual(math.parse('function f(x) = x^a', scope).eval(), 'f(x)');
assert.deepEqual(scope, {
a: 3,
b: 4,
c: 5,
f: 'f(x)',
ans: 'f(x)'
});
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.parse('hello("jos")', scope).eval(), 'hello, jos!');
});
it('should parse zero', function() {
assert.equal(math.parse('0').toString(), 'ans = 0');
});
it('should parse a string', function() {
assert.equal(math.parse('"hello"').toString(), 'ans = "hello"');
});
it('should parse a matrix', function() {
assert.equal(math.parse('[1, 2 + 3i, 4]').toString(), 'ans = [[1, 2 + 3i, 4]]');
});
it('shouldn\'t break with multiple unary minuses', function() {
assert.equal(math.eval('5-3'), 2);
assert.equal(math.eval('5--3'), 8);
assert.equal(math.eval('5---3'), 2);
assert.equal(math.eval('5+---3'), 2);
assert.equal(math.eval('5----3'), 8);
assert.equal(math.eval('5+--(2+1)'), 8);
});
it('operators', function () {
it('should parse +', function() {
assert.equal(math.eval('2 + 3'), 5);
assert.equal(math.eval('2 + 3 + 4'), 9);
});
it('should parse /', function() {
assert.equal(math.eval('4 / 2'), 2);
assert.equal(math.eval('8 / 2 / 2'), 2);
});
it('should parse ./', function() {
assert.equal(math.eval('4 ./ 2'), 2);
assert.equal(math.eval('8 ./ 2 / 2'), 2);
});
it('should parse .*', function() {
approx.equal(math.eval('4 .* 2'), 8);
approx.equal(math.eval('8 .* 2 .* 2'), 32);
});
it('should parse .^', function() {
approx.equal(math.eval('2.^3'), 8);
approx.equal(math.eval('-2.^2'), -4); // -(2^2)
approx.equal(math.eval('2.^3.^4'), 2.41785163922926e+24); // 2^(3^4)
});
it('should parse ==', function() {
assert.equal(math.eval('2 == 3'), false);
assert.equal(math.eval('2 == 2'), true);
});
it('should parse >', function() {
assert.equal(math.eval('2 > 3'), false);
assert.equal(math.eval('2 > 2'), false);
assert.equal(math.eval('2 > 1'), true);
});
it('should parse >=', function() {
assert.equal(math.eval('2 >= 3'), false);
assert.equal(math.eval('2 >= 2'), true);
assert.equal(math.eval('2 >= 1'), true);
});
it('should parse %', function() {
approx.equal(math.eval('8 % 3'), 2);
});
it.skip('should parse mod', function() {
approx.equal(math.eval('8 mod 3'), 2);
});
it.skip('should parse *', function() {
approx.equal(math.eval('4 * 2'), 8);
approx.equal(math.eval('8 * 2 * 2'), 32);
});
it.skip('should parse ^', function() {
approx.equal(math.eval('2^3'), 8);
approx.equal(math.eval('-2^2'), -4); // -(2^2)
approx.equal(math.eval('2^3^4'), 2.41785163922926e+24); // 2^(3^4)
});
it.skip('should parse <', function() {
assert.equal(math.eval('2 < 3'), true);
assert.equal(math.eval('2 < 2'), false);
assert.equal(math.eval('2 < 1'), false);
});
it.skip('should parse <=', function() {
assert.equal(math.eval('2 <= 3'), true);
assert.equal(math.eval('2 <= 2'), true);
assert.equal(math.eval('2 <= 1'), false);
});
it.skip('should parse -', function() {
assert.equal(math.eval('4 - 2'), 2);
assert.equal(math.eval('8 - 2 - 2'), 4);
});
it.skip('should parse unary -', function() {
assert.equal(math.eval('-2'), -2);
assert.equal(math.eval('4*-2'), -8);
assert.equal(math.eval('4 * -2'), -8);
assert.equal(math.eval('4+-2'), 2);
assert.equal(math.eval('4 + -2'), 2);
assert.equal(math.eval('4--2'), 6);
assert.equal(math.eval('4 - -2'), 6);
});
it.skip('should parse unary !=', function() {
assert.equal(math.eval('2 != 3'), true);
assert.equal(math.eval('2 != 2'), false);
});
it.skip('should parse :', function() {
assert.equal(math.eval('2:5'), [2,3,4,5]);
assert.equal(math.eval('5:-1:2'), [5,4,3,2]);
});
it('should parse in', function() {
assert.equal(math.eval('2.54 cm in inch').toString(), '1 inch');
assert.equal(math.eval('2.54 cm + 2 inch in foot').toString(), '0.25 foot');
});
});
describe('functions', function () {
it('should parse all arithmetic functions', function () {
assert.equal(math.eval('abs(-4.2)'), 4.2);
assert.equal(math.eval('add(2, 3)'), 5);
assert.equal(math.eval('ceil(1.3)'), 2);
assert.equal(math.eval('ceil(1.8)'), 2);
assert.equal(math.eval('cube(4)'), 64);
assert.equal(math.eval('divide(4, 2)'), 2);
assert.equal(math.eval('edivide(4, 2)'), 2);
assert.equal(math.eval('emultiply(4, 2)'), 8);
approx.equal(math.eval('epow(2,3)'), 8);
approx.equal(math.eval('epow(-2,2)'), 4);
assert.equal(math.eval('equal(2, 3)'), false);
assert.equal(math.eval('equal(2, 2)'), true);
approx.equal(math.eval('exp(1)'), Math.E);
approx.deepEqual(math.eval('1+exp(pi*i)'), new math.type.Complex(0, 0));
assert.equal(math.eval('fix(1.3)'), 1);
assert.equal(math.eval('fix(1.8)'), 1);
assert.equal(math.eval('floor(1.3)'), 1);
assert.equal(math.eval('floor(1.8)'), 1);
assert.equal(math.eval('gcd(12, 8)'), 4);
assert.equal(math.eval('larger(2, 3)'), false);
assert.equal(math.eval('larger(2, 2)'), false);
assert.equal(math.eval('larger(2, 1)'), true);
assert.equal(math.eval('largereq(2, 3)'), false);
assert.equal(math.eval('largereq(2, 2)'), true);
assert.equal(math.eval('largereq(2, 1)'), true);
assert.equal(math.eval('lcm(4, 6)'), 12);
approx.equal(math.eval('log(e)'), 1);
approx.equal(math.eval('log(2.71828182845905)'), 1);
approx.equal(math.eval('log10(1000)'), 3);
approx.equal(math.eval('mod(8, 3)'), 2);
approx.equal(math.eval('multiply(4, 2)'), 8);
approx.equal(math.eval('pow(2,3)'), 8);
approx.equal(math.eval('pow(-2,2)'), 4);
assert.equal(math.eval('round(pi)'), 3);
assert.equal(math.eval('round(pi, 3)'), 3.142);
assert.equal(math.eval('sign(3)'), 1);
assert.equal(math.eval('sign(-3)'), -1);
assert.equal(math.eval('sign(0)'), 0);
assert.equal(math.eval('smaller(2, 3)'), true);
assert.equal(math.eval('smaller(2, 2)'), false);
assert.equal(math.eval('smaller(2, 1)'), false);
assert.equal(math.eval('smallereq(2, 3)'), true);
assert.equal(math.eval('smallereq(2, 2)'), true);
assert.equal(math.eval('smallereq(2, 1)'), false);
assert.equal(math.eval('sqrt(25)'), 5);
assert.equal(math.eval('square(4)'), 16);
assert.equal(math.eval('subtract(4, 2)'), 2);
assert.equal(math.eval('unary(4)'), -4);
assert.equal(math.eval('unequal(2, 3)'), true);
assert.equal(math.eval('unequal(2, 2)'), false);
assert.deepEqual(math.eval('xgcd(36163, 21199)'), [1247, -7, 12]);
});
describe('construction', function () {
it('should parse construction function boolean correctly', function() {
assert.equal(math.eval('boolean("true")'), true);
assert.equal(math.eval('boolean("false")'), false);
assert.equal(math.eval('boolean(true)'), true);
assert.equal(math.eval('boolean(false)'), false);
assert.equal(math.eval('boolean(1)'), true);
assert.equal(math.eval('boolean(2)'), true);
assert.equal(math.eval('boolean(0)'), false);
});
it('should parse construction function complex correctly', function() {
assert.deepEqual(math.eval('complex()'), new math.type.Complex(0,0));
assert.deepEqual(math.eval('complex(2,3)'), new math.type.Complex(2,3));
assert.deepEqual(math.eval('complex("2+3i")'), new math.type.Complex(2,3));
});
it('should pasre construction function number correctly', function() {
assert.equal(math.eval('number(123)'), 123);
assert.equal(math.eval('number("123")'), 123);
assert.equal(math.eval('number()'), 0);
});
it('should pasre construction function string correctly', function() {
assert.equal(math.eval('string(123)'), '123');
assert.equal(math.eval('string(2+3i)'), '2 + 3i');
assert.equal(math.eval('string(1:5)'), '[1, 2, 3, 4, 5]');
assert.equal(math.eval('string(2 inch)'), '2 inch');
assert.equal(math.eval('string([1,2;3,4])'), '[[1, 2], [3, 4]]');
});
it('should pasre construction function unit correctly', function() {
assert.deepEqual(math.eval('unit(2, "m")'), new math.type.Unit(2, 'm'));
assert.deepEqual(math.eval('unit("2m")'), new math.type.Unit(2, 'm'));
});
});
});
});