Intial Commit

This commit is contained in:
valki
2020-10-17 18:42:50 +02:00
commit 664c6d8ca3
5892 changed files with 759183 additions and 0 deletions

View File

@@ -0,0 +1,59 @@
# Algebra (symbolic computation)
math.js has built-in support for symbolic computation ([CAS](https://www.wikiwand.com/en/Computer_algebra_system)). It can parse expressions into an expression tree and do algebraic operations like simplification and derivation on the tree.
> It's worth mentioning an excellent extension on math.js here: [mathsteps](https://github.com/socraticorg/mathsteps), a step-by-step math solver library that is focused on pedagogy (how best to teach). The math problems it focuses on are pre-algebra and algebra problems involving simplifying expressions.
## Simplify
The function [`math.simplify`](../reference/functions/simplify.md) simplifies an expression tree:
```js
// simplify an expression
console.log(math.simplify('3 + 2 / 4').toString()); // '7 / 2'
console.log(math.simplify('2x + 3x').toString()); // '5 * x'
console.log(math.simplify('x^2 + x + 3 + x^2').toString()); // '2 * x ^ 2 + x + 3'
console.log(math.simplify('x * y * -x / (x ^ 2)').toString()); // '-y'
```
The function accepts either a string or an expression tree (`Node`) as input, and outputs a simplified expression tree (`Node`). This node tree can be transformed and evaluated as described in detail on the page [Expression trees]('./expression_trees.md').
```js
// work with an expression tree, evaluate results
var f = math.parse('2x + x');
var simplified = math.simplify(f);
console.log(simplified.toString()); // '3 * x'
console.log(simplified.eval({x: 4})); // 12
```
For more details on the theory of expression simplification, see:
- [Strategies for simplifying math expressions (Stackoverflow)](http://stackoverflow.com/questions/7540227/strategies-for-simplifying-math-expressions)
- [Symbolic computation - Simplification (Wikipedia)](https://en.wikipedia.org/wiki/Symbolic_computation#Simplification)
## Derivative
The function [`math.derivative`](../reference/functions/derivative.md) finds the symbolic derivative of an expression:
```js
// calculate a derivative
console.log(math.derivative('2x^2 + 3x + 4', 'x').toString()); // '4 * x + 3'
console.log(math.derivative('sin(2x)', 'x').toString()); // '2 * cos(2 * x)'
```
Similar to the function `math.simplify`, `math.derivative` accepts either a string or an expression tree (`Node`) as input, and outputs a simplified expression tree (`Node`).
```js
// work with an expression tree, evaluate results
var h = math.parse('x^2 + x');
var x = math.parse('x');
var dh = math.derivative(h, x);
console.log(dh.toString()); // '2 * x + 1'
console.log(dh.eval({x: 3})); // '7'
```
The rules used by `math.derivative` can be found on Wikipedia:
- [Differentiation rules (Wikipedia)](http://en.wikipedia.org/wiki/Differentiation_rules)

View File

@@ -0,0 +1,376 @@
# Customization
Besides parsing and evaluating expressions, the expression parser supports
a number of features to customize processing and evaluation of expressions
and outputting expressions.
On this page:
- [Function transforms](#function-transforms)
- [Custom argument parsing](#custom-argument-parsing)
- [Custom LaTeX handlers](#custom-latex-handlers)
- [Custom LaTeX and string output](#custom-latex-and-string-output)
- [Customize supported characters](#customize-supported-characters)
## Function transforms
It is possible to preprocess function arguments and post process a functions
return value by writing a *transform* for the function. A transform is a
function wrapping around a function to be transformed or completely replaces
a function.
For example, the functions for math.js use zero-based matrix indices (as is
common in programing languages), but the expression parser uses one-based
indices. To enable this, all functions dealing with indices have a transform,
which changes input from one-based to zero-based, and transforms output (and
error message) from zero-based to one-based.
```js
// using plain JavaScript, indices are zero-based:
var a = [[1, 2], [3, 4]]; // a 2x2 matrix
math.subset(a, math.index(0, 1)); // returns 2
// using the expression parser, indices are transformed to one-based:
var a = [[1, 2], [3, 4]]; // a 2x2 matrix
var scope = {
a: a
};
math.eval('subset(a, index(1, 2))', scope); // returns 2
```
To create a transform for a function, the transform function must be attached
to the function as property `transform`:
```js
var math = require('../index');
// create a function
function addIt(a, b) {
return a + b;
}
// attach a transform function to the function addIt
addIt.transform = function (a, b) {
console.log('input: a=' + a + ', b=' + b);
// we can manipulate input here before executing addIt
var res = addIt(a, b);
console.log('result: ' + res);
// we can manipulate result here before returning
return res;
};
// import the function into math.js
math.import({
addIt: addIt
});
// use the function via the expression parser
console.log('Using expression parser:');
console.log('2+4=' + math.eval('addIt(2, 4)'));
// This will output:
//
// input: a=2, b=4
// result: 6
// 2+4=6
// when used via plain JavaScript, the transform is not invoked
console.log('');
console.log('Using plain JavaScript:');
console.log('2+4=' + math.addIt(2, 4));
// This will output:
//
// 6
```
Functions with a transform must be imported in the `math` namespace, as they
need to be processed at compile time. They are not supported when passed via a
scope at evaluation time.
## Custom argument parsing
The expression parser of math.js has support for letting functions
parse and evaluate arguments themselves, instead of calling them with
evaluated arguments. This is useful for example when creating a function
like `plot(f(x), x)` or `integrate(f(x), x, start, end)`, where some of the
arguments need to be processed in a special way. In these cases, the expression
`f(x)` will be evaluated repeatedly by the function, and `x` is not evaluated
but used to specify the variable looping over the function `f(x)`.
Functions having a property `rawArgs` with value `true` are treated in a special
way by the expression parser: they will be invoked with unevaluated arguments,
allowing the function to process the arguments in a customized way. Raw
functions are called as:
```
rawFunction(args: Node[], math: Object, scope: Object)
```
Where :
- `args` is an Array with nodes of the parsed arguments.
- `math` is the math namespace against which the expression was compiled.
- `scope` is the scope provided when evaluating the expression.
Raw functions must be imported in the `math` namespace, as they need to be
processed at compile time. They are not supported when passed via a scope
at evaluation time.
A simple example:
```js
function myFunction(args, math, scope) {
// get string representation of the arguments
var str = args.map(function (arg) {
return arg.toString();
})
// evaluate the arguments
var res = args.map(function (arg) {
return arg.compile().eval(scope);
});
return 'arguments: ' + str.join(',') + ', evaluated: ' + res.join(',');
}
// mark the function as "rawArgs", so it will be called with unevaluated arguments
myFunction.rawArgs = true;
// import the new function in the math namespace
math.import({
myFunction: myFunction
})
// use the function
math.eval('myFunction(2 + 3, sqrt(4))');
// returns 'arguments: 2 + 3, sqrt(4), evaluated: 5, 2'
```
## Custom LaTeX handlers
You can attach a `toTex` property to your custom functions before importing them to define their LaTeX output. This
`toTex` property can be a handler in the format described in the next section 'Custom LaTeX and String conversion'
or a template string similar to ES6 templates.
### Template syntax
- `${name}`: Gets replaced by the name of the function
- `${args}`: Gets replaced by a comma separated list of the arguments of the function.
- `${args[0]}`: Gets replaced by the first argument of a function
- `$$`: Gets replaced by `$`
#### Example
```js
var customFunctions = {
plus: function (a, b) {
return a + b;
},
minus: function (a, b) {
return a - b;
},
binom: function (n, k) {
return 1;
}
};
customFunctions.plus.toTex = '${args[0]}+${args[1]}'; //template string
customFunctions.binom.toTex = '\\mathrm{${name}}\\left(${args}\\right)'; //template string
customFunctions.minus.toTex = function (node, options) { //handler function
return node.args[0].toTex(options) + node.name + node.args[1].toTex(options);
};
math.import(customFunctions);
math.parse('plus(1,2)').toTex(); //'1+2'
math.parse('binom(1,2)').toTex(); // '\\mathrm{binom}\\left(1,2\\right)'
math.parse('minus(1,2)').toTex(); // '1minus2'
```
## Custom LaTeX and string output
All expression nodes have a method `toTex` and `toString` to output an expression respectively in LaTex format or as regular text .
The functions `toTex` and `toString` accept an `options` argument to customise output. This object is of the following form:
```js
{
parenthesis: 'keep', // parenthesis option
handler: someHandler, // handler to change the output
implicit: 'hide' // how to treat implicit multiplication
}
```
### Parenthesis
The `parenthesis` option changes the way parentheses are used in the output. There are three options available:
- `keep` Keep the parentheses from the input and display them as is. This is the default.
- `auto` Only display parentheses that are necessary. Mathjs tries to get rid of as much parentheses as possible.
- `all` Display all parentheses that are given by the structure of the node tree. This makes the output precedence unambiguous.
There's two ways of passing callbacks:
1. Pass an object that maps function names to callbacks. Those callbacks will be used for FunctionNodes with
functions of that name.
2. Pass a function to `toTex`. This function will then be used for every node.
```js
var expression = math.parse('(1+1+1)');
expression.toString(); //(1 + 1 + 1)
expression.toString({parenthesis: 'keep'}); //(1 + 1 + 1)
expression.toString({parenthesis: 'auto'}); //1 + 1 + 1
expression.toString({parenthesis: 'all'}); //(1 + 1) + 1
```
### Handler
You can provide the `toTex` and `toString` functions of an expression with your own custom handlers that override the internal behaviour. This is especially useful to provide LaTeX/string output for your own custom functions. This can be done in two ways:
1. Pass an object that maps function names to callbacks. Those callbacks will be used for FunctionNodes that contain functions with that name.
2. Pass a callback directly. This callback will run for every node, so you can replace the output of anything you like.
A callback function has the following form:
```js
var callback = function (node, options) {
...
}
```
Where `options` is the object passed to `toTex`/`toString`. Don't forget to pass this on to the child nodes, and `node` is a reference to the current node.
If a callback returns nothing, the standard output will be used. If your callback returns a string, this string will be used.
**Although the following examples use `toTex`, it works for `toString` in the same way**
#### Examples for option 1
```js
var customFunctions = {
binomial: function (n, k) {
//calculate n choose k
// (do some stuff)
return result;
}
};
var customLaTeX = {
'binomial': function (node, options) { //provide toTex for your own custom function
return '\\binom{' + node.args[0].toTex(options) + '}{' + node.args[1].toTex(options) + '}';
},
'factorial': function (node, options) { //override toTex for builtin functions
return 'factorial\\left(' + node.args[0] + '\\right)';
}
};
```
You can simply use your custom toTex functions by passing them to `toTex`:
```js
math.import(customFunctions);
var expression = math.parse('binomial(factorial(2),1)');
var latex = expression.toTex({handler: customLaTeX});
//latex now contains "\binom{factorial\\left(2\\right)}{1}"
```
#### Examples for option 2:
```js
var customLaTeX = function (node, options) {
if ((node.type === 'OperatorNode') && (node.fn === 'add')) {
//don't forget to pass the options to the toTex functions
return node.args[0].toTex(options) + ' plus ' + node.args[1].toTex(options);
}
else if (node.type === 'ConstantNode') {
if (node.value == 0) {
return '\\mbox{zero}';
}
else if (node.value == 1) {
return '\\mbox{one}';
}
else if (node.value == 2) {
return '\\mbox{two}';
}
else {
return node.value;
}
}
};
var expression = math.parse('1+2');
var latex = expression.toTex({handler: customLaTeX});
//latex now contains '\mbox{one} plus \mbox{two}'
```
Another example in conjunction with custom functions:
```js
var customFunctions = {
binomial: function (n, k) {
//calculate n choose k
// (do some stuff)
return result;
}
};
var customLaTeX = function (node, options) {
if ((node.type === 'FunctionNode') && (node.name === 'binomial')) {
return '\\binom{' + node.args[0].toTex(options) + '}{' + node.args[1].toTex(options) + '}';
}
};
math.import(customFunctions);
var expression = math.parse('binomial(2,1)');
var latex = expression.toTex({handler: customLaTeX});
//latex now contains "\binom{2}{1}"
```
### Implicit multiplication
You can change the way that implicit multiplication is converted to a string or LaTeX. The two options are `hide`, to not show a multiplication operator for implicit multiplication and `show` to show it.
Example:
```js
var node = math.parse('2a');
node.toString(); //'2 a'
node.toString({implicit: 'hide'}); //'2 a'
node.toString({implicit: 'show'}); //'2 * a'
node.toTex(); //'2~ a'
node.toTex({implicit: 'hide'}); //'2~ a'
node.toTex({implicit: 'show'}); //'2\\cdot a'
```
## Customize supported characters
It is possible to customize the characters allowed in symbols and digits.
The `parse` function exposes the following test functions:
- `math.expression.parse.isAlpha(c, cPrev, cNext)`
- `math.expression.parse.isWhitespace(c, nestingLevel)`
- `math.expression.parse.isDecimalMark(c, cNext)`
- `math.expression.parse.isDigitDot(c)`
- `math.expression.parse.isDigit(c)`
The exact signature and implementation of these functions can be looked up in
the [source code of the parser](https://github.com/josdejong/mathjs/blob/master/lib/expression/parse.js). The allowed alpha characters are described here: [Constants and variables](syntax.md#constants-and-variables).
For example, the `$` character is not supported by default. It can be enabled
by replacing the `isAlpha` function:
```js
var isAlphaOriginal = math.expression.parse.isAlpha;
math.expression.parse.isAlpha = function (c, cPrev, cNext) {
return isAlphaOriginal(c, cPrev, cNext) || (c === '$');
};
// now we can use the $ character in expressions
var result = math.eval('$foo', {$foo: 42}); // returns 42
console.log(result);
```

View File

@@ -0,0 +1,610 @@
# Expression trees
When parsing an expression via `math.parse(expr)`, math.js generates an
expression tree and returns the root node of the tree. An expression tree can
be used to analyze, manipulate, and evaluate expressions.
Example:
```js
var node = math.parse('sqrt(2 + x)');
```
In this case, the expression `sqrt(2 + x)` is parsed as:
```
FunctionNode sqrt
|
OperatorNode +
/ \
ConstantNode 2 x SymbolNode
```
Alternatively, this expression tree can be build by manually creating nodes:
```js
var node1 = new math.expression.node.ConstantNode(2);
var node2 = new math.expression.node.SymbolNode('x');
var node3 = new math.expression.node.OperatorNode('+', 'add', [node1, node2]);
var node4 = new math.expression.node.FunctionNode('sqrt', [node3]);
```
The resulting expression tree with root node `node4` is equal to the expression
tree generated by `math.parse('sqrt(2 + x)')`.
## API
### Methods
All nodes have the following methods:
- `clone() : Node`
Create a shallow clone of the node.
The node itself is cloned, its childs are not cloned.
- `cloneDeep() : Node`
Create a deep clone of the node.
Both the node as well as all its childs are cloned recursively.
- `compile() : Object`
Compile an expression into optimized JavaScript code. `compile` returns an
object with a function `eval([scope])` to evaluate. Example:
```js
var node = math.parse('2 + x'); // returns the root Node of an expression tree
var code = node.compile(); // returns {eval: function (scope) {...}}
var eval = code.eval({x: 3}); // returns 5
```
- `eval([scope]) : Object`
Compile and eval an expression, this is the equivalent of doing
`node.compile().eval(scope)`. Example:
```js
var node = math.parse('2 + x'); // returns the root Node of an expression tree
var eval = node.eval({x: 3}); // returns 5
```
- `equals(other: Node) : boolean`
Test whether this node equals an other node. Does a deep comparison of the
values of both nodes.
- `filter(callback: function) : Node[]`
Recursively filter nodes in an expression tree. The `callback` function is
called as `callback(node: Node, path: string, parent: Node) : boolean` for
every node in the tree, and must return a boolean. The function `filter`
returns an array with nodes for which the test returned true.
Parameter `path` is a string containing a relative JSON Path.
Example:
```js
var node = math.parse('x^2 + x/4 + 3*y');
var filtered = node.filter(function (node) {
return node.isSymbolNode && node.name == 'x';
});
// returns an array with two entries: two SymbolNodes 'x'
```
- `forEach(callback: function) : Node[]`
Execute a callback for each of the child nodes of this node. The `callback`
function is called as `callback(child: Node, path: string, parent: Node)`.
Parameter `path` is a string containing a relative JSON Path.
See also `traverse`, which is a recursive version of `forEach`.
Example:
```js
var node = math.parse('3 * x + 2');
node.forEach(function (node, path, parent) {
switch (node.type) {
case 'OperatorNode': console.log(node.type, node.op); break;
case 'ConstantNode': console.log(node.type, node.value); break;
case 'SymbolNode': console.log(node.type, node.name); break;
default: console.log(node.type);
}
});
// outputs:
// OperatorNode *
// ConstantNode 2
```
- `map(callback: function) : Node[]`
Transform a node. Creates a new Node having it's childs be the results of
calling the provided callback function for each of the childs of the original
node. The `callback` function is called as `callback(child: Node, path: string,
parent: Node)` and must return a Node. Parameter `path` is a string containing
a relative JSON Path.
See also `transform`, which is a recursive version of `map`.
- `toString(options: object) : string`
Get a string representation of the parsed expression. This is not exactly
the same as the original input. Example:
```js
var node = math.parse('3+4*2');
node.toString(); // returns '3 + (4 * 2)'
```
Information about the options in [Customization](customization.md#custom-latex-and-string-output).
- `toTex(options: object): string`
Get a [LaTeX](http://en.wikipedia.org/wiki/LaTeX) representation of the
expression. Example:
```js
var node = math.parse('sqrt(2/3)');
node.toTex(); // returns '\sqrt{\frac{2}{3}}'
```
Information about the options in [Customization](customization.md#custom-latex-and-string-output).
- `transform(callback: function)`
Recursively transform an expression tree via a transform function. Similar
to `Array.map`, but recursively executed on all nodes in the expression tree.
The callback function is a mapping function accepting a node, and returning
a replacement for the node or the original node. Function `callback` is
called as `callback(node: Node, path: string, parent: Node)` for every node
in the tree, and must return a `Node`. Parameter `path` is a string containing
a relative JSON Path.
For example, to replace all nodes of type `SymbolNode` having name 'x' with a
ConstantNode with value `3`:
```js
var node = math.parse('x^2 + 5*x');
var transformed = node.transform(function (node, path, parent) {
if (node.SymbolNode && node.name == 'x') {
return new math.expression.node.ConstantNode(3);
}
else {
return node;
}
});
transformed.toString(); // returns '(3 ^ 2) + (5 * 3)'
```
- `traverse(callback)`
Recursively traverse all nodes in a node tree. Executes given callback for
this node and each of its child nodes. Similar to `Array.forEach`, except
recursive.
The callback function is a mapping function accepting a node, and returning
a replacement for the node or the original node. Function `callback` is
called as `callback(node: Node, path: string, parent: Node)` for every node
in the tree. Parameter `path` is a string containing a relative JSON Path.
Example:
```js
var node = math.parse('3 * x + 2');
node.traverse(function (node, path, parent) {
switch (node.type) {
case 'OperatorNode': console.log(node.type, node.op); break;
case 'ConstantNode': console.log(node.type, node.value); break;
case 'SymbolNode': console.log(node.type, node.name); break;
default: console.log(node.type);
}
});
// outputs:
// OperatorNode +
// OperatorNode *
// ConstantNode 3
// SymbolNode x
// ConstantNode 2
```
### Properties
Each `Node` has the following properties:
- `comment: string`
A string holding a comment if there was any in the expression, or else the
string will be empty string. A comment can be attached to the root node of
an expression or to each of the childs nodes of a `BlockNode`.
- `isNode: true`
Is defined with value `true` on Nodes. Additionally, each type of node
adds it's own flag, for example a `SymbolNode` as has a property
`isSymbolNode: true`.
- `type: string`
The type of the node, for example `'SymbolNode'` in case of a `SymbolNode`.
## Nodes
math.js has the following types of nodes. All nodes are available at the
namespace `math.expression.node`.
### AccessorNode
Construction:
```
new AccessorNode(object: Node, index: IndexNode)
```
Properties:
- `object: Node`
- `index: IndexNode`
- `name: string` (read-only) The function or method name. Returns an empty string when undefined.
Examples:
```js
var node1 = math.parse('a[3]');
var object = new math.expression.node.SymbolNode('a');
var index = new math.expression.node.IndexNode([3]);
var node2 = new math.expression.node.AccessorNode(object, index);
```
### ArrayNode
Construction:
```
new ArrayNode(items: Node[])
```
Properties:
- `items: Node[]`
Examples:
```js
var node1 = math.parse('[1, 2, 3]');
var one = new math.expression.node.ConstantNode(1);
var two = new math.expression.node.ConstantNode(2);
var three = new math.expression.node.ConstantNode(3);
var node2 = new math.expression.node.ArrayNode([one, two, three]);
```
### AssignmentNode
Construction:
```
new AssignmentNode(object: SymbolNode, value: Node)
new AssignmentNode(object: SymbolNode | AccessorNode, index: IndexNode, value: Node)
```
Properties:
- `object: SymbolNode | AccessorNode`
- `index: IndexNode | null`
- `value: Node`
- `name: string` (read-only) The function or method name. Returns an empty string when undefined.
Examples:
```js
var node1 = math.parse('a = 3');
var object = new math.expression.node.SymbolNode('a');
var value = new math.expression.node.ConstantNode(3);
var node2 = new math.expression.node.AssignmentNode(object, value);
```
### BlockNode
A `BlockNode` is created when parsing a multi line expression like `a=2;b=3` or
`a=2\nb=3`. Evaluating a `BlockNode` returns a `ResultSet`. The results can be
retrieved via `ResultSet.entries` or `ResultSet.valueOf()`, which contains
an `Array` with the results of the visible lines (i.e. lines not ending with
a semicolon).
Construction:
```
block = new BlockNode(Array.<{node: Node} | {node: Node, visible: boolean}>)
```
Properties:
- `blocks: Array.<{node: Node, visible: boolean}>`
Examples:
```js
var block1 = math.parse('a=1; b=2; c=3');
var a = new math.expression.node.SymbolNode('a');
var one = new math.expression.node.ConstantNode(1);
var ass1 = new math.expression.node.AssignmentNode(a, one);
var b = new math.expression.node.SymbolNode('b');
var two = new math.expression.node.ConstantNode(2);
var ass2 = new math.expression.node.AssignmentNode(b, two);
var c = new math.expression.node.SymbolNode('c');
var three = new math.expression.node.ConstantNode(3);
var ass3 = new math.expression.node.AssignmentNode(c, three);
var block2 = new BlockNode([
{node: ass1, visible: false},
{node: ass2, visible: false},
{node: ass3, visible: true}
]);
```
### ConditionalNode
Construction:
```
new ConditionalNode(condition: Node, trueExpr: Node, falseExpr: Node)
```
Properties:
- `condition: Node`
- `trueExpr: Node`
- `falseExpr: Node`
Examples:
```js
var node1 = math.parse('a > 0 ? a : -a');
var a = new math.expression.node.SymbolNode('a');
var zero = new math.expression.node.ConstantNode(0);
var condition = new math.expression.node.OperatorNode('>', 'larger', [a, zero]);
var trueExpr = a;
var falseExpr = new math.expression.node.OperatorNode('-', 'unaryMinus', [a]);
var node2 = new math.expression.node.ConditionalNode(condition, trueExpr, falseExpr);
```
### ConstantNode
Construction:
```
new ConstantNode(value: * [, valueType: string])
```
Properties:
- `value: *`
- `valueType: string`
Examples:
```js
var node1 = math.parse('2.4');
var node2 = new math.expression.node.ConstantNode(2.4);
var node3 = new math.expression.node.ConstantNode('2.4', 'number');
```
### FunctionAssignmentNode
Construction:
```
new FunctionAssignmentNode(name: string, params: string[], expr: Node)
```
Properties:
- `name: string`
- `params: string[]`
- `expr: Node`
Examples:
```js
var node1 = math.parse('f(x) = x^2');
var x = new math.expression.node.SymbolNode('x');
var two = new math.expression.node.ConstantNode(2);
var expr = new math.expression.node.OperatorNode('^', 'pow', [x, 2]);
var node2 = new math.expression.node.FunctionAssignmentNode('f', ['x'], expr);
```
### FunctionNode
Construction:
```
new FunctionNode(fn: Node | string, args: Node[])
```
Properties:
- `fn: Node | string` (read-only) The object or function name which to invoke.
- `args: Node[]`
Examples:
```js
var node1 = math.parse('sqrt(4)');
var four = new math.expression.node.ConstantNode(4);
var node3 = new math.expression.node.FunctionNode(new SymbolNode('sqrt'), [four]);
```
### IndexNode
Construction:
```
new IndexNode(dimensions: Node[])
new IndexNode(dimensions: Node[], dotNotation: boolean)
```
Each dimension can be a single value, a range, or a property. The values of
indices are one-based, including range end.
An optional property `dotNotation` can be provided describing whether this index
was written using dot notation like `a.b`, or using bracket notation
like `a["b"]`. Default value is `false`. This information is used when
stringifying the IndexNode.
Properties:
- `dimensions: Node[]`
- `dotNotation: boolean`
Examples:
```js
var node1 = math.parse('A[1:3, 2]');
var A = new math.expression.node.SymbolNode('A');
var one = new math.expression.node.ConstantNode(1);
var two = new math.expression.node.ConstantNode(2);
var three = new math.expression.node.ConstantNode(3);
var range = new math.expression.node.RangeNode(one, three);
var index = new math.expression.node.IndexNode([range, two]);
var node2 = new math.expression.node.AccessNode(A, index);
```
### ObjectNode
Construction:
```
new ObjectNode(properties: Object.<string, Node>)
```
Properties:
- `properties: Object.<string, Node>`
Examples:
```js
var node1 = math.parse('{a: 1, b: 2, c: 3}');
var a = new math.expression.node.ConstantNode(1);
var b = new math.expression.node.ConstantNode(2);
var c = new math.expression.node.ConstantNode(3);
var node2 = new math.expression.node.ObjectNode({a: a, b: b, c: c});
```
### OperatorNode
Construction:
```
new OperatorNode(op: string, fn: string, args: Node[])
```
Properties:
- `op: string`
- `fn: string`
- `args: Node[]`
Examples:
```js
var node1 = math.parse('2.3 + 5');
var a = new math.expression.node.ConstantNode(2.3);
var b = new math.expression.node.ConstantNode(5);
var node2 = new math.expression.node.OperatorNode('+', 'add', [a, b]);
```
### ParenthesisNode
Construction:
```
new ParenthesisNode(content: Node)
```
Properties:
- `content: Node`
Examples:
```js
var node1 = math.parse('(1)');
var a = new math.expression.node.ConstantNode(1);
var node2 = new math.expression.node.ParenthesisNode(a);
```
### RangeNode
Construction:
```
new RangeNode(start: Node, end: Node [, step: Node])
```
Properties:
- `start: Node`
- `end: Node`
- `step: Node | null`
Examples:
```js
var node1 = math.parse('1:10');
var node2 = math.parse('0:2:10');
var zero = new math.expression.node.ConstantNode(0);
var one = new math.expression.node.ConstantNode(1);
var two = new math.expression.node.ConstantNode(2);
var ten = new math.expression.node.ConstantNode(10);
var node3 = new math.expression.node.RangeNode(one, ten);
var node4 = new math.expression.node.RangeNode(zero, ten, two);
```
### SymbolNode
Construction:
```
new SymbolNode(name: string)
```
Properties:
- `name: string`
Examples:
```js
var node = math.parse('x');
var x = new math.expression.node.SymbolNode('x');
```

View File

@@ -0,0 +1,20 @@
# Expressions
Math.js contains a flexible and easy to use expression parser.
The parser supports all data types, functions and constants available in math.js.
Whilst the math.js library is aimed at JavaScript developers, the expression
parser is aimed at end users: mathematicians, engineers, students, pupils.
The syntax of the expression parser differs from JavaScript and the low-level
math.js library.
This section is divided in the following pages:
- [Parsing and evaluation](parsing.md) describes how to parse and
evaluate expressions with math.js.
- [Syntax](syntax.md) describes how to write expressions.
- [Expression trees](expression_trees.md) explains how to parse an expression into an
expression tree, and use this to analyse and manipulate the expression.
- [Algebra](algebra.md) describing symbolic computation in math.js.
- [Customization](customization.md) describes how to customize processing and
evaluation of expressions.

View File

@@ -0,0 +1,207 @@
# Expression parsing and evaluation
Expressions can be parsed and evaluated in various ways:
- Using the function [`math.eval(expr [,scope])`](#eval).
- Using the function [`math.compile(expr)`](#compile).
- Using the function [`math.parse(expr)`](#parse).
- By creating a [parser](#parser), `math.parser()`, which contains a function
`eval` and keeps a scope with assigned variables in memory.
## Eval
Math.js comes with a function `math.eval` to evaluate expressions. Syntax:
```js
math.eval(expr)
math.eval(expr, scope)
math.eval([expr1, expr2, expr3, ...])
math.eval([expr1, expr2, expr3, ...], scope)
```
Function `eval` accepts a single expression or an array with
expressions as the first argument and has an optional second argument
containing a scope with variables and functions. The scope is a regular
JavaScript Object. The scope will be used to resolve symbols, and to write
assigned variables or function.
The following code demonstrates how to evaluate expressions.
```js
// evaluate expressions
math.eval('sqrt(3^2 + 4^2)'); // 5
math.eval('sqrt(-4)'); // 2i
math.eval('2 inch to cm'); // 5.08 cm
math.eval('cos(45 deg)'); // 0.7071067811865476
// provide a scope
var scope = {
a: 3,
b: 4
};
math.eval('a * b', scope); // 12
math.eval('c = 2.3 + 4.5', scope); // 6.8
scope.c; // 6.8
```
## Compile
Math.js contains a function `math.compile` which compiles expressions
into JavaScript code. This is a shortcut for first [parsing](#parse) and then
compiling an expression. The syntax is:
```js
math.compile(expr);
math.compile([expr1, expr2, expr3, ...]);
```
Function `compile` accepts a single expression or an array with
expressions as the argument. Function `compile` returns an object with a function
`eval([scope])`, which can be executed to evaluate the expression against an
(optional) scope:
```js
var code = math.compile(expr); // compile an expression
var result = code.eval([scope]); // evaluate the code with an optional scope
```
An expression needs to be compiled only once, after which the
expression can be evaluated repeatedly and against different scopes.
The optional scope is used to resolve symbols and to write assigned
variables or functions. Parameter `scope` is a regular Object.
Example usage:
```js
// parse an expression into a node, and evaluate the node
var code1 = math.compile('sqrt(3^2 + 4^2)');
code1.eval(); // 5
```
## Parse
Math.js contains a function `math.parse` to parse expressions into an
[expression tree](expression_trees.md). The syntax is:
```js
math.parse(expr)
math.parse([expr1, expr2, expr3, ...])
```
Function `parse` accepts a single expression or an array with
expressions as the argument. Function `parse` returns a the root node of the tree,
which can be successively compiled and evaluated:
```js
var node = math.parse(expr); // parse expression into a node tree
var code = node.compile(); // compile the node tree
var result = code.eval([scope]); // evaluate the code with an optional scope
```
The API of nodes is described in detail on the page
[Expression trees](expression_trees.md).
An expression needs to be parsed and compiled only once, after which the
expression can be evaluated repeatedly. On evaluation, an optional scope
can be provided, which is used to resolve symbols and to write assigned
variables or functions. Parameter `scope` is a regular Object.
Example usage:
```js
// parse an expression into a node, and evaluate the node
var node1 = math.parse('sqrt(3^2 + 4^2)');
var code1 = node1.compile();
code1.eval(); // 5
// provide a scope
var node2 = math.parse('x^a', scope);
var code2 = node2.compile();
var scope = {
x: 3,
a: 2
};
code2.eval(scope); // 9
// change a value in the scope and re-evaluate the node
scope.a = 3;
code2.eval(scope); // 27
```
Parsed expressions can be exported to text using `node.toString()`, and can
be exported to LaTeX using `node.toTex()`. The LaTeX export can be used to
pretty print an expression in the browser with a library like
[MathJax](http://www.mathjax.org/). Example usage:
```js
// parse an expression
var node = math.parse('sqrt(x/x+1)');
node.toString(); // returns 'sqrt((x / x) + 1)'
node.toTex(); // returns '\sqrt{ {\frac{x}{x} }+{1} }'
```
## Parser
In addition to the static functions [`math.eval`](#eval) and
[`math.parse`](#parse), math.js contains a parser with functions `eval` and
`parse`, which automatically keeps a scope with assigned variables in memory.
The parser also contains some convenience functions to get, set, and remove
variables from memory.
A parser can be created by:
```js
var parser = math.parser();
```
The parser contains the following functions:
- `clear()`
Completely clear the parser's scope.
- `eval(expr)`
Evaluate an expression. Returns the result of the expression.
- `get(name)`
Retrieve a variable or function from the parser's scope.
- `getAll()`
Retrieve a map with all defined a variables from the parser's scope.
- `remove(name)`
Remove a variable or function from the parser's scope.
- `set(name, value)`
Set a variable or function in the parser's scope.
The following code shows how to create and use a parser.
```js
// create a parser
var parser = math.parser();
// evaluate expressions
parser.eval('sqrt(3^2 + 4^2)'); // 5
parser.eval('sqrt(-4)'); // 2i
parser.eval('2 inch to cm'); // 5.08 cm
parser.eval('cos(45 deg)'); // 0.7071067811865476
// define variables and functions
parser.eval('x = 7 / 2'); // 3.5
parser.eval('x + 3'); // 6.5
parser.eval('f(x, y) = x^y'); // f(x, y)
parser.eval('f(2, 3)'); // 8
// get and set variables and functions
var x = parser.get('x'); // x = 7
var f = parser.get('f'); // function
var g = f(3, 3); // g = 27
parser.set('h', 500);
parser.eval('h / 2'); // 250
parser.set('hello', function (name) {
return 'hello, ' + name + '!';
});
parser.eval('hello("user")'); // "hello, user!"
// clear defined functions and variables
parser.clear();
```

View File

@@ -0,0 +1,599 @@
# Expression syntax
This page describes the syntax of expression parser of math.js. It describes
how to work with the available data types, functions, operators, variables,
and more.
## Differences from JavaScript
The expression parser of math.js is aimed at a mathematical audience,
not a programming audience. The syntax is similar to most calculators and
mathematical applications. This is close to JavaScript as well, though there
are a few important differences between the syntax of the expression parser and
the lower level syntax of math.js. Differences are:
- No need to prefix functions and constants with the `math.*` namespace,
you can just enter `sin(pi / 4)`.
- Matrix indexes are one-based instead of zero-based.
- There are index and range operators which allow more conveniently getting
and setting matrix indexes, like `A[2:4, 1]`.
- Both indexes and ranges and have the upper-bound included.
- There is a differing syntax for defining functions. Example: `f(x) = x^2`.
- There are custom operators like `x + y` instead of `add(x, y)`.
- Some operators are different. For example `^` is used for exponentiation,
not bitwise xor.
## Operators
The expression parser has operators for all common arithmetic operations such
as addition and multiplication. The expression parser uses conventional infix
notation for operators: an operator is placed between its arguments.
Round parentheses can be used to override the default precedence of operators.
```js
// use operators
math.eval('2 + 3'); // 5
math.eval('2 * 3'); // 6
// use parentheses to override the default precedence
math.eval('2 + 3 * 4'); // 14
math.eval('(2 + 3) * 4'); // 20
```
The following operators are available:
Operator | Name | Syntax | Associativity | Example | Result
----------- | ----------------------- | ---------- | ------------- | --------------------- | ---------------
`(`, `)` | Grouping | `(x)` | None | `2 * (3 + 4)` | `14`
`[`, `]` | Matrix, Index | `[...]` | None | `[[1,2],[3,4]]` | `[[1,2],[3,4]]`
`{`, `}` | Object | `{...}` | None | `{a: 1, b: 2}` | `{a: 1, b: 2}`
`,` | Parameter separator | `x, y` | Left to right | `max(2, 1, 5)` | `5`
`.` | Property accessor | `obj.prop` | Left to right | `obj={a: 12}; obj.a` | `12`
`;` | Statement separator | `x; y` | Left to right | `a=2; b=3; a*b` | `[6]`
`;` | Row separator | `[x; y]` | Left to right | `[1,2;3,4]` | `[[1,2],[3,4]]`
`\n` | Statement separator | `x \n y` | Left to right | `a=2 \n b=3 \n a*b` | `[2,3,6]`
`+` | Add | `x + y` | Left to right | `4 + 5` | `9`
`+` | Unary plus | `+y` | Right to left | `+4` | `4`
`-` | Subtract | `x - y` | Left to right | `7 - 3` | `4`
`-` | Unary minus | `-y` | Right to left | `-4` | `-4`
`*` | Multiply | `x * y` | Left to right | `2 * 3` | `6`
`.*` | Element-wise multiply | `x .* y` | Left to right | `[1,2,3] .* [1,2,3]` | `[1,4,9]`
`/` | Divide | `x / y` | Left to right | `6 / 2` | `3`
`./` | Element-wise divide | `x ./ y` | Left to right | `[9,6,4] ./ [3,2,2]` | `[3,3,2]`
`%`, `mod` | Modulus | `x % y` | Left to right | `8 % 3` | `2`
`^` | Power | `x ^ y` | Right to left | `2 ^ 3` | `8`
`.^` | Element-wise power | `x .^ y` | Right to left | `[2,3] .^ [3,3]` | `[9,27]`
`'` | Transpose | `y'` | Left to right | `[[1,2],[3,4]]'` | `[[1,3],[2,4]]`
`!` | Factorial | `y!` | Left to right | `5!` | `120`
`&` | Bitwise and | `x & y` | Left to right | `5 & 3` | `1`
`~` | Bitwise not | `~x` | Right to left | `~2` | `-3`
<code>&#124;</code> | Bitwise or | <code>x &#124; y</code> | Left to right | <code>5 &#124; 3</code> | `7`
<code>^&#124;</code> | Bitwise xor | <code>x ^&#124; y</code> | Left to right | <code>5 ^&#124; 2</code> | `6`
`<<` | Left shift | `x << y` | Left to right | `4 << 1` | `8`
`>>` | Right arithmetic shift | `x >> y` | Left to right | `8 >> 1` | `4`
`>>>` | Right logical shift | `x >>> y` | Left to right | `-8 >>> 1` | `2147483644`
`and` | Logical and | `x and y` | Left to right | `true and false` | `false`
`not` | Logical not | `not y` | Right to left | `not true` | `false`
`or` | Logical or | `x or y` | Left to right | `true or false` | `true`
`xor` | Logical xor | `x xor y` | Left to right | `true xor true` | `false`
`=` | Assignment | `x = y` | Right to left | `a = 5` | `5`
`?` `:` | Conditional expression | `x ? y : z` | Right to left | `15 > 100 ? 1 : -1` | `-1`
`:` | Range | `x : y` | Right to left | `1:4` | `[1,2,3,4]`
`to`, `in` | Unit conversion | `x to y` | Left to right | `2 inch to cm` | `5.08 cm`
`==` | Equal | `x == y` | Left to right | `2 == 4 - 2` | `true`
`!=` | Unequal | `x != y` | Left to right | `2 != 3` | `true`
`<` | Smaller | `x < y` | Left to right | `2 < 3` | `true`
`>` | Larger | `x > y` | Left to right | `2 > 3` | `false`
`<=` | Smallereq | `x <= y` | Left to right | `4 <= 3` | `false`
`>=` | Largereq | `x >= y` | Left to right | `2 + 4 >= 6` | `true`
## Precedence
The operators have the following precedence, from highest to lowest:
Operators | Description
--------------------------------- | --------------------
`(...)`<br>`[...]`<br>`{...}` | Grouping<br>Matrix<br>Object
`x(...)`<br>`x[...]`<br>`obj.prop`<br>`:`| Function call<br>Matrix index<br>Property accessor<br>Key/value separator
`'` | Matrix transpose
`!` | Factorial
`^`, `.^` | Exponentiation
`+`, `-`, `~`, `not` | Unary plus, unary minus, bitwise not, logical not
`x unit` | Unit
`*`, `/`, `.*`, `./`, `%`, `mod` | Multiply, divide, modulus, implicit multiply
`+`, `-` | Add, subtract
`:` | Range
`to`, `in` | Unit conversion
`<<`, `>>`, `>>>` | Bitwise left shift, bitwise right arithmetic shift, bitwise right logical shift
`==`, `!=`, `<`, `>`, `<=`, `>=` | Relational
`&` | Bitwise and
<code>^&#124;</code> | Bitwise xor
<code>&#124;</code> | Bitwise or
`and` | Logical and
`xor` | Logical xor
`or` | Logical or
`?`, `:` | Conditional expression
`=` | Assignment
`,` | Parameter and column separator
`;` | Row separator
`\n`, `;` | Statement separators
## Functions
Functions are called by entering their name, followed by zero or more
arguments enclosed by parentheses. All available functions are listed on the
page [Functions](../reference/functions.md).
```js
math.eval('sqrt(25)'); // 5
math.eval('log(1000, 3 + 7)'); // 4
math.eval('sin(pi / 4)'); // 0.7071067811865475
```
New functions can be defined using the `function` keyword. Functions can be
defined with multiple variables. Function assignments are limited: they can
only be defined on a single line.
```js
var parser = math.parser();
parser.eval('f(x) = x ^ 2 - 5');
parser.eval('f(2)'); // -1
parser.eval('f(3)'); // 4
parser.eval('g(x, y) = x ^ y');
parser.eval('g(2, 3)'); // 8
```
Math.js itself heavily uses typed functions, which ensure correct inputs and
throws meaningful errors when the input arguments are invalid. One can create
a [typed-function](https://github.com/josdejong/typed-function) in the
expression parser like:
```js
var parser = math.parser();
parser.eval('f = typed({"number": f(x) = x ^ 2 - 5})');
```
## Constants and variables
Math.js has a number of built-in constants such as `pi` and `e`.
All available constants are listed on he page
[Constants](../reference/constants.md).
```js
// use constants
math.eval('pi'); // 3.141592653589793
math.eval('e ^ 2'); // 7.3890560989306495
math.eval('log(e)'); // 1
math.eval('e ^ (pi * i) + 1'); // ~0 (Euler)
```
Variables can be defined using the assignment operator `=`, and can be used
like constants.
```js
var parser = math.parser();
// define variables
parser.eval('a = 3.4'); // 3.4
parser.eval('b = 5 / 2'); // 2.5
// use variables
parser.eval('a * b'); // 8.5
```
Variable names must:
- Begin with an "alpha character", which is:
- A latin letter (upper or lower case). Ascii: `a-z`, `A-Z`
- An underscore. Ascii: `_`
- A latin letter with accents. Unicode: `\u00C0` - `\u02AF`
- A greek letter. Unicode: `\u0370` - `\u03FF`
- A letter-like character. Unicode: `\u2100` - `\u214F`
- A mathematical alphanumeric symbol. Unicode: `\u{1D400}` - `\u{1D7FF}` excluding invalid code points
- Contain only alpha characters (above) and digits `0-9`
- Not be any of the following: `mod`, `to`, `in`, `and`, `xor`, `or`, `not`, `end`. It is possible to assign to some of these, but that's not recommended.
It is possible to customize the allowed alpha characters, see [Customize supported characters](customization.md#customize-supported-characters) for more information.
## Data types
The expression parser supports booleans, numbers, complex numbers, units,
strings, matrices, and objects.
### Booleans
Booleans `true` and `false` can be used in expressions.
```js
// use booleans
math.eval('true'); // true
math.eval('false'); // false
math.eval('(2 == 3) == false'); // true
```
Booleans can be converted to numbers and strings and vice versa using the
functions `number` and `boolean`, and `string`.
```js
// convert booleans
math.eval('number(true)'); // 1
math.eval('string(false)'); // "false"
math.eval('boolean(1)'); // true
math.eval('boolean("false")'); // false
```
### Numbers
The most important and basic data type in math.js are numbers. Numbers use a
point as decimal mark. Numbers can be entered with exponential notation.
Examples:
```js
// numbers in math.js
math.eval('2'); // 2
math.eval('3.14'); // 3.14
math.eval('1.4e3'); // 1400
math.eval('22e-3'); // 0.022
```
A number can be converted to a string and vice versa using the functions
`number` and `string`.
```js
// convert a string into a number
math.eval('number("2.3")'); // 2.3
math.eval('string(2.3)'); // "2.3"
```
Math.js uses regular JavaScript numbers, which are floating points with a
limited precision and limited range. The limitations are described in detail
on the page [Numbers](../datatypes/numbers.md).
```js
math.eval('1e-325'); // 0
math.eval('1e309'); // Infinity
math.eval('-1e309'); // -Infinity
```
When doing calculations with floats, one can very easily get round-off errors:
```js
// round-off error due to limited floating point precision
math.eval('0.1 + 0.2'); // 0.30000000000000004
```
When outputting results, the function `math.format` can be used to hide
these round-off errors when outputting results for the user:
```js
var ans = math.eval('0.1 + 0.2'); // 0.30000000000000004
math.format(ans, {precision: 14}); // "0.3"
```
### BigNumbers
Math.js supports BigNumbers for calculations with an arbitrary precision.
The pros and cons of Number and BigNumber are explained in detail on the page
[Numbers](../datatypes/numbers.md).
BigNumbers are slower but have a higher precision. Calculations with big
numbers are supported only by arithmetic functions.
BigNumbers can be created using the `bignumber` function:
```js
math.eval('bignumber(0.1) + bignumber(0.2)'); // BigNumber, 0.3
```
The default number type of the expression parser can be changed at instantiation
of math.js. The expression parser parses numbers as BigNumber by default:
```js
// Configure the type of number: 'number' (default), 'BigNumber', or 'Fraction'
math.config({number: 'BigNumber'});
// all numbers are parsed as BigNumber
math.eval('0.1 + 0.2'); // BigNumber, 0.3
```
BigNumbers can be converted to numbers and vice versa using the functions
`number` and `bignumber`. When converting a BigNumber to a Number, the high
precision of the BigNumber will be lost. When a BigNumber is too large to be represented
as Number, it will be initialized as `Infinity`.
### Complex numbers
Complex numbers can be created using the imaginary unit `i`, which is defined
as `i^2 = -1`. Complex numbers have a real and complex part, which can be
retrieved using the functions `re` and `im`.
```js
var parser = math.parser();
// create complex numbers
parser.eval('a = 2 + 3i'); // Complex, 2 + 3i
parser.eval('b = 4 - i'); // Complex, 4 - i
// get real and imaginary part of a complex number
parser.eval('re(a)'); // Number, 2
parser.eval('im(a)'); // Number, 3
// calculations with complex numbers
parser.eval('a + b'); // Complex, 6 + 2i
parser.eval('a * b'); // Complex, 11 + 10i
parser.eval('i * i'); // Number, -1
parser.eval('sqrt(-4)'); // Complex, 2i
```
Math.js does not automatically convert complex numbers with an imaginary part
of zero to numbers. They can be converted to a number using the function
`number`.
```js
// convert a complex number to a number
var parser = math.parser();
parser.eval('a = 2 + 3i'); // Complex, 2 + 3i
parser.eval('b = a - 3i'); // Complex, 2 + 0i
parser.eval('number(b)'); // Number, 2
parser.eval('number(a)'); // Error: 2 + i is no valid number
```
### Units
math.js supports units. Units can be used in the arithmetic operations
add, subtract, multiply, divide, and exponentiation.
Units can also be converted from one to another.
An overview of all available units can be found on the page
[Units](../datatypes/units.md).
Units can be converted using the operator `to` or `in`.
```js
// create a unit
math.eval('5.4 kg'); // Unit, 5.4 kg
// convert a unit
math.eval('2 inch to cm'); // Unit, 5.08 cm
math.eval('20 celsius in fahrenheit'); // Unit, ~68 fahrenheit
math.eval('90 km/h to m/s'); // Unit, 25 m / s
// convert a unit to a number
// A second parameter with the unit for the exported number must be provided
math.eval('number(5 cm, mm)'); // Number, 50
// calculations with units
math.eval('0.5kg + 33g'); // Unit, 0.533 kg
math.eval('3 inch + 2 cm'); // Unit, 3.7874 inch
math.eval('3 inch + 2 cm'); // Unit, 3.7874 inch
math.eval('12 seconds * 2'); // Unit, 24 seconds
math.eval('sin(45 deg)'); // Number, 0.7071067811865475
math.eval('9.81 m/s^2 * 5 s to mi/h') // Unit, 109.72172512527 mi / h
```
### Strings
Strings are enclosed by double quotes ". Strings can be concatenated using the
function `concat` (not by adding them using `+` like in JavaScript). Parts of
a string can be retrieved or replaced by using indexes. Strings can be converted
to a number using function `number`, and numbers can be converted to a string
using function `string`.
When setting the value of a character in a string, the character that has been
set is returned. Likewise, when a range of characters is set, that range of
characters is returned.
```js
var parser = math.parser();
// create a string
parser.eval('"hello"'); // String, "hello"
// string manipulation
parser.eval('a = concat("hello", " world")'); // String, "hello world"
parser.eval('size(a)'); // Matrix [11]
parser.eval('a[1:5]'); // String, "hello"
parser.eval('a[1] = "H"'); // String, "H"
parser.eval('a[7:12] = "there!"'); // String, "there!"
parser.eval('a'); // String, "Hello there!"
// string conversion
parser.eval('number("300")'); // Number, 300
parser.eval('string(300)'); // String, "300"
```
Strings can be used in the `eval` function, to parse expressions inside
the expression parser:
```js
math.eval('eval("2 + 3")'); // 5
```
### Matrices
Matrices can be created by entering a series of values between square brackets,
elements are separated by a comma `,`.
A matrix like `[1, 2, 3]` will create a vector, a 1-dimensional matrix with
size `[3]`. To create a multi-dimensional matrix, matrices can be nested into
each other. For easier creation of two-dimensional matrices, a semicolon `;`
can be used to separate rows in a matrix.
```js
// create a matrix
math.eval('[1, 2, 3]'); // Matrix, size [3]
math.eval('[[1, 2, 3], [4, 5, 6]]'); // Matrix, size [2, 3]
math.eval('[[[1, 2], [3, 4]], [[5, 6], [7, 8]]]'); // Matrix, size [2, 2, 2]
// create a two dimensional matrix
math.eval('[1, 2, 3; 4, 5, 6]'); // Matrix, size [2, 3]
```
Another way to create filled matrices is using the functions `zeros`, `ones`,
`eye`, and `range`.
```js
// initialize a matrix with ones or zeros
math.eval('zeros(3, 2)'); // Matrix, [[0, 0], [0, 0], [0, 0]], size [3, 2]
math.eval('ones(3)'); // Matrix, [1, 1, 1], size [3]
math.eval('5 * ones(2, 2)'); // Matrix, [[5, 5], [5, 5]], size [2, 2]
// create an identity matrix
math.eval('eye(2)'); // Matrix, [[1, 0], [0, 1]], size [2, 2]
// create a range
math.eval('1:4'); // Matrix, [1, 2, 3, 4], size [4]
math.eval('0:2:10'); // Matrix, [0, 2, 4, 6, 8, 10], size [6]
```
A subset can be retrieved from a matrix using indexes and a subset of a matrix
can be replaced by using indexes. Indexes are enclosed in square brackets, and
contain a number or a range for each of the matrix dimensions. A range can have
its start and/or end undefined. When the start is undefined, the range will start
at 1, when the end is undefined, the range will end at the end of the matrix.
There is a context variable `end` available as well to denote the end of the
matrix.
*IMPORTANT: matrix indexes and ranges work differently from the math.js indexes
in JavaScript: They are one-based with an included upper-bound, similar to most
math applications.*
```js
parser = math.parser();
// create matrices
parser.eval('a = [1, 2; 3, 4]'); // Matrix, [[1, 2], [3, 4]]
parser.eval('b = zeros(2, 2)'); // Matrix, [[0, 0], [0, 0]]
parser.eval('c = 5:9'); // Matrix, [5, 6, 7, 8, 9]
// replace a subset in a matrix
parser.eval('b[1, 1:2] = [5, 6]'); // Matrix, [[5, 6], [0, 0]]
parser.eval('b[2, :] = [7, 8]'); // Matrix, [[5, 6], [7, 8]]
// perform a matrix calculation
parser.eval('d = a * b'); // Matrix, [[19, 22], [43, 50]]
// retrieve a subset of a matrix
parser.eval('d[2, 1]'); // 43
parser.eval('d[2, 1:end]'); // Matrix, [[43, 50]]
parser.eval('c[end - 1 : -1 : 2]'); // Matrix, [8, 7, 6]
```
## Objects
Objects in math.js work the same as in languages like JavaScript and Python.
An object is enclosed by square brackets `{`, `}`, and contains a set of
comma separated key/value pairs. Keys and values are separated by a colon `:`.
Keys can be a symbol like `prop` or a string like `"prop"`.
```js
math.eval('{a: 2 + 1, b: 4}'); // {a: 3, b: 4}
math.eval('{"a": 2 + 1, "b": 4}'); // {a: 3, b: 4}
```
Objects can contain objects:
```js
math.eval('{a: 2, b: {c: 3, d: 4}}'); // {a: 2, b: {c: 3, d: 4}}
```
Object properties can be retrieved or replaced using dot notation or bracket
notation. Unlike JavaScript, when setting a property value, the whole object
is returned, not the property value
```js
var scope = {
obj: {
prop: 42
}
};
// retrieve properties
math.eval('obj.prop', scope); // 42
math.eval('obj["prop"]', scope); // 42
// set properties (returns the whole object, not the property value!)
math.eval('obj.prop = 43', scope); // {prop: 43}
math.eval('obj["prop"] = 43', scope); // {prop: 43}
scope.obj; // {prop: 43}
```
## Multi-line expressions
An expression can contain multiple lines, and expressions can be spread over
multiple lines. Lines can be separated by a newline character `\n` or by a
semicolon `;`. Output of statements followed by a semicolon will be hidden from
the output, and empty lines are ignored. The output is returned as a `ResultSet`,
with an entry for every visible statement.
```js
// a multi-line expression
math.eval('1 * 3 \n 2 * 3 \n 3 * 3'); // ResultSet, [3, 6, 9]
// semicolon statements are hidden from the output
math.eval('a=3; b=4; a + b \n a * b'); // ResultSet, [7, 12]
// single expression spread over multiple lines
math.eval('a = 2 +\n 3'); // 5
math.eval('[\n 1, 2;\n 3, 4\n]'); // Matrix, [[1, 2], [3, 4]]
```
The results can be read from a `ResultSet` via the property `ResultSet.entries`
which is an `Array`, or by calling `ResultSet.valueOf()`, which returns the
array with results.
## Implicit multiplication
The expression parser supports implicit multiplication. Implicit multiplication
has the same precedence as explicit multiplications and divisions, so `3/4 mm`
is evaluated as `(3 / 4) * mm`.
Parentheses are parsed as a function call when there is a symbol or accessor on
the left hand side, like `sqrt(4)` or `obj.method(4)`. In other cases the
parentheses are interpreted as an implicit multiplication.
Implicit multiplication can be tricky as there is ambiguity on how an expression
is evaluated. Use it carefully.
Here some examples:
Expression | Evaluated as | Result
--------------- | ----------------- | ------------------
(1 + 3) pi | (1 + 3) * pi | 12.566370614359172
(4 - 1) 2 | (4 - 1) * 2 | 6
3 / 4 mm | (3 / 4) * mm | 0.75 mm
2 + 3 i | 2 + (3 * i) | 2 + 3i
(1 + 2) (4 - 2) | (1 + 2) * (4 - 2) | 6
sqrt(4) (1 + 2) | sqrt(4) * (1 + 2) | 6
## Comments
Comments can be added to explain or describe calculations in the text. A comment
starts with a sharp sign character `#`, and ends at the end of the line. A line
can contain a comment only, or can contain an expression followed by a comment.
```js
var parser = math.parser();
parser.eval('# define some variables');
parser.eval('width = 3'); // 3
parser.eval('height = 4'); // 4
parser.eval('width * height # calculate the area'); // 12
```