From b851f418e54cefe1959878f3d68899652716c393 Mon Sep 17 00:00:00 2001 From: josdejong Date: Sat, 13 Apr 2013 10:28:10 +0200 Subject: [PATCH] Implemented math.eval and a readonly option for the Parser and Scope. --- HISTORY.md | 6 + Jakefile.js | 2 +- README.md | 1 + math.js | 5411 ++++++++++++++++++------------------ math.min.js | 6 +- src/expr/Parser.js | 29 +- src/expr/Scope.js | 25 +- src/function/utils/eval.js | 22 + test/expr/parser.js | 7 + test/function/util.js | 10 + 10 files changed, 2822 insertions(+), 2697 deletions(-) create mode 100644 src/function/utils/eval.js diff --git a/HISTORY.md b/HISTORY.md index a3f885469..592bdabe3 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -2,6 +2,12 @@ https://github.com/josdejong/mathjs +## not yet released, version 0.7.0 + +- Implemented method math.eval, which uses a readonly parser to evaluate + expressions. + + ## 2013-04-13, version 0.6.0 - Implemented chained operations via method math.select(). For example diff --git a/Jakefile.js b/Jakefile.js index 62c49aaf6..7007ff2ca 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -44,7 +44,6 @@ task('concat', function () { './src/type/**/*.js', './src/constants.js', './src/functions.js', - './src/function/**/*.js', './src/expr/node/Node.js', './src/expr/node/Symbol.js', './src/expr/node/Constant.js', @@ -56,6 +55,7 @@ task('concat', function () { './src/expr/Scope.js', './src/expr/Parser.js', './src/expr/Workspace.js', + './src/function/**/*.js', './src/compatibility.js', './src/init.js' ], diff --git a/README.md b/README.md index 17735f975..af4e661f1 100644 --- a/README.md +++ b/README.md @@ -455,6 +455,7 @@ types (Number, Complex, Unit, String, and Array) where applicable. ### Utils - math.clone(x) +- math.eval(expr) - math.format([template, ] values) - math.import(filename | object, override) - math.select([x]) diff --git a/math.js b/math.js index dd4be8453..74d0bc596 100644 --- a/math.js +++ b/math.js @@ -2958,6 +2958,2714 @@ function newArgumentsError(name, count, min, max) { return new SyntaxError(msg); } +/** + * Node + */ +function Node() {} + +math.expr.node.Node = Node; + +/** + * Evaluate the node + * @return {*} result + */ +Node.prototype.eval = function () { + throw new Error('Cannot evaluate a Node interface'); +}; + +/** + * Get string representation + * @return {String} + */ +Node.prototype.toString = function() { + return ''; +}; + +/** + * @constructor Symbol + * A symbol can hold and evaluate a variable or function with parameters. + * @param {String} [name] + * @param {function} fn + * @param {Node[]} params + * @extends {Node} + */ +function Symbol(name, fn, params) { + this.name = name; + this.fn = fn; + this.params = params; +} + +Symbol.prototype = new Node(); + +math.expr.node.Symbol = Symbol; + +/** + * Check whether the Symbol has one or multiple parameters set. + * @return {Boolean} + */ +Symbol.prototype.hasParams = function () { + return (this.params != undefined && this.params.length > 0); +}; + +/** + * Evaluate the symbol + * @return {*} result + * @override + */ +Symbol.prototype.eval = function() { + var fn = this.fn; + if (fn === undefined) { + throw new Error('Undefined symbol ' + this.name); + } + + // evaluate the parameters + var results = this.params.map(function (param) { + return param.eval(); + }); + + // evaluate the function + return fn.apply(this, results); +}; + +/** + * Get string representation + * @return {String} str + * @override + */ +Symbol.prototype.toString = function() { + // variable. format the symbol like "myvar" + if (this.name && !this.params) { + return this.name; + } + + /* TODO: determine if the function is an operator + // operator. format the operation like "(2 + 3)" + if (this.fn && (this.fn instanceof math.fn.Operator)) { + if (this.params && this.params.length == 2) { + return '(' + + this.params[0].toString() + ' ' + + this.name + ' ' + + this.params[1].toString() + ')'; + } + } + */ + + // function. format the operation like "f(2, 4.2)" + var str = this.name; + if (this.params && this.params.length) { + str += '(' + this.params.join(', ') + ')'; + } + return str; +}; + +/** + * @constructor Constant + * @param {*} value + * @extends {Node} + */ +function Constant(value) { + this.value = value; +} + +Constant.prototype = new Node(); + +math.expr.node.Constant = Constant; + +/** + * Evaluate the constant + * @return {*} value + */ +Constant.prototype.eval = function () { + return this.value; +}; + +/** + * Get string representation + * @return {String} str + */ +Constant.prototype.toString = function() { + return this.value ? math.format(this.value) : ''; +}; + +/** + * @constructor MatrixNode + * Holds an n-dimensional array with nodes + * @param {Array} nodes + * @extends {Node} + */ +function MatrixNode(nodes) { + this.nodes = nodes || []; +} + +MatrixNode.prototype = new Node(); + +math.expr.node.MatrixNode = MatrixNode; + +(function () { + /** + * Evaluate the array + * @return {Matrix} results + * @override + */ + MatrixNode.prototype.eval = function() { + // recursively evaluate the nodes in the array, and merge the result + var array = evalArray(this.nodes); + if (containsMatrix(array)) { + array = merge(array); + } + return new Matrix(array); + }; + + /** + * Recursively evaluate an array with nodes + * @param {Array} array + * @returns {Array} results + */ + function evalArray(array) { + return array.map(function (child) { + if (child instanceof Array) { + // evaluate a nested array + return evalArray(child); + } + else { + // evaluate a node (end point) + return child.eval(); + } + }) + } + + /** + * Merge nested Matrices in an Array. + * @param {Array} array Two-dimensional array containing Matrices + * @return {Array} merged The merged array (two-dimensional) + */ + function merge (array) { + var merged = []; + var rows = array.length; + for (var r = 0; r < rows; r++) { + var row = array[r]; + var cols = row.length; + var submatrix = null; + var submatrixRows = null; + for (var c = 0; c < cols; c++) { + var entry = math.clone(row[c]); + var size; + if (entry instanceof Matrix) { + // get the data from the matrix + size = entry.size(); + entry = entry.valueOf(); + if (size.length == 1) { + entry = [entry]; + size = [1, size[0]]; + } + else if (size.length > 2) { + throw new Error('Cannot merge a multi dimensional matrix'); + } + } + else if (entry instanceof Range) { + // change range into an 1xn matrix + entry = [entry.valueOf()]; + size = [1, entry[0].length]; + } + else { + // change scalar into a 1x1 matrix + size = [1, 1]; + entry = [[entry]]; + } + + // check the height of this row + if (submatrix == null) { + // first entry + submatrix = entry; + submatrixRows = size[0]; + } + else if (size[0] == submatrixRows) { + // merge + for (var s = 0; s < submatrixRows; s++) { + submatrix[s] = submatrix[s].concat(entry[s]); + } + } + else { + // no good... + throw new Error('Dimension mismatch ' + + '(' + size[0] + ' != ' + submatrixRows + ')'); + } + } + + // merge the submatrix + merged = merged.concat(submatrix); + } + + return merged; + } + + /** + * Recursively test whether a multidimensional array contains at least one + * Matrix or Range. + * @param {Array} array + * @return {Boolean} containsMatrix + */ + function containsMatrix(array) { + return array.some(function (child) { + if (child instanceof Matrix || child instanceof Range) { + return true; + } + else if (child instanceof Array) { + return containsMatrix(child); + } + else { + return false; + } + }); + } + + /** + * Get string representation + * @return {String} str + * @override + */ + MatrixNode.prototype.toString = function() { + return util.formatArray(this.nodes); + }; +})(); +/** + * @constructor Block + * Holds a set with nodes + * @extends {Node} + */ +function Block() { + this.params = []; + this.visible = []; +} + +Block.prototype = new Node(); + +math.expr.node.Block = Block; + +/** + * Add a parameter + * @param {Node} param + * @param {Boolean} [visible] true by default + */ +Block.prototype.add = function (param, visible) { + var index = this.params.length; + this.params[index] = param; + this.visible[index] = (visible != undefined) ? visible : true; +}; + +/** + * Evaluate the set + * @return {*[]} results + * @override + */ +Block.prototype.eval = function() { + // evaluate the parameters + var results = []; + for (var i = 0, iMax = this.params.length; i < iMax; i++) { + var result = this.params[i].eval(); + if (this.visible[i]) { + results.push(result); + } + } + + return results; +}; + +/** + * Get string representation + * @return {String} str + * @override + */ +Block.prototype.toString = function() { + var strings = []; + + for (var i = 0, iMax = this.params.length; i < iMax; i++) { + if (this.visible[i]) { + strings.push('\n ' + this.params[i].toString()); + } + } + + return '[' + strings.join(',') + '\n]'; +}; + +/** + * @constructor Assignment + * @param {String} name Symbol name + * @param {Node[] | undefined} params Zero or more parameters + * @param {Node} expr The expression defining the symbol + * @param {function} result placeholder for the result + */ +function Assignment(name, params, expr, result) { + this.name = name; + this.params = params; + this.expr = expr; + this.result = result; +} + +Assignment.prototype = new Node(); + +math.expr.node.Assignment = Assignment; + +/** + * Evaluate the assignment + * @return {*} result + */ +Assignment.prototype.eval = function() { + if (this.expr === undefined) { + throw new Error('Undefined symbol ' + this.name); + } + + var result; + var params = this.params; + + if (params && params.length) { + // change part of a matrix, for example "a=[]", "a(2,3)=4.5" + var paramResults = []; + this.params.forEach(function (param) { + paramResults.push(param.eval()); + }); + + var exprResult = this.expr.eval(); + + // test if definition is currently undefined + if (this.result.value == undefined) { + throw new Error('Undefined symbol ' + this.name); + } + + var prevResult = this.result(); + // TODO: check type of prevResult: Matrix, Array, String, other... + if (!prevResult.set) { + throw new TypeError('Cannot apply a subset to object of type ' + + math.typeof(prevResult)); + + } + result = prevResult.set(paramResults, exprResult); + + this.result.value = result; + } + else { + // variable definition, for example "a = 3/4" + result = this.expr.eval(); + this.result.value = result; + } + + return result; +}; + +/** + * Get string representation + * @return {String} + */ +Assignment.prototype.toString = function() { + var str = ''; + + str += this.name; + if (this.params && this.params.length) { + str += '(' + this.params.join(', ') + ')'; + } + str += ' = '; + str += this.expr.toString(); + + return str; +}; + +/** + * @constructor Arguments + * invoke a list with parameters on the results of a node + * @param {Node} object + * @param {Node[]} params + */ +function Arguments (object, params) { + this.object = object; + this.params = params; +} + +Arguments.prototype = new Node(); + +math.expr.node.Arguments = Arguments; + +/** + * Evaluate the parameters + * @return {*} result + */ +Arguments.prototype.eval = function() { + var object = this.object; + if (object == undefined) { + throw new Error ('Node undefined'); + } + var objectRes = object.eval(); + + // evaluate the parameters + var params = this.params; + var paramsRes = []; + for (var i = 0, len = params.length; i < len; i++) { + paramsRes[i] = params[i].eval(); + } + + // TODO: check type of objectRes + if (!objectRes.get) { + throw new TypeError('Cannot apply arguments to object of type ' + + math.typeof(objectRes)); + } + return objectRes.get(paramsRes); +}; + +/** + * Get string representation + * @return {String} str + */ +Arguments.prototype.toString = function() { + // format the arguments like "(2, 4.2)" + var str = this.object ? this.object.toString() : ''; + if (this.params) { + str += '(' + this.params.join(', ') + ')'; + } + return str; +}; + +/** + * @constructor FunctionAssignment + * assigns a custom defined function + * + * @param {String} name Function name + * @param {String[]} variableNames Variable names + * @param {function[]} variables Links to the variables in a scope + * @param {Node} expr The function expression + * @param {function} result Link to store the result + */ +function FunctionAssignment(name, variableNames, variables, expr, result) { + this.name = name; + this.variables = variables; + + this.values = []; + for (var i = 0, iMax = this.variables.length; i < iMax; i++) { + this.values[i] = (function () { + var value = function () { + return value.value; + }; + value.value = undefined; + return value; + })(); + } + + this.def = this.createFunction(name, variableNames, variables, expr); + + this.result = result; +} + +FunctionAssignment.prototype = new Node(); + +math.expr.node.FunctionAssignment = FunctionAssignment; + +/** + * Create a function from the function assignment + * @param {String} name Function name + * @param {String[]} variableNames Variable names + * @param {function[]} values Zero or more functions + * @param {Node} expr The function expression + * + */ +FunctionAssignment.prototype.createFunction = function (name, variableNames, + values, expr) { + var fn = function () { + // validate correct number of arguments + var valuesNum = values ? values.length : 0; + var argumentsNum = arguments ? arguments.length : 0; + if (valuesNum != argumentsNum) { + throw newArgumentsError(name, argumentsNum, valuesNum); + } + + // fill in all parameter values + if (valuesNum > 0) { + for (var i = 0; i < valuesNum; i++){ + values[i].value = arguments[i]; + } + } + + // evaluate the expression + return expr.eval(); + }; + + fn.toString = function() { + return name + '(' + variableNames.join(', ') + ')'; + }; + + return fn; +}; + +/** + * Evaluate the function assignment + * @return {function} result + */ +FunctionAssignment.prototype.eval = function() { + // link the variables to the values of this function assignment + var variables = this.variables, + values = this.values; + for (var i = 0, iMax = variables.length; i < iMax; i++) { + variables[i].value = values[i]; + } + + // put the definition in the result + this.result.value = this.def; + + // TODO: what to return? a neat "function y(x) defined"? + return this.def; +}; + +/** + * get string representation + * @return {String} str + */ +FunctionAssignment.prototype.toString = function() { + return this.def.toString(); +}; + + +/** + * Scope + * A scope stores functions. + * + * @constructor mathnotepad.Scope + * @param {Scope} [parentScope] + * @param {Object} [options] Available options: + * {boolean} readonly (false by default). + */ +math.expr.Scope = function Scope(parentScope, options) { + this.readonly = false; + if (options && options.readonly != undefined) { + this.readonly = options.readonly; + } + + this.parentScope = parentScope; + this.nestedScopes = undefined; + + this.symbols = {}; // the actual symbols + + // the following objects are just used to test existence. + this.defs = {}; // definitions by name (for example "a = [1, 2; 3, 4]") + this.updates = {}; // updates by name (for example "a(2, 1) = 5.2") + this.links = {}; // links by name (for example "2 * a") +}; + +// TODO: rethink the whole scoping solution again. Try to simplify + +math.expr.Scope.prototype = { + /** + * Create a nested scope + * The variables in a nested scope are not accessible from the parent scope + * @return {math.expr.Scope} nestedScope + */ + createNestedScope: function () { + if (this.readonly) { + throw new Error('Cannot create nested scope: Scope is read-only'); + } + + var nestedScope = new math.expr.Scope(this); + if (!this.nestedScopes) { + this.nestedScopes = []; + } + this.nestedScopes.push(nestedScope); + return nestedScope; + }, + + /** + * Clear all symbols in this scope and its nested scopes + * (parent scope will not be cleared) + */ + clear: function () { + if (this.readonly) { + throw new Error('Cannot clear scope: Scope is read-only'); + } + + this.symbols = {}; + this.defs = {}; + this.links = {}; + this.updates = {}; + + if (this.nestedScopes) { + var nestedScopes = this.nestedScopes; + for (var i = 0, iMax = nestedScopes.length; i < iMax; i++) { + nestedScopes[i].clear(); + } + } + }, + + /** + * create a symbol + * @param {String} name + * @return {function} symbol + * @private + */ + createSymbol: function (name) { + var symbol = this.symbols[name]; + if (!symbol) { + // get a link to the last definition + var lastDef = this.findDef(name); + + // create a new symbol + symbol = this.newSymbol(name, lastDef); + this.symbols[name] = symbol; + + } + return symbol; + }, + + /** + * Create a new symbol + * @param {String} name + * @param {*} [value] + * @return {function} symbol + * @private + */ + newSymbol: function (name, value) { + // create a new symbol + var scope = this; + var symbol = function () { + var args, i; + if (!symbol.value) { + // try to resolve again + symbol.value = scope.findDef(name); + + if (!symbol.value) { + throw new Error('Undefined symbol ' + name); + } + } + if (typeof symbol.value === 'function') { + return symbol.value.apply(null, arguments); + } + else if (symbol.value instanceof Matrix || symbol.value instanceof Range || symbol.value instanceof Array) { + if (arguments.length) { + var matrix = (symbol.value instanceof Array) ? new Matrix(symbol.value) : symbol.value; + args = []; + for (i = 0; i < arguments.length; i++) { + args[i] = arguments[i]; + } + return matrix.get(args); + } + else { + return symbol.value; + } + } + // TODO: implement get subset for all types + else { + return symbol.value; + } + }; + + symbol.value = value; + + symbol.toString = function () { + return symbol.value ? symbol.value.toString() : ''; + }; + + return symbol; + }, + + /** + * create a link to a value. + * @param {String} name + * @return {function} symbol + */ + createLink: function (name) { + var symbol = this.links[name]; + if (!symbol) { + symbol = this.createSymbol(name); + this.links[name] = symbol; + } + return symbol; + }, + + /** + * Create a variable definition + * Returns the created symbol + * @param {String} name + * @param {*} [value] + * @return {function} symbol + */ + createDef: function (name, value) { + if (this.readonly) { + throw new Error('Cannot create variable: Scope is read-only'); + } + + var symbol = this.defs[name]; + if (!symbol) { + symbol = this.createSymbol(name); + this.defs[name] = symbol; + } + if (symbol && value != undefined) { + symbol.value = value; + } + return symbol; + }, + + /** + * Create a variable update definition + * Returns the created symbol + * @param {String} name + * @return {function} symbol + */ + createUpdate: function (name) { + if (this.readonly) { + throw new Error('Cannot update variable: Scope is read-only'); + } + + var symbol = this.updates[name]; + if (!symbol) { + symbol = this.createLink(name); + this.updates[name] = symbol; + } + return symbol; + }, + + /** + * Create a constant + * @param {String} name + * @param {*} value + * @return {function} symbol + * @private + */ + createConstant: function (name, value) { + var symbol = this.newSymbol(name, value); + this.symbols[name] = symbol; + this.defs[name] = symbol; + return symbol; + }, + + /** + * get the link to a symbol definition or update. + * If the symbol is not found in this scope, it will be looked up in its parent + * scope. + * @param {String} name + * @return {function | undefined} symbol, or undefined when not found + */ + findDef: function (name) { + var symbol; + + // check scope + symbol = this.defs[name]; + if (symbol) { + return symbol; + } + symbol = this.updates[name]; + if (symbol) { + return symbol; + } + + // check parent scope + if (this.parentScope) { + return this.parentScope.findDef(name); + } + else { + // this is the root scope (has no parent), + // try to load constants, functions, or unit from the library + + // check function (and load the function), for example "sin" or "sqrt" + // search in the mathnotepad.math namespace for this symbol + var fn = math[name]; + if (fn) { + return this.createConstant(name, fn); + } + + // Check if token is a unit + if (Unit.isPlainUnit(name)) { + var unit = new Unit(null, name); + return this.createConstant(name, unit); + } + } + + return undefined; + }, + + /** + * Remove a link to a symbol + * @param {String} name + */ + removeLink: function (name) { + delete this.links[name]; + }, + + /** + * Remove a definition of a symbol + * @param {String} name + */ + removeDef: function (name) { + delete this.defs[name]; + }, + + /** + * Remove an update definition of a symbol + * @param {String} name + */ + removeUpdate: function (name) { + delete this.updates[name]; + }, + + /** + * initialize the scope and its nested scopes + * + * All functions are linked to their previous definition + * If there is no parentScope, or no definition of the func in the parent scope, + * the link will be set undefined + */ + init: function () { + var symbols = this.symbols; + var parentScope = this.parentScope; + + for (var name in symbols) { + if (symbols.hasOwnProperty(name)) { + var symbol = symbols[name]; + symbol.value = (parentScope ? parentScope.findDef(name) : undefined); + } + } + + if (this.nestedScopes) { + this.nestedScopes.forEach(function (nestedScope) { + nestedScope.init(); + }); + } + }, + + /** + * Check whether this scope or any of its nested scopes contain a link to a + * symbol with given name + * @param {String} name + * @return {boolean} hasLink True if a link with given name is found + */ + hasLink: function (name) { + if (this.links[name]) { + return true; + } + + if (this.nestedScopes) { + var nestedScopes = this.nestedScopes; + for (var i = 0, iMax = nestedScopes.length; i < iMax; i++) { + if (nestedScopes[i].hasLink(name)) { + return true; + } + } + } + + return false; + }, + + /** + * Check whether this scope contains a definition of a symbol with given name + * @param {String} name + * @return {boolean} hasDef True if a definition with given name is found + */ + hasDef: function (name) { + return (this.defs[name] != undefined); + }, + + /** + * Check whether this scope contains an update definition of a symbol with + * given name + * @param {String} name + * @return {boolean} hasUpdate True if an update definition with given name is found + */ + hasUpdate: function (name) { + return (this.updates[name] != undefined); + }, + + /** + * Retrieve all undefined symbols + * @return {function[]} undefinedSymbols All symbols which are undefined + */ + getUndefinedSymbols: function () { + var symbols = this.symbols; + var undefinedSymbols = []; + for (var i in symbols) { + if (symbols.hasOwnProperty(i)) { + var symbol = symbols[i]; + if (symbol.value == undefined) { + undefinedSymbols.push(symbol); + } + } + } + + if (this.nestedScopes) { + this.nestedScopes.forEach(function (nestedScope) { + undefinedSymbols = + undefinedSymbols.concat(nestedScope.getUndefinedSymbols()); + }); + } + + return undefinedSymbols; + } +}; + +(function () { + /** + * @constructor math.expr.Parser + * Parser parses math expressions and evaluates them or returns a node tree. + * + * @param {Object} [options] Available options: + * {boolean} readonly (false by default). + * + * Methods: + * var result = parser.eval(expr); // evaluate an expression + * var value = parser.get(name); // retrieve a variable from the parser + * parser.set(name, value); // set a variable in the parser + * + * // it is possible to parse an expression into a node tree: + * var node = parser.parse(expr); // parse an expression into a node tree + * var result = node.eval(); // evaluate a parsed node + * + * Example usage: + * var parser = new math.expr.Parser(); + * // Note: there is a convenience method which can be used instead: + * // var parser = new math.parser(); + * + * // evaluate expressions + * var a = parser.eval('sqrt(3^2 + 4^2)'); // 5 + * var b = parser.eval('sqrt(-4)'); // 2i + * var c = parser.eval('2 inch in cm'); // 5.08 cm + * var d = 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('function 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'); // 7 + * var f = parser.get('f'); // function + * var g = f(3, 2); // 9 + * parser.set('h', 500); + * var i = 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(); + */ + math.expr.Parser = function Parser(options) { + if (this.constructor != Parser) { + throw new SyntaxError( + 'Parser constructor must be called with the new operator'); + } + + this.scope = new math.expr.Scope(null, options); + }; + + /** + * Parse an expression end return the parsed function node. + * The node can be evaluated via node.eval() + * @param {String} expression + * @param {Scope} [scope] + * @return {Node} node + * @throws {Error} + */ + math.expr.Parser.prototype.parse = function (expression, scope) { + expr = expression || ''; + + if (!scope) { + scope = this.scope; + } + + return parse_start(scope); + }; + + /** + * Parse and evaluate the given expression + * @param {String} expression A string containing an expression, for example "2+3" + * @return {*} result The result, or undefined when the expression was + * empty + * @throws {Error} + */ + math.expr.Parser.prototype.eval = function (expression) { + var node = this.parse(expression); + return node.eval(); + }; + + /** + * Get a variable (a function or variable) by name from the parsers scope. + * Returns undefined when not found + * @param {String} name + * @return {* | undefined} value + */ + math.expr.Parser.prototype.get = function (name) { + var symbol = this.scope.findDef(name); + if (symbol) { + return symbol.value; + } + return undefined; + }; + + /** + * Set a symbol (a function or variable) by name from the parsers scope. + * @param {String} name + * @param {* | undefined} value + */ + math.expr.Parser.prototype.set = function (name, value) { + this.scope.createDef(name, value); + }; + + /** + * Clear the scope with variables and functions + */ + math.expr.Parser.prototype.clear = function () { + this.scope.clear(); + }; + + // token types enumeration + var TOKENTYPE = { + NULL : 0, + DELIMITER : 1, + NUMBER : 2, + SYMBOL : 3, + UNKNOWN : 4 + }; + + var expr = ''; // current expression + var index = 0; // current index in expr + var c = ''; // current token character in expr + var token = ''; // current token + var token_type = TOKENTYPE.NULL; // type of the token + // TODO: do not use this.token, but a local variable var token for better speed? -> getToken() must return token. + + /** + * Get the next character from the expression. + * The character is stored into the char t. + * If the end of the expression is reached, the function puts an empty + * string in t. + * @private + */ + function getChar() { + index++; + c = expr.charAt(index); + } + + /** + * Get the first character from the expression. + * The character is stored into the char t. + * If the end of the expression is reached, the function puts an empty + * string in t. + * @private + */ + function getFirstChar() { + index = 0; + c = expr.charAt(0); + } + + /** + * Get next token in the current string expr. + * Uses the Parser data expr, e, token, t, token_type and err + * The token and token type are available at token_type and token + * @private + */ + function getToken() { + token_type = TOKENTYPE.NULL; + token = ''; + + // skip over whitespaces + while (c == ' ' || c == '\t') { // space or tab + getChar(); + } + + // skip comment + if (c == '#') { + while (c != '\n' && c != '') { + getChar(); + } + } + + // check for end of expression + if (c == '') { + // token is still empty + token_type = TOKENTYPE.DELIMITER; + return; + } + + // check for minus, comma, parentheses, quotes, newline, semicolon + if (c == '-' || c == ',' || + c == '(' || c == ')' || + c == '[' || c == ']' || + c == '\"' || c == '\n' || + c == ';' || c == ':' || + c == '!' || c == '\'') { + token_type = TOKENTYPE.DELIMITER; + token += c; + getChar(); + return; + } + + // check for operators (delimiters) + if (isDelimiter(c)) { + token_type = TOKENTYPE.DELIMITER; + while (isDelimiter(c)) { + token += c; + getChar(); + } + return; + } + + // check for a number + if (isDigitDot(c)) { + token_type = TOKENTYPE.NUMBER; + while (isDigitDot(c)) { + token += c; + getChar(); + } + + // check for scientific notation like "2.3e-4" or "1.23e50" + if (c == 'E' || c == 'e') { + token += c; + getChar(); + + if (c == '+' || c == '-') { + token += c; + getChar(); + } + + // Scientific notation MUST be followed by an exponent + if (!isDigit(c)) { + // this is no legal number, exponent is missing. + token_type = TOKENTYPE.UNKNOWN; + } + + while (isDigit(c)) { + token += c; + getChar(); + } + } + return; + } + + // check for variables or functions + if (isAlpha(c)) { + token_type = TOKENTYPE.SYMBOL; + + while (isAlpha(c) || isDigit(c)) + { + token += c; + getChar(); + } + return; + } + + // something unknown is found, wrong characters -> a syntax error + token_type = TOKENTYPE.UNKNOWN; + while (c != '') { + token += c; + getChar(); + } + throw createSyntaxError('Syntax error in part "' + token + '"'); + } + + /** + * checks if the given char c is a delimiter + * minus is not checked in this method (can be unary minus) + * @param {String} c a string with one character + * @return {Boolean} + * @private + */ + function isDelimiter (c) { + return c == '&' || + c == '|' || + c == '<' || + c == '>' || + c == '=' || + c == '+' || + c == '/' || + c == '*' || + c == '%' || + c == '^' || + c == ',' || + c == ';' || + c == '\n' || + c == '!' || + c == '\''; + } + + /** + * Check if a given name is valid + * if not, an error is thrown + * @param {String} name + * @return {boolean} valid + * @private + */ + function isValidSymbolName (name) { + for (var i = 0, iMax = name.length; i < iMax; i++) { + var c = name.charAt(i); + //var valid = (isAlpha(c) || (i > 0 && isDigit(c))); // TODO + var valid = (isAlpha(c)); + if (!valid) { + return false; + } + } + + return true; + } + + /** + * checks if the given char c is a letter (upper or lower case) + * or underscore + * @param {String} c a string with one character + * @return {Boolean} + * @private + */ + function isAlpha (c) { + return ((c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + c == '_'); + } + + /** + * checks if the given char c is a digit or dot + * @param {String} c a string with one character + * @return {Boolean} + * @private + */ + function isDigitDot (c) { + return ((c >= '0' && c <= '9') || + c == '.'); + } + + /** + * checks if the given char c is a digit + * @param {String} c a string with one character + * @return {Boolean} + * @private + */ + function isDigit (c) { + return ((c >= '0' && c <= '9')); + } + + /** + * Start of the parse levels below, in order of precedence + * @param {Scope} scope + * @return {Node} node + * @private + */ + function parse_start (scope) { + // get the first character in expression + getFirstChar(); + + getToken(); + + var node; + if (token == '') { + // empty expression + node = new Constant(undefined); + } + else { + node = parse_block(scope); + } + + // check for garbage at the end of the expression + // an expression ends with a empty character '' and token_type DELIMITER + if (token != '') { + if (token_type == TOKENTYPE.DELIMITER) { + // user entered a not existing operator like "//" + + // TODO: give hints for aliases, for example with "<>" give as hint " did you mean != ?" + throw createError('Unknown operator ' + token); + } + else { + throw createSyntaxError('Unexpected part "' + token + '"'); + } + } + + return node; + } + + /** + * Parse a block with expressions. Expressions can be separated by a newline + * character '\n', or by a semicolon ';'. In case of a semicolon, no output + * of the preceding line is returned. + * @param {Scope} scope + * @return {Node} node + * @private + */ + function parse_block (scope) { + var node, block, visible; + + if (token != '\n' && token != ';' && token != '') { + node = parse_ans(scope); + } + + while (token == '\n' || token == ';') { + if (!block) { + // initialize the block + block = new Block(); + if (node) { + visible = (token != ';'); + block.add(node, visible); + } + } + + getToken(); + if (token != '\n' && token != ';' && token != '') { + node = parse_ans(scope); + + visible = (token != ';'); + block.add(node, visible); + } + } + + if (block) { + return block; + } + + if (!node) { + node = parse_ans(scope); + } + + return node; + } + + /** + * Parse assignment of ans. + * Ans is assigned when the expression itself is no variable or function + * assignment + * @param {Scope} scope + * @return {Node} node + * @private + */ + function parse_ans (scope) { + var expression = parse_function_assignment(scope); + + if (!scope.readonly) { + // TODO: not so nice having to specify some special types here... + if (!(expression instanceof Assignment) + // !(expression instanceof FunctionAssignment) && // TODO + // !(expression instanceof plot) // TODO + ) { + // create a variable definition for ans + var name = 'ans'; + var params = undefined; + var link = scope.createDef(name); + return new Assignment(name, params, expression, link); + } + } + + return expression; + } + + /** + * Parse a function assignment like "function f(a,b) = a*b" + * @param {Scope} scope + * @return {Node} node + * @private + */ + function parse_function_assignment (scope) { + // TODO: keyword 'function' must become a reserved keyword + if (token_type == TOKENTYPE.SYMBOL && token == 'function') { + // get function name + getToken(); + if (token_type != TOKENTYPE.SYMBOL) { + throw createSyntaxError('Function name expected'); + } + var name = token; + + // get parenthesis open + getToken(); + if (token != '(') { + throw createSyntaxError('Opening parenthesis ( expected'); + } + + // get function variables + var functionScope = scope.createNestedScope(); + var variableNames = []; + var variables = []; + while (true) { + getToken(); + if (token_type == TOKENTYPE.SYMBOL) { + // store parameter + var variableName = token; + var variable = functionScope.createDef(variableName); + variableNames.push(variableName); + variables.push(variable); + } + else { + throw createSyntaxError('Variable name expected'); + } + + getToken(); + if (token == ',') { + // ok, nothing to do, read next variable + } + else if (token == ')') { + // end of variable list encountered. break loop + break; + } + else { + throw createSyntaxError('Comma , or closing parenthesis ) expected"'); + } + } + + getToken(); + if (token != '=') { + throw createSyntaxError('Equal sign = expected'); + } + + // parse the expression, with the correct function scope + getToken(); + var expression = parse_range(functionScope); + var result = scope.createDef(name); + + return new FunctionAssignment(name, variableNames, variables, + expression, result); + } + + return parse_assignment(scope); + } + + /** + * Assignment of a variable, can be a variable like "a=2.3" or a updating an + * existing variable like "matrix(2,3:5)=[6,7,8]" + * @param {Scope} scope + * @return {Node} node + * @private + */ + function parse_assignment (scope) { + var linkExisted = false; + if (token_type == TOKENTYPE.SYMBOL) { + linkExisted = scope.hasLink(token); + } + + var node = parse_range(scope); + + // TODO: support chained assignments like "a = b = 2.3" + if (token == '=') { + if (!(node instanceof Symbol)) { + throw createSyntaxError('Symbol expected at the left hand side ' + + 'of assignment operator ='); + } + var name = node.name; + var params = node.params; + + if (!linkExisted) { + // we parsed the assignment as if it where an expression instead, + // therefore, a link was created to the symbol. This link must + // be cleaned up again, and only if it wasn't existing before + scope.removeLink(name); + } + + // parse the expression, with the correct function scope + getToken(); + var expression = parse_range(scope); + var link = node.hasParams() ? scope.createUpdate(name) : scope.createDef(name); + return new Assignment(name, params, expression, link); + } + + return node; + } + + /** + * parse range, "start:end" or "start:step:end" + * @param {Scope} scope + * @return {Node} node + * @private + */ + function parse_range (scope) { + var node = parse_conditions(scope); + + if (token == ':') { + var params = [node]; + + while (token == ':') { + getToken(); + params.push(parse_conditions(scope)); + } + + if (params.length > 3) { + throw new TypeError('Invalid range'); + } + + var name = 'range'; + var fn = math.range; + node = new Symbol(name, fn, params); + } + + return node; + } + + /** + * conditions like and, or, in + * @param {Scope} scope + * @return {Node} node + * @private + */ + function parse_conditions (scope) { + var node = parse_bitwise_conditions(scope); + + // TODO: precedence of And above Or? + // TODO: implement a method for unit to number conversion + var operators = { + 'in' : 'in' + /* TODO: implement conditions + 'and' : 'and', + '&&' : 'and', + 'or': 'or', + '||': 'or', + 'xor': 'xor' + */ + }; + while (operators[token] !== undefined) { + // TODO: with all operators: only load one instance of the operator, use the scope + var name = token; + var fn = math[operators[name]]; + + getToken(); + var params = [node, parse_bitwise_conditions(scope)]; + node = new Symbol(name, fn, params); + } + + return node; + } + + /** + * conditional operators and bitshift + * @param {Scope} scope + * @return {Node} node + * @private + */ + function parse_bitwise_conditions (scope) { + var node = parse_comparison(scope); + + /* TODO: implement bitwise conditions + var operators = { + '&' : 'bitwiseand', + '|' : 'bitwiseor', + // todo: bitwise xor? + '<<': 'bitshiftleft', + '>>': 'bitshiftright' + }; + while (operators[token] !== undefined) { + var name = token; + var fn = math[operators[name]]; + + getToken(); + var params = [node, parse_comparison()]; + node = new Symbol(name, fn, params); + } + */ + + return node; + } + + /** + * comparison operators + * @param {Scope} scope + * @return {Node} node + * @private + */ + function parse_comparison (scope) { + var node = parse_addsubtract(scope); + + var operators = { + '==': 'equal', + '!=': 'unequal', + '<': 'smaller', + '>': 'larger', + '<=': 'smallereq', + '>=': 'largereq' + }; + while (operators[token] !== undefined) { + var name = token; + var fn = math[operators[name]]; + + getToken(); + var params = [node, parse_addsubtract(scope)]; + node = new Symbol(name, fn, params); + } + + return node; + } + + /** + * add or subtract + * @param {Scope} scope + * @return {Node} node + * @private + */ + function parse_addsubtract (scope) { + var node = parse_multiplydivide(scope); + + var operators = { + '+': 'add', + '-': 'subtract' + }; + while (operators[token] !== undefined) { + var name = token; + var fn = math[operators[name]]; + + getToken(); + var params = [node, parse_multiplydivide(scope)]; + node = new Symbol(name, fn, params); + } + + return node; + } + + /** + * multiply, divide, modulus + * @param {Scope} scope + * @return {Node} node + * @private + */ + function parse_multiplydivide (scope) { + var node = parse_unaryminus(scope); + + var operators = { + '*': 'multiply', + '/': 'divide', + '%': 'mod', + 'mod': 'mod' + }; + while (operators[token] !== undefined) { + var name = token; + var fn = math[operators[name]]; + + getToken(); + var params = [node, parse_unaryminus(scope)]; + node = new Symbol(name, fn, params); + } + + return node; + } + + /** + * Unary minus + * @param {Scope} scope + * @return {Node} node + * @private + */ + function parse_unaryminus (scope) { + if (token == '-') { + var name = token; + var fn = math.unaryminus; + getToken(); + var params = [parse_pow(scope)]; + + return new Symbol(name, fn, params); + } + + return parse_pow(scope); + } + + /** + * power + * Node: power operator is right associative + * @param {Scope} scope + * @return {Node} node + * @private + */ + function parse_pow (scope) { + var nodes = [ + parse_factorial(scope) + ]; + + // stack all operands of a chained power operator (like '2^3^3') + while (token == '^') { + getToken(); + nodes.push(parse_factorial(scope)); + } + + // evaluate the operands from right to left (right associative) + var node = nodes.pop(); + while (nodes.length) { + var leftNode = nodes.pop(); + var name = '^'; + var fn = math.pow; + var params = [leftNode, node]; + node = new Symbol(name, fn, params); + } + + return node; + } + + /** + * Factorial + * @param {Scope} scope + * @return {Node} node + * @private + */ + function parse_factorial (scope) { + var node = parse_transpose(scope); + + while (token == '!') { + var name = token; + var fn = math.factorial; + getToken(); + var params = [node]; + + node = new Symbol(name, fn, params); + } + + return node; + } + + /** + * Transpose + * @param {Scope} scope + * @return {Node} node + * @private + */ + function parse_transpose (scope) { + var node = parse_plot(scope); + + while (token == '\'') { + var name = token; + var fn = math.transpose; + getToken(); + var params = [node]; + + node = new Symbol(name, fn, params); + } + + return node; + } + + /** + * parse plot + * @param {Scope} scope + * @return {Node} node + * @private + */ + function parse_plot (scope) { + /* TODO: implement plot + if (token_type == TOKENTYPE.SYMBOL && + token == 'plot') { + getToken(); + + // parse the parentheses and parameters of the plot + // the parameters are something like: plot(sin(x), cos(x), x) + var functions = []; + if (token == '(') { + var plotScope = scope.createNestedScope(); + + getToken(); + functions.push(parse_range(plotScope)); + + // parse a list with parameters + while (token == ',') { + getToken(); + functions.push(parse_range(plotScope)); + } + + if (token != ')') { + throw createSyntaxError('Parenthesis ) missing'); + } + getToken(); + } + + // check what the variable of the functions is. + var variable = undefined; + var lastFunction = functions[functions.length - 1]; + if (lastFunction) { + // if the last function is a variable, remove it from the functions list + // and use its variable func + var lastIsSymbol = (lastFunction instanceof Symbol && + !lastFunction.hasParams()); + if (lastIsSymbol) { + functions.pop(); + variable = lastFunction.fn; + } + } + return new plot(functions, variable, plotScope); + } + */ + + return parse_symbol(scope); + } + + /** + * parse symbols: functions, variables, constants, units + * @param {Scope} scope + * @return {Node} node + * @private + */ + function parse_symbol (scope) { + if (token_type == TOKENTYPE.SYMBOL) { + var name = token; + + getToken(); + + var link = scope.createLink(name); + // TODO: split applying arguments from symbol? + var args = parse_arguments(scope); + var symbol = new Symbol(name, link, args); + + /* TODO: parse arguments + // parse arguments + while (token == '(') { + symbol = parse_arguments(scope, symbol); + } + */ + return symbol; + } + + return parse_string(scope); + } + + /** + * parse arguments, enclosed in parenthesis + * @param {Scope} scope + * @return {Node[]} arguments + * @private + */ + function parse_arguments (scope) { + var args = []; + if (token == '(') { + // TODO: in case of Plot, create a new scope. + + getToken(); + + if (token != ')') { + args.push(parse_range(scope)); + + // parse a list with parameters + while (token == ',') { + getToken(); + args.push(parse_range(scope)); + } + } + + if (token != ')') { + throw createSyntaxError('Parenthesis ) missing'); + } + getToken(); + } + + return args; + } + + /** + * parse a string. + * A string is enclosed by double quotes + * @param {Scope} scope + * @return {Node} node + * @private + */ + function parse_string (scope) { + if (token == '"') { + // string "..." + var str = ''; + var tPrev = ''; + while (c != '' && (c != '\"' || tPrev == '\\')) { // also handle escape character + str += c; + tPrev = c; + getChar(); + } + + getToken(); + if (token != '"') { + throw createSyntaxError('End of string " missing'); + } + getToken(); + + var node = new Constant(str); + + /* TODO: parse arguments + // parse arguments + while (token == '(') { + node = parse_arguments(scope, node); + } + */ + + return node; + } + + return parse_matrix(scope); + } + + /** + * parse the matrix + * @param {Scope} scope + * @return {Node} A MatrixNode + * @private + */ + function parse_matrix (scope) { + if (token == '[') { + // matrix [...] + var array; + + // skip newlines + getToken(); + while (token == '\n') { + getToken(); + } + + // check if this is an empty matrix "[ ]" + if (token != ']') { + // this is a non-empty matrix + var params = []; + var r = 0, c = 0; + + params[0] = [parse_range(scope)]; + + // the columns in the matrix are separated by commas, and the rows by dot-comma's + while (token == ',' || token == ';') { + if (token == ',') { + c++; + } + else { + r++; + c = 0; + params[r] = []; + } + + // skip newlines + getToken(); + while (token == '\n') { + getToken(); + } + + params[r][c] = parse_range(scope); + + // skip newlines + while (token == '\n') { + getToken(); + } + } + + var rows = params.length; + var cols = (params.length > 0) ? params[0].length : 0; + + // check if the number of columns matches in all rows + for (r = 1; r < rows; r++) { + if (params[r].length != cols) { + throw createError('Number of columns must match ' + + '(' + params[r].length + ' != ' + cols + ')'); + } + } + + if (token != ']') { + throw createSyntaxError('End of matrix ] missing'); + } + + getToken(); + array = new MatrixNode(params); + } + else { + // this is an empty matrix "[ ]" + getToken(); + array = new MatrixNode([[]]); + } + + /* TODO: parse arguments + // parse arguments + while (token == '(') { + array = parse_arguments(scope, array); + } + */ + + return array; + } + + return parse_number(scope); + } + + /** + * parse a number + * @param {Scope} scope + * @return {Node} node + * @private + */ + function parse_number (scope) { + if (token_type == TOKENTYPE.NUMBER) { + // this is a number + var number; + if (token == '.') { + number = 0.0; + } else { + number = Number(token); + } + getToken(); + + /* TODO: implicit multiplication? + // TODO: how to calculate a=3; 2/2a ? is this (2/2)*a or 2/(2*a) ? + // check for implicit multiplication + if (token_type == TOKENTYPE.VARIABLE) { + node = multiply(node, parse_pow()); + } + //*/ + + var value; + if (token_type == TOKENTYPE.SYMBOL) { + if (token == 'i' || token == 'I') { + value = new Complex(0, number); + getToken(); + return new Constant(value); + } + + if (Unit.isPlainUnit(token)) { + value = new Unit(number, token); + getToken(); + return new Constant(value); + } + + throw createTypeError('Unknown unit "' + token + '"'); + } + + // just a regular number + var node = new Constant(number); + + /* TODO: parse arguments + // parse arguments + while (token == '(') { + node = parse_arguments(scope, node); + } + */ + + return node; + } + + return parse_parentheses(scope); + } + + /** + * parentheses + * @param {Scope} scope + * @return {Node} node + * @private + */ + function parse_parentheses (scope) { + // check if it is a parenthesized expression + if (token == '(') { + // parentheses (...) + getToken(); + var node = parse_range(scope); // start again + + if (token != ')') { + throw createSyntaxError('Parenthesis ) expected'); + } + getToken(); + + /* TODO: implicit multiplication? + // TODO: how to calculate a=3; 2/2a ? is this (2/2)*a or 2/(2*a) ? + // check for implicit multiplication + if (token_type == TOKENTYPE.VARIABLE) { + node = multiply(node, parse_pow()); + } + //*/ + + /* TODO: parse arguments + // parse arguments + while (token == '(') { + node = parse_arguments(scope, node); + } + */ + + return node; + } + + return parse_end(scope); + } + + /** + * Evaluated when the expression is not yet ended but expected to end + * @param {Scope} scope + * @return {Node} res + * @private + */ + function parse_end (scope) { + if (token == '') { + // syntax error or unexpected end of expression + throw createSyntaxError('Unexpected end of expression'); + } else { + throw createSyntaxError('Value expected'); + } + } + + /** + * Shortcut for getting the current row value (one based) + * Returns the line of the currently handled expression + * @private + */ + function row () { + // TODO: also register row number during parsing + return undefined; + } + + /** + * Shortcut for getting the current col value (one based) + * Returns the column (position) where the last token starts + * @private + */ + function col () { + return index - token.length + 1; + } + + /** + * Build up an error message + * @param {String} message + * @return {String} message with row and column information + * @private + */ + function createErrorMessage (message) { + var r = row(); + var c = col(); + if (r === undefined) { + if (c === undefined) { + return message; + } else { + return message + ' (char ' + c + ')'; + } + } else { + return message + ' (line ' + r + ', char ' + c + ')'; + } + } + + /** + * Create an error + * @param {String} message + * @return {SyntaxError} instantiated error + * @private + */ + function createSyntaxError (message) { + return new SyntaxError(createErrorMessage(message)); + } + + /** + * Create an error + * @param {String} message + * @return {TypeError} instantiated error + * @private + */ + function createTypeError(message) { + return new TypeError(createErrorMessage(message)); + } + + /** + * Create an error + * @param {String} message + * @return {Error} instantiated error + * @private + */ + function createError (message) { + return new Error(createErrorMessage(message)); + } + +})(); + +(function () { + /** + * @constructor math.expr.Workspace + * + * Workspace manages a set of expressions. Expressions can be added, replace, + * deleted, and inserted in the workspace. The workspace keeps track on the + * dependencies between the expressions, and automatically updates results of + * depending expressions when variables or function definitions are changed in + * the workspace. + * + * Methods: + * var id = workspace.append(expr); + * var id = workspace.insertBefore(expr, beforeId); + * var id = workspace.insertAfter(expr, afterId); + * workspace.replace(expr, id); + * workspace.remove(id); + * workspace.clear(); + * var expr = workspace.getExpr(id); + * var result = workspace.getResult(id); + * var deps = workspace.getDependencies(id); + * var changes = workspace.getChanges(updateSeq); + * + * Usage: + * var workspace = new math.expr.Workspace(); + * var id0 = workspace.append('a = 3/4'); + * var id1 = workspace.append('a + 2'); + * console.log('a + 2 = ' + workspace.getResult(id1)); + * workspace.replace('a=5/2', id0); + * console.log('a + 2 = ' + workspace.getResult(id1)); + */ + function Workspace () { + this.idMax = -1; + this.updateSeq = 0; + this.parser = new math.expr.Parser(); + this.scope = new math.expr.Scope(); + + this.nodes = {}; + this.firstNode = undefined; + this.lastNode = undefined; + } + + math.expr.Workspace = Workspace; + + /** + * clear the workspace + */ + Workspace.prototype.clear = function () { + this.nodes = {}; + this.firstNode = undefined; + this.lastNode = undefined; + }; + + /** + * append an expression to the workspace + * @param {String} expression + * @return {Number} id of the created node + */ + Workspace.prototype.append = function (expression) { + // create the node + var id = this._getNewId(); + var parentScope = this.lastNode ? this.lastNode.scope : this.scope; + var scope = new math.expr.Scope(parentScope); + var node = new Workspace.Node({ + 'id': id, + 'expression': expression, + 'parser': this.parser, + 'scope': scope, + 'nextNode': undefined, + 'previousNode': this.lastNode + }); + this.nodes[id] = node; + + // link next and previous nodes + if (!this.firstNode) { + this.firstNode = node; + } + if (this.lastNode) { + this.lastNode.nextNode = node; + } + this.lastNode = node; + + // update this node + this._update([id]); + + return id; + }; + + /** + * insert an expression before an existing expression + * @param {String} expression the new expression + * @param {Number} beforeId id of an existing expression + * @return {Number} id id of the created node + */ + Workspace.prototype.insertBefore = function (expression, beforeId) { + var nextNode = this.nodes[beforeId]; + if (!nextNode) { + throw 'Node with id "' + beforeId + '" not found'; + } + + var previousNode = nextNode.previousNode; + + // create the node + var id = this._getNewId(); + var previousScope = previousNode ? previousNode.scope : this.scope; + var scope = new math.expr.Scope(previousScope); + var node = new Workspace.Node({ + 'id': id, + 'expression': expression, + 'parser': this.parser, + 'scope': scope, + 'nextNode': nextNode, + 'previousNode': previousNode + }); + this.nodes[id] = node; + + // link next and previous nodes + if (previousNode) { + previousNode.nextNode = node; + } + else { + this.firstNode = node; + } + nextNode.previousNode = node; + + // link to the new the scope + nextNode.scope.parentScope = node.scope; + + // update this node and all dependent nodes + var ids = this.getDependencies(id); + if (ids.indexOf(id) == -1) { + ids.unshift(id); + } + this._update(ids); + + return id; + }; + + /** + * insert an expression after an existing expression + * @param {String} expression the new expression + * @param {Number} afterId id of an existing expression + * @return {Number} id id of the created expression + */ + Workspace.prototype.insertAfter = function (expression, afterId) { + var previousNode = this.nodes[afterId]; + if (!previousNode) { + throw 'Node with id "' + afterId + '" not found'; + } + + if (previousNode == this.lastNode) { + return this.append(expression); + } + else { + return this.insertBefore(afterId + 1, expression); + } + }; + + + /** + * remove an expression. If the expression is not found, no action will + * be taken. + * @param {Number} id id of an existing expression + */ + Workspace.prototype.remove = function (id) { + var node = this.nodes[id]; + if (!node) { + throw 'Node with id "' + id + '" not found'; + } + + // get the dependencies (needed to update them after deletion of this node) + var dependentIds = this.getDependencies(id); + + // adjust links to previous and next nodes + var previousNode = node.previousNode; + var nextNode = node.nextNode; + if (previousNode) { + previousNode.nextNode = nextNode; + } + else { + this.firstNode = nextNode; + } + if (nextNode) { + nextNode.previousNode = previousNode; + } + else { + this.lastNode = previousNode; + } + + // re-link the scope + var previousScope = previousNode ? previousNode.scope : this.scope; + if (nextNode) { + nextNode.scope.parentScope = previousScope; + } + + // remove the node + delete this.nodes[id]; + + // update all dependent nodes + this._update(dependentIds); + }; + + + /** + * replace an existing expression + * @param {String} expression the new expression + * @param {Number} id id of an existing expression + */ + Workspace.prototype.replace = function (expression, id) { + var node = this.nodes[id]; + if (!node) { + throw 'Node with id "' + id + '" not found'; + } + + // get the dependencies + var dependentIds = [id]; + Workspace._merge(dependentIds, this.getDependencies(id)); + + var previousNode = node.previousNode; + var nextNode = node.nextNode; + var previousScope = previousNode ? previousNode.scope : this.scope; + + // replace the expression + node.setExpr(expression); + + // add the new dependencies + Workspace._merge(dependentIds, this.getDependencies(id)); + + // update all dependencies + this._update(dependentIds); + }; + + /** + * @constructor Workspace.Node + * @param {Object} params Object containing parameters: + * {Number} id + * {String} expression An expression, for example "2+3" + * {Parser} parser + * {Scope} scope + * {Workspace.Node} nextNode + * {Workspace.Node} previousNode + */ + Workspace.Node = function (params) { + this.id = params.id; + this.parser = params.parser; + this.scope = params.scope; + this.nextNode = params.nextNode; + this.previousNode = params.previousNode; + // TODO: throw error when id, parser, or scope is not given + + this.updateSeq = 0; + this.result = undefined; + this.setExpr(params.expression); + }; + + /** + * set the node's expression + * @param {String} expression + */ + Workspace.Node.prototype.setExpr = function (expression) { + this.expression = expression || ''; + this.scope.clear(); + this._parse(); + }; + + /** + * get the node's expression + * @return {String} expression + */ + Workspace.Node.prototype.getExpr = function () { + return this.expression; + }; + + /** + * get the result of the nodes expression + * @return {*} result + */ + Workspace.Node.prototype.getResult = function () { + // TODO: automatically evaluate when not up to date? + return this.result; + }; + + /** + * parse the node's expression + * @private + */ + Workspace.Node.prototype._parse = function () { + try { + this.fn = this.parser.parse(this.expression, this.scope); + } + catch (err) { + var value = 'Error: ' + String(err.message || err); + this.fn = new Constant(value); + } + }; + + /** + * Evaluate the node expression + * @return {*} result + */ + Workspace.Node.prototype.eval = function () { + try { + this.scope.init(); + this.result = this.fn.eval(); + } + catch (err) { + this.scope.init(); + this.result = 'Error: ' + String(err.message || err); + } + return this.result; + }; + + /** + * Merge array2 into array1, only adding distinct elements. + * The elements are not sorted. + * @param {Array} array1 + * @param {Array} array2 + * @private + */ + Workspace._merge = function (array1, array2) { + for (var i = 0, iMax = array2.length; i < iMax; i++) { + var elem = array2[i]; + if (array1.indexOf(elem) == -1) { + array1.push(elem); + } + } + }; + + /** + * Retrieve the id's of the nodes which are dependent on this node + * @param {Number} id + * @return {Number[]} id's of dependent nodes. The ids are not ordered + */ + Workspace.prototype.getDependencies = function (id) { + var ids = [], + name; + + var node = this.nodes[id]; + if (node) { + // create a list with all symbol names defined/updated in this scope + var defs = node.scope.defs; + var updates = node.scope.updates; + var symbolNames = []; + for (name in defs) { + if (defs.hasOwnProperty(name)) { + symbolNames.push(name); + } + } + for (name in updates) { + if (updates.hasOwnProperty(name) && symbolNames.indexOf(name) == -1) { + symbolNames.push(name); + } + } + + // loop through the nodes and retrieve the ids of nodes dependent on + // these values. We start at current node + var n = node.nextNode; + while (n && symbolNames.length) { + var scope = n.scope; + // loop through each of the parameters and check if the scope + // contains bindings to this parameter func + var i = 0; + while (i < symbolNames.length) { + name = symbolNames[i]; + + // check if this scope contains a link to the current symbol name + if (scope.hasLink(name) || scope.hasUpdate(name)) { + if (ids.indexOf(n.id) == -1) { + ids.push(n.id); + + // recursively check the dependencies of this id + var childIds = this.getDependencies(n.id); + Workspace._merge(ids, childIds); + } + } + + // stop propagation of the current symbol name as soon as it is + // redefined in one of the next scopes (not if it is updated) + if (scope.hasDef(name)) { + symbolNames.splice(i, 1); + i--; + } + + i++; + } + + n = n.nextNode; + } + } + + return ids; + }; + + /** + * Retrieve an expression, the original string + * @param {Number} id Id of the expression to be retrieved + * @return {String} The original expression as a string + */ + Workspace.prototype.getExpr = function (id) { + var node = this.nodes[id]; + if (!node) { + throw 'Node with id "' + id + '" not found'; + } + + return node.getExpr(); + }; + + + /** + * get the result of and expression + * @param {Number} id + * @return {*} result + */ + Workspace.prototype.getResult = function (id) { + var node = this.nodes[id]; + if (!node) { + throw 'Node with id "' + id + '" not found'; + } + + return node.getResult(); + }; + + + /** + * Update the results of an expression and all dependent expressions + * @param {Number[]} ids Ids of the expressions to be updated + * @private + */ + Workspace.prototype._update = function (ids) { + this.updateSeq++; + var updateSeq = this.updateSeq; + var nodes = this.nodes; + + for (var i = 0, iMax = ids.length; i < iMax; i++) { + var id = ids[i]; + var node = nodes[id]; + if (node) { + node.eval(); + //console.log('eval node=' + id + ' result=' + node.result.toString()); // TODO: cleanup + node.updateSeq = updateSeq; + } + else { + // TODO: throw error? + } + } + }; + + /** + * Get all changes since an update sequence + * @param {Number} updateSeq. Optional. if not provided, all changes are + * since the creation of the workspace are returned + * @return {Object} ids Object containing two parameters: + * param {Number[]} ids Array containing + * the ids of the changed + * expressions + * param {Number} updateSeq the current update + * sequence + */ + Workspace.prototype.getChanges = function (updateSeq) { + var changedIds = []; + var node = this.firstNode; + updateSeq = updateSeq || 0; + while (node) { + if (node.updateSeq > updateSeq) { + changedIds.push(node.id); + } + node = node.nextNode; + } + return { + 'ids': changedIds, + 'updateSeq': this.updateSeq + }; + }; + + /** + * Return a new, unique id for an expression + * @return {Number} new id + * @private + */ + Workspace.prototype._getNewId = function () { + this.idMax++; + return this.idMax; + }; + + /** + * String representation of the Workspace + * @return {String} description + */ + Workspace.prototype.toString = function () { + return JSON.stringify(this.toJSON()); + }; + + /** + * JSON representation of the Workspace + * @return {Object} description + */ + Workspace.prototype.toJSON = function () { + var json = []; + + var node = this.firstNode; + while (node) { + var desc = { + 'id': node.id, + 'expression': node.expression, + 'dependencies': this.getDependencies(node.id) + }; + + try { + desc.result = node.getResult(); + } catch (err) { + desc.result = 'Error: ' + String(err.message || err); + } + + json.push(desc); + + node = node.nextNode; + } + + return json; + }; + +})(); /** * Calculate the square root of a value * @param {Number | Complex | Array | Matrix | Range} x @@ -6244,6 +8952,29 @@ math.clone = function clone(x) { throw newUnsupportedTypeError('clone', x); }; +/** + * Evaluate an expression. The expression will be evaluated using a read-only + * instance of a Parser (i.e. variable definitions are not supported). + * @param {String} expr + * @return {*} res + */ +math.eval = function eval(expr) { + if (arguments.length != 1) { + throw newArgumentsError('eval', arguments.length, 1); + } + + if (!isString(expr)) { + throw new TypeError('String expected'); + } + + return _readonlyParser.eval(expr); +}; + +/** @private */ +var _readonlyParser = new math.expr.Parser({ + readonly: true +}); + /** * Format a value of any type into a string. Interpolate values into the string. * Usage: @@ -6474,2686 +9205,6 @@ math['typeof'] = function math_typeof(x) { return type; }; -/** - * Node - */ -function Node() {} - -math.expr.node.Node = Node; - -/** - * Evaluate the node - * @return {*} result - */ -Node.prototype.eval = function () { - throw new Error('Cannot evaluate a Node interface'); -}; - -/** - * Get string representation - * @return {String} - */ -Node.prototype.toString = function() { - return ''; -}; - -/** - * @constructor Symbol - * A symbol can hold and evaluate a variable or function with parameters. - * @param {String} [name] - * @param {function} fn - * @param {Node[]} params - * @extends {Node} - */ -function Symbol(name, fn, params) { - this.name = name; - this.fn = fn; - this.params = params; -} - -Symbol.prototype = new Node(); - -math.expr.node.Symbol = Symbol; - -/** - * Check whether the Symbol has one or multiple parameters set. - * @return {Boolean} - */ -Symbol.prototype.hasParams = function () { - return (this.params != undefined && this.params.length > 0); -}; - -/** - * Evaluate the symbol - * @return {*} result - * @override - */ -Symbol.prototype.eval = function() { - var fn = this.fn; - if (fn === undefined) { - throw new Error('Undefined symbol ' + this.name); - } - - // evaluate the parameters - var results = this.params.map(function (param) { - return param.eval(); - }); - - // evaluate the function - return fn.apply(this, results); -}; - -/** - * Get string representation - * @return {String} str - * @override - */ -Symbol.prototype.toString = function() { - // variable. format the symbol like "myvar" - if (this.name && !this.params) { - return this.name; - } - - /* TODO: determine if the function is an operator - // operator. format the operation like "(2 + 3)" - if (this.fn && (this.fn instanceof math.fn.Operator)) { - if (this.params && this.params.length == 2) { - return '(' + - this.params[0].toString() + ' ' + - this.name + ' ' + - this.params[1].toString() + ')'; - } - } - */ - - // function. format the operation like "f(2, 4.2)" - var str = this.name; - if (this.params && this.params.length) { - str += '(' + this.params.join(', ') + ')'; - } - return str; -}; - -/** - * @constructor Constant - * @param {*} value - * @extends {Node} - */ -function Constant(value) { - this.value = value; -} - -Constant.prototype = new Node(); - -math.expr.node.Constant = Constant; - -/** - * Evaluate the constant - * @return {*} value - */ -Constant.prototype.eval = function () { - return this.value; -}; - -/** - * Get string representation - * @return {String} str - */ -Constant.prototype.toString = function() { - return this.value ? math.format(this.value) : ''; -}; - -/** - * @constructor MatrixNode - * Holds an n-dimensional array with nodes - * @param {Array} nodes - * @extends {Node} - */ -function MatrixNode(nodes) { - this.nodes = nodes || []; -} - -MatrixNode.prototype = new Node(); - -math.expr.node.MatrixNode = MatrixNode; - -(function () { - /** - * Evaluate the array - * @return {Matrix} results - * @override - */ - MatrixNode.prototype.eval = function() { - // recursively evaluate the nodes in the array, and merge the result - var array = evalArray(this.nodes); - if (containsMatrix(array)) { - array = merge(array); - } - return new Matrix(array); - }; - - /** - * Recursively evaluate an array with nodes - * @param {Array} array - * @returns {Array} results - */ - function evalArray(array) { - return array.map(function (child) { - if (child instanceof Array) { - // evaluate a nested array - return evalArray(child); - } - else { - // evaluate a node (end point) - return child.eval(); - } - }) - } - - /** - * Merge nested Matrices in an Array. - * @param {Array} array Two-dimensional array containing Matrices - * @return {Array} merged The merged array (two-dimensional) - */ - function merge (array) { - var merged = []; - var rows = array.length; - for (var r = 0; r < rows; r++) { - var row = array[r]; - var cols = row.length; - var submatrix = null; - var submatrixRows = null; - for (var c = 0; c < cols; c++) { - var entry = math.clone(row[c]); - var size; - if (entry instanceof Matrix) { - // get the data from the matrix - size = entry.size(); - entry = entry.valueOf(); - if (size.length == 1) { - entry = [entry]; - size = [1, size[0]]; - } - else if (size.length > 2) { - throw new Error('Cannot merge a multi dimensional matrix'); - } - } - else if (entry instanceof Range) { - // change range into an 1xn matrix - entry = [entry.valueOf()]; - size = [1, entry[0].length]; - } - else { - // change scalar into a 1x1 matrix - size = [1, 1]; - entry = [[entry]]; - } - - // check the height of this row - if (submatrix == null) { - // first entry - submatrix = entry; - submatrixRows = size[0]; - } - else if (size[0] == submatrixRows) { - // merge - for (var s = 0; s < submatrixRows; s++) { - submatrix[s] = submatrix[s].concat(entry[s]); - } - } - else { - // no good... - throw new Error('Dimension mismatch ' + - '(' + size[0] + ' != ' + submatrixRows + ')'); - } - } - - // merge the submatrix - merged = merged.concat(submatrix); - } - - return merged; - } - - /** - * Recursively test whether a multidimensional array contains at least one - * Matrix or Range. - * @param {Array} array - * @return {Boolean} containsMatrix - */ - function containsMatrix(array) { - return array.some(function (child) { - if (child instanceof Matrix || child instanceof Range) { - return true; - } - else if (child instanceof Array) { - return containsMatrix(child); - } - else { - return false; - } - }); - } - - /** - * Get string representation - * @return {String} str - * @override - */ - MatrixNode.prototype.toString = function() { - return util.formatArray(this.nodes); - }; -})(); -/** - * @constructor Block - * Holds a set with nodes - * @extends {Node} - */ -function Block() { - this.params = []; - this.visible = []; -} - -Block.prototype = new Node(); - -math.expr.node.Block = Block; - -/** - * Add a parameter - * @param {Node} param - * @param {Boolean} [visible] true by default - */ -Block.prototype.add = function (param, visible) { - var index = this.params.length; - this.params[index] = param; - this.visible[index] = (visible != undefined) ? visible : true; -}; - -/** - * Evaluate the set - * @return {*[]} results - * @override - */ -Block.prototype.eval = function() { - // evaluate the parameters - var results = []; - for (var i = 0, iMax = this.params.length; i < iMax; i++) { - var result = this.params[i].eval(); - if (this.visible[i]) { - results.push(result); - } - } - - return results; -}; - -/** - * Get string representation - * @return {String} str - * @override - */ -Block.prototype.toString = function() { - var strings = []; - - for (var i = 0, iMax = this.params.length; i < iMax; i++) { - if (this.visible[i]) { - strings.push('\n ' + this.params[i].toString()); - } - } - - return '[' + strings.join(',') + '\n]'; -}; - -/** - * @constructor Assignment - * @param {String} name Symbol name - * @param {Node[] | undefined} params Zero or more parameters - * @param {Node} expr The expression defining the symbol - * @param {function} result placeholder for the result - */ -function Assignment(name, params, expr, result) { - this.name = name; - this.params = params; - this.expr = expr; - this.result = result; -} - -Assignment.prototype = new Node(); - -math.expr.node.Assignment = Assignment; - -/** - * Evaluate the assignment - * @return {*} result - */ -Assignment.prototype.eval = function() { - if (this.expr === undefined) { - throw new Error('Undefined symbol ' + this.name); - } - - var result; - var params = this.params; - - if (params && params.length) { - // change part of a matrix, for example "a=[]", "a(2,3)=4.5" - var paramResults = []; - this.params.forEach(function (param) { - paramResults.push(param.eval()); - }); - - var exprResult = this.expr.eval(); - - // test if definition is currently undefined - if (this.result.value == undefined) { - throw new Error('Undefined symbol ' + this.name); - } - - var prevResult = this.result(); - // TODO: check type of prevResult: Matrix, Array, String, other... - if (!prevResult.set) { - throw new TypeError('Cannot apply a subset to object of type ' + - math.typeof(prevResult)); - - } - result = prevResult.set(paramResults, exprResult); - - this.result.value = result; - } - else { - // variable definition, for example "a = 3/4" - result = this.expr.eval(); - this.result.value = result; - } - - return result; -}; - -/** - * Get string representation - * @return {String} - */ -Assignment.prototype.toString = function() { - var str = ''; - - str += this.name; - if (this.params && this.params.length) { - str += '(' + this.params.join(', ') + ')'; - } - str += ' = '; - str += this.expr.toString(); - - return str; -}; - -/** - * @constructor Arguments - * invoke a list with parameters on the results of a node - * @param {Node} object - * @param {Node[]} params - */ -function Arguments (object, params) { - this.object = object; - this.params = params; -} - -Arguments.prototype = new Node(); - -math.expr.node.Arguments = Arguments; - -/** - * Evaluate the parameters - * @return {*} result - */ -Arguments.prototype.eval = function() { - var object = this.object; - if (object == undefined) { - throw new Error ('Node undefined'); - } - var objectRes = object.eval(); - - // evaluate the parameters - var params = this.params; - var paramsRes = []; - for (var i = 0, len = params.length; i < len; i++) { - paramsRes[i] = params[i].eval(); - } - - // TODO: check type of objectRes - if (!objectRes.get) { - throw new TypeError('Cannot apply arguments to object of type ' + - math.typeof(objectRes)); - } - return objectRes.get(paramsRes); -}; - -/** - * Get string representation - * @return {String} str - */ -Arguments.prototype.toString = function() { - // format the arguments like "(2, 4.2)" - var str = this.object ? this.object.toString() : ''; - if (this.params) { - str += '(' + this.params.join(', ') + ')'; - } - return str; -}; - -/** - * @constructor FunctionAssignment - * assigns a custom defined function - * - * @param {String} name Function name - * @param {String[]} variableNames Variable names - * @param {function[]} variables Links to the variables in a scope - * @param {Node} expr The function expression - * @param {function} result Link to store the result - */ -function FunctionAssignment(name, variableNames, variables, expr, result) { - this.name = name; - this.variables = variables; - - this.values = []; - for (var i = 0, iMax = this.variables.length; i < iMax; i++) { - this.values[i] = (function () { - var value = function () { - return value.value; - }; - value.value = undefined; - return value; - })(); - } - - this.def = this.createFunction(name, variableNames, variables, expr); - - this.result = result; -} - -FunctionAssignment.prototype = new Node(); - -math.expr.node.FunctionAssignment = FunctionAssignment; - -/** - * Create a function from the function assignment - * @param {String} name Function name - * @param {String[]} variableNames Variable names - * @param {function[]} values Zero or more functions - * @param {Node} expr The function expression - * - */ -FunctionAssignment.prototype.createFunction = function (name, variableNames, - values, expr) { - var fn = function () { - // validate correct number of arguments - var valuesNum = values ? values.length : 0; - var argumentsNum = arguments ? arguments.length : 0; - if (valuesNum != argumentsNum) { - throw newArgumentsError(name, argumentsNum, valuesNum); - } - - // fill in all parameter values - if (valuesNum > 0) { - for (var i = 0; i < valuesNum; i++){ - values[i].value = arguments[i]; - } - } - - // evaluate the expression - return expr.eval(); - }; - - fn.toString = function() { - return name + '(' + variableNames.join(', ') + ')'; - }; - - return fn; -}; - -/** - * Evaluate the function assignment - * @return {function} result - */ -FunctionAssignment.prototype.eval = function() { - // link the variables to the values of this function assignment - var variables = this.variables, - values = this.values; - for (var i = 0, iMax = variables.length; i < iMax; i++) { - variables[i].value = values[i]; - } - - // put the definition in the result - this.result.value = this.def; - - // TODO: what to return? a neat "function y(x) defined"? - return this.def; -}; - -/** - * get string representation - * @return {String} str - */ -FunctionAssignment.prototype.toString = function() { - return this.def.toString(); -}; - - -/** - * Scope - * A scope stores functions. - * - * @constructor mathnotepad.Scope - * @param {Scope} [parentScope] - */ -math.expr.Scope = function Scope(parentScope) { - this.parentScope = parentScope; - this.nestedScopes = undefined; - - this.symbols = {}; // the actual symbols - - // the following objects are just used to test existence. - this.defs = {}; // definitions by name (for example "a = [1, 2; 3, 4]") - this.updates = {}; // updates by name (for example "a(2, 1) = 5.2") - this.links = {}; // links by name (for example "2 * a") -}; - -// TODO: rethink the whole scoping solution again. Try to simplify - -math.expr.Scope.prototype = { - /** - * Create a nested scope - * The variables in a nested scope are not accessible from the parent scope - * @return {math.expr.Scope} nestedScope - */ - createNestedScope: function () { - var nestedScope = new math.expr.Scope(this); - if (!this.nestedScopes) { - this.nestedScopes = []; - } - this.nestedScopes.push(nestedScope); - return nestedScope; - }, - - /** - * Clear all symbols in this scope and its nested scopes - * (parent scope will not be cleared) - */ - clear: function () { - this.symbols = {}; - this.defs = {}; - this.links = {}; - this.updates = {}; - - if (this.nestedScopes) { - var nestedScopes = this.nestedScopes; - for (var i = 0, iMax = nestedScopes.length; i < iMax; i++) { - nestedScopes[i].clear(); - } - } - }, - - /** - * create a symbol - * @param {String} name - * @return {function} symbol - * @private - */ - createSymbol: function (name) { - var symbol = this.symbols[name]; - if (!symbol) { - // get a link to the last definition - var lastDef = this.findDef(name); - - // create a new symbol - symbol = this.newSymbol(name, lastDef); - this.symbols[name] = symbol; - - } - return symbol; - }, - - /** - * Create a new symbol - * @param {String} name - * @param {*} [value] - * @return {function} symbol - * @private - */ - newSymbol: function (name, value) { - // create a new symbol - var scope = this; - var symbol = function () { - var args, i; - if (!symbol.value) { - // try to resolve again - symbol.value = scope.findDef(name); - - if (!symbol.value) { - throw new Error('Undefined symbol ' + name); - } - } - if (typeof symbol.value === 'function') { - return symbol.value.apply(null, arguments); - } - else if (symbol.value instanceof Matrix || symbol.value instanceof Range || symbol.value instanceof Array) { - if (arguments.length) { - var matrix = (symbol.value instanceof Array) ? new Matrix(symbol.value) : symbol.value; - args = []; - for (i = 0; i < arguments.length; i++) { - args[i] = arguments[i]; - } - return matrix.get(args); - } - else { - return symbol.value; - } - } - // TODO: implement get subset for all types - else { - return symbol.value; - } - }; - - symbol.value = value; - - symbol.toString = function () { - return symbol.value ? symbol.value.toString() : ''; - }; - - return symbol; - }, - - /** - * create a link to a value. - * @param {String} name - * @return {function} symbol - */ - createLink: function (name) { - var symbol = this.links[name]; - if (!symbol) { - symbol = this.createSymbol(name); - this.links[name] = symbol; - } - return symbol; - }, - - /** - * Create a variable definition - * Returns the created symbol - * @param {String} name - * @param {*} [value] - * @return {function} symbol - */ - createDef: function (name, value) { - var symbol = this.defs[name]; - if (!symbol) { - symbol = this.createSymbol(name); - this.defs[name] = symbol; - } - if (symbol && value != undefined) { - symbol.value = value; - } - return symbol; - }, - - /** - * Create a variable update definition - * Returns the created symbol - * @param {String} name - * @return {function} symbol - */ - createUpdate: function (name) { - var symbol = this.updates[name]; - if (!symbol) { - symbol = this.createLink(name); - this.updates[name] = symbol; - } - return symbol; - }, - - /** - * Create a constant - * @param {String} name - * @param {*} value - * @return {function} symbol - * @private - */ - createConstant: function (name, value) { - var symbol = this.newSymbol(name, value); - this.symbols[name] = symbol; - this.defs[name] = symbol; - return symbol; - }, - - /** - * get the link to a symbol definition or update. - * If the symbol is not found in this scope, it will be looked up in its parent - * scope. - * @param {String} name - * @return {function | undefined} symbol, or undefined when not found - */ - findDef: function (name) { - var symbol; - - // check scope - symbol = this.defs[name]; - if (symbol) { - return symbol; - } - symbol = this.updates[name]; - if (symbol) { - return symbol; - } - - // check parent scope - if (this.parentScope) { - return this.parentScope.findDef(name); - } - else { - // this is the root scope (has no parent), - // try to load constants, functions, or unit from the library - - // check function (and load the function), for example "sin" or "sqrt" - // search in the mathnotepad.math namespace for this symbol - var fn = math[name]; - if (fn) { - return this.createConstant(name, fn); - } - - // Check if token is a unit - if (Unit.isPlainUnit(name)) { - var unit = new Unit(null, name); - return this.createConstant(name, unit); - } - } - - return undefined; - }, - - /** - * Remove a link to a symbol - * @param {String} name - */ - removeLink: function (name) { - delete this.links[name]; - }, - - /** - * Remove a definition of a symbol - * @param {String} name - */ - removeDef: function (name) { - delete this.defs[name]; - }, - - /** - * Remove an update definition of a symbol - * @param {String} name - */ - removeUpdate: function (name) { - delete this.updates[name]; - }, - - /** - * initialize the scope and its nested scopes - * - * All functions are linked to their previous definition - * If there is no parentScope, or no definition of the func in the parent scope, - * the link will be set undefined - */ - init: function () { - var symbols = this.symbols; - var parentScope = this.parentScope; - - for (var name in symbols) { - if (symbols.hasOwnProperty(name)) { - var symbol = symbols[name]; - symbol.value = (parentScope ? parentScope.findDef(name) : undefined); - } - } - - if (this.nestedScopes) { - this.nestedScopes.forEach(function (nestedScope) { - nestedScope.init(); - }); - } - }, - - /** - * Check whether this scope or any of its nested scopes contain a link to a - * symbol with given name - * @param {String} name - * @return {boolean} hasLink True if a link with given name is found - */ - hasLink: function (name) { - if (this.links[name]) { - return true; - } - - if (this.nestedScopes) { - var nestedScopes = this.nestedScopes; - for (var i = 0, iMax = nestedScopes.length; i < iMax; i++) { - if (nestedScopes[i].hasLink(name)) { - return true; - } - } - } - - return false; - }, - - /** - * Check whether this scope contains a definition of a symbol with given name - * @param {String} name - * @return {boolean} hasDef True if a definition with given name is found - */ - hasDef: function (name) { - return (this.defs[name] != undefined); - }, - - /** - * Check whether this scope contains an update definition of a symbol with - * given name - * @param {String} name - * @return {boolean} hasUpdate True if an update definition with given name is found - */ - hasUpdate: function (name) { - return (this.updates[name] != undefined); - }, - - /** - * Retrieve all undefined symbols - * @return {function[]} undefinedSymbols All symbols which are undefined - */ - getUndefinedSymbols: function () { - var symbols = this.symbols; - var undefinedSymbols = []; - for (var i in symbols) { - if (symbols.hasOwnProperty(i)) { - var symbol = symbols[i]; - if (symbol.value == undefined) { - undefinedSymbols.push(symbol); - } - } - } - - if (this.nestedScopes) { - this.nestedScopes.forEach(function (nestedScope) { - undefinedSymbols = - undefinedSymbols.concat(nestedScope.getUndefinedSymbols()); - }); - } - - return undefinedSymbols; - } -}; - -(function () { - /** - * @constructor math.expr.Parser - * Parser parses math expressions and evaluates them or returns a node tree. - * - * Methods: - * var result = parser.eval(expr); // evaluate an expression - * var value = parser.get(name); // retrieve a variable from the parser - * parser.set(name, value); // set a variable in the parser - * - * // it is possible to parse an expression into a node tree: - * var node = parser.parse(expr); // parse an expression into a node tree - * var result = node.eval(); // evaluate a parsed node - * - * Example usage: - * var parser = new math.expr.Parser(); - * // Note: there is a convenience method which can be used instead: - * // var parser = new math.parser(); - * - * // evaluate expressions - * var a = parser.eval('sqrt(3^2 + 4^2)'); // 5 - * var b = parser.eval('sqrt(-4)'); // 2i - * var c = parser.eval('2 inch in cm'); // 5.08 cm - * var d = 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('function 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'); // 7 - * var f = parser.get('f'); // function - * var g = f(3, 2); // 9 - * parser.set('h', 500); - * var i = 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(); - */ - math.expr.Parser = function Parser() { - if (this.constructor != Parser) { - throw new SyntaxError( - 'Parser constructor must be called with the new operator'); - } - - this.scope = new math.expr.Scope(); - }; - - /** - * Parse an expression end return the parsed function node. - * The node can be evaluated via node.eval() - * @param {String} expression - * @param {Scope} [scope] - * @return {Node} node - * @throws {Error} - */ - math.expr.Parser.prototype.parse = function (expression, scope) { - expr = expression || ''; - - if (!scope) { - scope = this.scope; - } - - return parse_start(scope); - }; - - /** - * Parse and evaluate the given expression - * @param {String} expression A string containing an expression, for example "2+3" - * @return {*} result The result, or undefined when the expression was - * empty - * @throws {Error} - */ - math.expr.Parser.prototype.eval = function (expression) { - var node = this.parse(expression); - return node.eval(); - }; - - /** - * Get a variable (a function or variable) by name from the parsers scope. - * Returns undefined when not found - * @param {String} name - * @return {* | undefined} value - */ - math.expr.Parser.prototype.get = function (name) { - var symbol = this.scope.findDef(name); - if (symbol) { - return symbol.value; - } - return undefined; - }; - - /** - * Set a symbol (a function or variable) by name from the parsers scope. - * @param {String} name - * @param {* | undefined} value - */ - math.expr.Parser.prototype.set = function (name, value) { - this.scope.createDef(name, value); - }; - - /** - * Clear the scope with variables and functions - */ - math.expr.Parser.prototype.clear = function () { - this.scope.clear(); - }; - - // token types enumeration - var TOKENTYPE = { - NULL : 0, - DELIMITER : 1, - NUMBER : 2, - SYMBOL : 3, - UNKNOWN : 4 - }; - - var expr = ''; // current expression - var index = 0; // current index in expr - var c = ''; // current token character in expr - var token = ''; // current token - var token_type = TOKENTYPE.NULL; // type of the token - // TODO: do not use this.token, but a local variable var token for better speed? -> getToken() must return token. - - /** - * Get the next character from the expression. - * The character is stored into the char t. - * If the end of the expression is reached, the function puts an empty - * string in t. - * @private - */ - function getChar() { - index++; - c = expr.charAt(index); - } - - /** - * Get the first character from the expression. - * The character is stored into the char t. - * If the end of the expression is reached, the function puts an empty - * string in t. - * @private - */ - function getFirstChar() { - index = 0; - c = expr.charAt(0); - } - - /** - * Get next token in the current string expr. - * Uses the Parser data expr, e, token, t, token_type and err - * The token and token type are available at token_type and token - * @private - */ - function getToken() { - token_type = TOKENTYPE.NULL; - token = ''; - - // skip over whitespaces - while (c == ' ' || c == '\t') { // space or tab - getChar(); - } - - // skip comment - if (c == '#') { - while (c != '\n' && c != '') { - getChar(); - } - } - - // check for end of expression - if (c == '') { - // token is still empty - token_type = TOKENTYPE.DELIMITER; - return; - } - - // check for minus, comma, parentheses, quotes, newline, semicolon - if (c == '-' || c == ',' || - c == '(' || c == ')' || - c == '[' || c == ']' || - c == '\"' || c == '\n' || - c == ';' || c == ':' || - c == '!' || c == '\'') { - token_type = TOKENTYPE.DELIMITER; - token += c; - getChar(); - return; - } - - // check for operators (delimiters) - if (isDelimiter(c)) { - token_type = TOKENTYPE.DELIMITER; - while (isDelimiter(c)) { - token += c; - getChar(); - } - return; - } - - // check for a number - if (isDigitDot(c)) { - token_type = TOKENTYPE.NUMBER; - while (isDigitDot(c)) { - token += c; - getChar(); - } - - // check for scientific notation like "2.3e-4" or "1.23e50" - if (c == 'E' || c == 'e') { - token += c; - getChar(); - - if (c == '+' || c == '-') { - token += c; - getChar(); - } - - // Scientific notation MUST be followed by an exponent - if (!isDigit(c)) { - // this is no legal number, exponent is missing. - token_type = TOKENTYPE.UNKNOWN; - } - - while (isDigit(c)) { - token += c; - getChar(); - } - } - return; - } - - // check for variables or functions - if (isAlpha(c)) { - token_type = TOKENTYPE.SYMBOL; - - while (isAlpha(c) || isDigit(c)) - { - token += c; - getChar(); - } - return; - } - - // something unknown is found, wrong characters -> a syntax error - token_type = TOKENTYPE.UNKNOWN; - while (c != '') { - token += c; - getChar(); - } - throw createSyntaxError('Syntax error in part "' + token + '"'); - } - - /** - * checks if the given char c is a delimiter - * minus is not checked in this method (can be unary minus) - * @param {String} c a string with one character - * @return {Boolean} - * @private - */ - function isDelimiter (c) { - return c == '&' || - c == '|' || - c == '<' || - c == '>' || - c == '=' || - c == '+' || - c == '/' || - c == '*' || - c == '%' || - c == '^' || - c == ',' || - c == ';' || - c == '\n' || - c == '!' || - c == '\''; - } - - /** - * Check if a given name is valid - * if not, an error is thrown - * @param {String} name - * @return {boolean} valid - * @private - */ - function isValidSymbolName (name) { - for (var i = 0, iMax = name.length; i < iMax; i++) { - var c = name.charAt(i); - //var valid = (isAlpha(c) || (i > 0 && isDigit(c))); // TODO - var valid = (isAlpha(c)); - if (!valid) { - return false; - } - } - - return true; - } - - /** - * checks if the given char c is a letter (upper or lower case) - * or underscore - * @param {String} c a string with one character - * @return {Boolean} - * @private - */ - function isAlpha (c) { - return ((c >= 'a' && c <= 'z') || - (c >= 'A' && c <= 'Z') || - c == '_'); - } - - /** - * checks if the given char c is a digit or dot - * @param {String} c a string with one character - * @return {Boolean} - * @private - */ - function isDigitDot (c) { - return ((c >= '0' && c <= '9') || - c == '.'); - } - - /** - * checks if the given char c is a digit - * @param {String} c a string with one character - * @return {Boolean} - * @private - */ - function isDigit (c) { - return ((c >= '0' && c <= '9')); - } - - /** - * Start of the parse levels below, in order of precedence - * @param {Scope} scope - * @return {Node} node - * @private - */ - function parse_start (scope) { - // get the first character in expression - getFirstChar(); - - getToken(); - - var node; - if (token == '') { - // empty expression - node = new Constant(undefined); - } - else { - node = parse_block(scope); - } - - // check for garbage at the end of the expression - // an expression ends with a empty character '' and token_type DELIMITER - if (token != '') { - if (token_type == TOKENTYPE.DELIMITER) { - // user entered a not existing operator like "//" - - // TODO: give hints for aliases, for example with "<>" give as hint " did you mean != ?" - throw createError('Unknown operator ' + token); - } - else { - throw createSyntaxError('Unexpected part "' + token + '"'); - } - } - - return node; - } - - /** - * Parse a block with expressions. Expressions can be separated by a newline - * character '\n', or by a semicolon ';'. In case of a semicolon, no output - * of the preceding line is returned. - * @param {Scope} scope - * @return {Node} node - * @private - */ - function parse_block (scope) { - var node, block, visible; - - if (token != '\n' && token != ';' && token != '') { - node = parse_ans(scope); - } - - while (token == '\n' || token == ';') { - if (!block) { - // initialize the block - block = new Block(); - if (node) { - visible = (token != ';'); - block.add(node, visible); - } - } - - getToken(); - if (token != '\n' && token != ';' && token != '') { - node = parse_ans(scope); - - visible = (token != ';'); - block.add(node, visible); - } - } - - if (block) { - return block; - } - - if (!node) { - node = parse_ans(scope); - } - - return node; - } - - /** - * Parse assignment of ans. - * Ans is assigned when the expression itself is no variable or function - * assignment - * @param {Scope} scope - * @return {Node} node - * @private - */ - function parse_ans (scope) { - var expression = parse_function_assignment(scope); - - // TODO: not so nice having to specify some special types here... - if (!(expression instanceof Assignment) - // !(expression instanceof FunctionAssignment) && // TODO - // !(expression instanceof plot) // TODO - ) { - // create a variable definition for ans - var name = 'ans'; - var params = undefined; - var link = scope.createDef(name); - return new Assignment(name, params, expression, link); - } - - return expression; - } - - /** - * Parse a function assignment like "function f(a,b) = a*b" - * @param {Scope} scope - * @return {Node} node - * @private - */ - function parse_function_assignment (scope) { - // TODO: keyword 'function' must become a reserved keyword - if (token_type == TOKENTYPE.SYMBOL && token == 'function') { - // get function name - getToken(); - if (token_type != TOKENTYPE.SYMBOL) { - throw createSyntaxError('Function name expected'); - } - var name = token; - - // get parenthesis open - getToken(); - if (token != '(') { - throw createSyntaxError('Opening parenthesis ( expected'); - } - - // get function variables - var functionScope = scope.createNestedScope(); - var variableNames = []; - var variables = []; - while (true) { - getToken(); - if (token_type == TOKENTYPE.SYMBOL) { - // store parameter - var variableName = token; - var variable = functionScope.createDef(variableName); - variableNames.push(variableName); - variables.push(variable); - } - else { - throw createSyntaxError('Variable name expected'); - } - - getToken(); - if (token == ',') { - // ok, nothing to do, read next variable - } - else if (token == ')') { - // end of variable list encountered. break loop - break; - } - else { - throw createSyntaxError('Comma , or closing parenthesis ) expected"'); - } - } - - getToken(); - if (token != '=') { - throw createSyntaxError('Equal sign = expected'); - } - - // parse the expression, with the correct function scope - getToken(); - var expression = parse_range(functionScope); - var result = scope.createDef(name); - - return new FunctionAssignment(name, variableNames, variables, - expression, result); - } - - return parse_assignment(scope); - } - - /** - * Assignment of a variable, can be a variable like "a=2.3" or a updating an - * existing variable like "matrix(2,3:5)=[6,7,8]" - * @param {Scope} scope - * @return {Node} node - * @private - */ - function parse_assignment (scope) { - var linkExisted = false; - if (token_type == TOKENTYPE.SYMBOL) { - linkExisted = scope.hasLink(token); - } - - var node = parse_range(scope); - - // TODO: support chained assignments like "a = b = 2.3" - if (token == '=') { - if (!(node instanceof Symbol)) { - throw createSyntaxError('Symbol expected at the left hand side ' + - 'of assignment operator ='); - } - var name = node.name; - var params = node.params; - - if (!linkExisted) { - // we parsed the assignment as if it where an expression instead, - // therefore, a link was created to the symbol. This link must - // be cleaned up again, and only if it wasn't existing before - scope.removeLink(name); - } - - // parse the expression, with the correct function scope - getToken(); - var expression = parse_range(scope); - var link = node.hasParams() ? scope.createUpdate(name) : scope.createDef(name); - return new Assignment(name, params, expression, link); - } - - return node; - } - - /** - * parse range, "start:end" or "start:step:end" - * @param {Scope} scope - * @return {Node} node - * @private - */ - function parse_range (scope) { - var node = parse_conditions(scope); - - if (token == ':') { - var params = [node]; - - while (token == ':') { - getToken(); - params.push(parse_conditions(scope)); - } - - if (params.length > 3) { - throw new TypeError('Invalid range'); - } - - var name = 'range'; - var fn = math.range; - node = new Symbol(name, fn, params); - } - - return node; - } - - /** - * conditions like and, or, in - * @param {Scope} scope - * @return {Node} node - * @private - */ - function parse_conditions (scope) { - var node = parse_bitwise_conditions(scope); - - // TODO: precedence of And above Or? - // TODO: implement a method for unit to number conversion - var operators = { - 'in' : 'in' - /* TODO: implement conditions - 'and' : 'and', - '&&' : 'and', - 'or': 'or', - '||': 'or', - 'xor': 'xor' - */ - }; - while (operators[token] !== undefined) { - // TODO: with all operators: only load one instance of the operator, use the scope - var name = token; - var fn = math[operators[name]]; - - getToken(); - var params = [node, parse_bitwise_conditions(scope)]; - node = new Symbol(name, fn, params); - } - - return node; - } - - /** - * conditional operators and bitshift - * @param {Scope} scope - * @return {Node} node - * @private - */ - function parse_bitwise_conditions (scope) { - var node = parse_comparison(scope); - - /* TODO: implement bitwise conditions - var operators = { - '&' : 'bitwiseand', - '|' : 'bitwiseor', - // todo: bitwise xor? - '<<': 'bitshiftleft', - '>>': 'bitshiftright' - }; - while (operators[token] !== undefined) { - var name = token; - var fn = math[operators[name]]; - - getToken(); - var params = [node, parse_comparison()]; - node = new Symbol(name, fn, params); - } - */ - - return node; - } - - /** - * comparison operators - * @param {Scope} scope - * @return {Node} node - * @private - */ - function parse_comparison (scope) { - var node = parse_addsubtract(scope); - - var operators = { - '==': 'equal', - '!=': 'unequal', - '<': 'smaller', - '>': 'larger', - '<=': 'smallereq', - '>=': 'largereq' - }; - while (operators[token] !== undefined) { - var name = token; - var fn = math[operators[name]]; - - getToken(); - var params = [node, parse_addsubtract(scope)]; - node = new Symbol(name, fn, params); - } - - return node; - } - - /** - * add or subtract - * @param {Scope} scope - * @return {Node} node - * @private - */ - function parse_addsubtract (scope) { - var node = parse_multiplydivide(scope); - - var operators = { - '+': 'add', - '-': 'subtract' - }; - while (operators[token] !== undefined) { - var name = token; - var fn = math[operators[name]]; - - getToken(); - var params = [node, parse_multiplydivide(scope)]; - node = new Symbol(name, fn, params); - } - - return node; - } - - /** - * multiply, divide, modulus - * @param {Scope} scope - * @return {Node} node - * @private - */ - function parse_multiplydivide (scope) { - var node = parse_unaryminus(scope); - - var operators = { - '*': 'multiply', - '/': 'divide', - '%': 'mod', - 'mod': 'mod' - }; - while (operators[token] !== undefined) { - var name = token; - var fn = math[operators[name]]; - - getToken(); - var params = [node, parse_unaryminus(scope)]; - node = new Symbol(name, fn, params); - } - - return node; - } - - /** - * Unary minus - * @param {Scope} scope - * @return {Node} node - * @private - */ - function parse_unaryminus (scope) { - if (token == '-') { - var name = token; - var fn = math.unaryminus; - getToken(); - var params = [parse_pow(scope)]; - - return new Symbol(name, fn, params); - } - - return parse_pow(scope); - } - - /** - * power - * Node: power operator is right associative - * @param {Scope} scope - * @return {Node} node - * @private - */ - function parse_pow (scope) { - var nodes = [ - parse_factorial(scope) - ]; - - // stack all operands of a chained power operator (like '2^3^3') - while (token == '^') { - getToken(); - nodes.push(parse_factorial(scope)); - } - - // evaluate the operands from right to left (right associative) - var node = nodes.pop(); - while (nodes.length) { - var leftNode = nodes.pop(); - var name = '^'; - var fn = math.pow; - var params = [leftNode, node]; - node = new Symbol(name, fn, params); - } - - return node; - } - - /** - * Factorial - * @param {Scope} scope - * @return {Node} node - * @private - */ - function parse_factorial (scope) { - var node = parse_transpose(scope); - - while (token == '!') { - var name = token; - var fn = math.factorial; - getToken(); - var params = [node]; - - node = new Symbol(name, fn, params); - } - - return node; - } - - /** - * Transpose - * @param {Scope} scope - * @return {Node} node - * @private - */ - function parse_transpose (scope) { - var node = parse_plot(scope); - - while (token == '\'') { - var name = token; - var fn = math.transpose; - getToken(); - var params = [node]; - - node = new Symbol(name, fn, params); - } - - return node; - } - - /** - * parse plot - * @param {Scope} scope - * @return {Node} node - * @private - */ - function parse_plot (scope) { - /* TODO: implement plot - if (token_type == TOKENTYPE.SYMBOL && - token == 'plot') { - getToken(); - - // parse the parentheses and parameters of the plot - // the parameters are something like: plot(sin(x), cos(x), x) - var functions = []; - if (token == '(') { - var plotScope = scope.createNestedScope(); - - getToken(); - functions.push(parse_range(plotScope)); - - // parse a list with parameters - while (token == ',') { - getToken(); - functions.push(parse_range(plotScope)); - } - - if (token != ')') { - throw createSyntaxError('Parenthesis ) missing'); - } - getToken(); - } - - // check what the variable of the functions is. - var variable = undefined; - var lastFunction = functions[functions.length - 1]; - if (lastFunction) { - // if the last function is a variable, remove it from the functions list - // and use its variable func - var lastIsSymbol = (lastFunction instanceof Symbol && - !lastFunction.hasParams()); - if (lastIsSymbol) { - functions.pop(); - variable = lastFunction.fn; - } - } - return new plot(functions, variable, plotScope); - } - */ - - return parse_symbol(scope); - } - - /** - * parse symbols: functions, variables, constants, units - * @param {Scope} scope - * @return {Node} node - * @private - */ - function parse_symbol (scope) { - if (token_type == TOKENTYPE.SYMBOL) { - var name = token; - - getToken(); - - var link = scope.createLink(name); - // TODO: split applying arguments from symbol? - var args = parse_arguments(scope); - var symbol = new Symbol(name, link, args); - - /* TODO: parse arguments - // parse arguments - while (token == '(') { - symbol = parse_arguments(scope, symbol); - } - */ - return symbol; - } - - return parse_string(scope); - } - - /** - * parse arguments, enclosed in parenthesis - * @param {Scope} scope - * @return {Node[]} arguments - * @private - */ - function parse_arguments (scope) { - var args = []; - if (token == '(') { - // TODO: in case of Plot, create a new scope. - - getToken(); - - if (token != ')') { - args.push(parse_range(scope)); - - // parse a list with parameters - while (token == ',') { - getToken(); - args.push(parse_range(scope)); - } - } - - if (token != ')') { - throw createSyntaxError('Parenthesis ) missing'); - } - getToken(); - } - - return args; - } - - /** - * parse a string. - * A string is enclosed by double quotes - * @param {Scope} scope - * @return {Node} node - * @private - */ - function parse_string (scope) { - if (token == '"') { - // string "..." - var str = ''; - var tPrev = ''; - while (c != '' && (c != '\"' || tPrev == '\\')) { // also handle escape character - str += c; - tPrev = c; - getChar(); - } - - getToken(); - if (token != '"') { - throw createSyntaxError('End of string " missing'); - } - getToken(); - - var node = new Constant(str); - - /* TODO: parse arguments - // parse arguments - while (token == '(') { - node = parse_arguments(scope, node); - } - */ - - return node; - } - - return parse_matrix(scope); - } - - /** - * parse the matrix - * @param {Scope} scope - * @return {Node} A MatrixNode - * @private - */ - function parse_matrix (scope) { - if (token == '[') { - // matrix [...] - var array; - - // skip newlines - getToken(); - while (token == '\n') { - getToken(); - } - - // check if this is an empty matrix "[ ]" - if (token != ']') { - // this is a non-empty matrix - var params = []; - var r = 0, c = 0; - - params[0] = [parse_range(scope)]; - - // the columns in the matrix are separated by commas, and the rows by dot-comma's - while (token == ',' || token == ';') { - if (token == ',') { - c++; - } - else { - r++; - c = 0; - params[r] = []; - } - - // skip newlines - getToken(); - while (token == '\n') { - getToken(); - } - - params[r][c] = parse_range(scope); - - // skip newlines - while (token == '\n') { - getToken(); - } - } - - var rows = params.length; - var cols = (params.length > 0) ? params[0].length : 0; - - // check if the number of columns matches in all rows - for (r = 1; r < rows; r++) { - if (params[r].length != cols) { - throw createError('Number of columns must match ' + - '(' + params[r].length + ' != ' + cols + ')'); - } - } - - if (token != ']') { - throw createSyntaxError('End of matrix ] missing'); - } - - getToken(); - array = new MatrixNode(params); - } - else { - // this is an empty matrix "[ ]" - getToken(); - array = new MatrixNode([[]]); - } - - /* TODO: parse arguments - // parse arguments - while (token == '(') { - array = parse_arguments(scope, array); - } - */ - - return array; - } - - return parse_number(scope); - } - - /** - * parse a number - * @param {Scope} scope - * @return {Node} node - * @private - */ - function parse_number (scope) { - if (token_type == TOKENTYPE.NUMBER) { - // this is a number - var number; - if (token == '.') { - number = 0.0; - } else { - number = Number(token); - } - getToken(); - - /* TODO: implicit multiplication? - // TODO: how to calculate a=3; 2/2a ? is this (2/2)*a or 2/(2*a) ? - // check for implicit multiplication - if (token_type == TOKENTYPE.VARIABLE) { - node = multiply(node, parse_pow()); - } - //*/ - - var value; - if (token_type == TOKENTYPE.SYMBOL) { - if (token == 'i' || token == 'I') { - value = new Complex(0, number); - getToken(); - return new Constant(value); - } - - if (Unit.isPlainUnit(token)) { - value = new Unit(number, token); - getToken(); - return new Constant(value); - } - - throw createTypeError('Unknown unit "' + token + '"'); - } - - // just a regular number - var node = new Constant(number); - - /* TODO: parse arguments - // parse arguments - while (token == '(') { - node = parse_arguments(scope, node); - } - */ - - return node; - } - - return parse_parentheses(scope); - } - - /** - * parentheses - * @param {Scope} scope - * @return {Node} node - * @private - */ - function parse_parentheses (scope) { - // check if it is a parenthesized expression - if (token == '(') { - // parentheses (...) - getToken(); - var node = parse_range(scope); // start again - - if (token != ')') { - throw createSyntaxError('Parenthesis ) expected'); - } - getToken(); - - /* TODO: implicit multiplication? - // TODO: how to calculate a=3; 2/2a ? is this (2/2)*a or 2/(2*a) ? - // check for implicit multiplication - if (token_type == TOKENTYPE.VARIABLE) { - node = multiply(node, parse_pow()); - } - //*/ - - /* TODO: parse arguments - // parse arguments - while (token == '(') { - node = parse_arguments(scope, node); - } - */ - - return node; - } - - return parse_end(scope); - } - - /** - * Evaluated when the expression is not yet ended but expected to end - * @param {Scope} scope - * @return {Node} res - * @private - */ - function parse_end (scope) { - if (token == '') { - // syntax error or unexpected end of expression - throw createSyntaxError('Unexpected end of expression'); - } else { - throw createSyntaxError('Value expected'); - } - } - - /** - * Shortcut for getting the current row value (one based) - * Returns the line of the currently handled expression - * @private - */ - function row () { - // TODO: also register row number during parsing - return undefined; - } - - /** - * Shortcut for getting the current col value (one based) - * Returns the column (position) where the last token starts - * @private - */ - function col () { - return index - token.length + 1; - } - - /** - * Build up an error message - * @param {String} message - * @return {String} message with row and column information - * @private - */ - function createErrorMessage (message) { - var r = row(); - var c = col(); - if (r === undefined) { - if (c === undefined) { - return message; - } else { - return message + ' (char ' + c + ')'; - } - } else { - return message + ' (line ' + r + ', char ' + c + ')'; - } - } - - /** - * Create an error - * @param {String} message - * @return {SyntaxError} instantiated error - * @private - */ - function createSyntaxError (message) { - return new SyntaxError(createErrorMessage(message)); - } - - /** - * Create an error - * @param {String} message - * @return {TypeError} instantiated error - * @private - */ - function createTypeError(message) { - return new TypeError(createErrorMessage(message)); - } - - /** - * Create an error - * @param {String} message - * @return {Error} instantiated error - * @private - */ - function createError (message) { - return new Error(createErrorMessage(message)); - } - -})(); - -(function () { - /** - * @constructor math.expr.Workspace - * - * Workspace manages a set of expressions. Expressions can be added, replace, - * deleted, and inserted in the workspace. The workspace keeps track on the - * dependencies between the expressions, and automatically updates results of - * depending expressions when variables or function definitions are changed in - * the workspace. - * - * Methods: - * var id = workspace.append(expr); - * var id = workspace.insertBefore(expr, beforeId); - * var id = workspace.insertAfter(expr, afterId); - * workspace.replace(expr, id); - * workspace.remove(id); - * workspace.clear(); - * var expr = workspace.getExpr(id); - * var result = workspace.getResult(id); - * var deps = workspace.getDependencies(id); - * var changes = workspace.getChanges(updateSeq); - * - * Usage: - * var workspace = new math.expr.Workspace(); - * var id0 = workspace.append('a = 3/4'); - * var id1 = workspace.append('a + 2'); - * console.log('a + 2 = ' + workspace.getResult(id1)); - * workspace.replace('a=5/2', id0); - * console.log('a + 2 = ' + workspace.getResult(id1)); - */ - function Workspace () { - this.idMax = -1; - this.updateSeq = 0; - this.parser = new math.expr.Parser(); - this.scope = new math.expr.Scope(); - - this.nodes = {}; - this.firstNode = undefined; - this.lastNode = undefined; - } - - math.expr.Workspace = Workspace; - - /** - * clear the workspace - */ - Workspace.prototype.clear = function () { - this.nodes = {}; - this.firstNode = undefined; - this.lastNode = undefined; - }; - - /** - * append an expression to the workspace - * @param {String} expression - * @return {Number} id of the created node - */ - Workspace.prototype.append = function (expression) { - // create the node - var id = this._getNewId(); - var parentScope = this.lastNode ? this.lastNode.scope : this.scope; - var scope = new math.expr.Scope(parentScope); - var node = new Workspace.Node({ - 'id': id, - 'expression': expression, - 'parser': this.parser, - 'scope': scope, - 'nextNode': undefined, - 'previousNode': this.lastNode - }); - this.nodes[id] = node; - - // link next and previous nodes - if (!this.firstNode) { - this.firstNode = node; - } - if (this.lastNode) { - this.lastNode.nextNode = node; - } - this.lastNode = node; - - // update this node - this._update([id]); - - return id; - }; - - /** - * insert an expression before an existing expression - * @param {String} expression the new expression - * @param {Number} beforeId id of an existing expression - * @return {Number} id id of the created node - */ - Workspace.prototype.insertBefore = function (expression, beforeId) { - var nextNode = this.nodes[beforeId]; - if (!nextNode) { - throw 'Node with id "' + beforeId + '" not found'; - } - - var previousNode = nextNode.previousNode; - - // create the node - var id = this._getNewId(); - var previousScope = previousNode ? previousNode.scope : this.scope; - var scope = new math.expr.Scope(previousScope); - var node = new Workspace.Node({ - 'id': id, - 'expression': expression, - 'parser': this.parser, - 'scope': scope, - 'nextNode': nextNode, - 'previousNode': previousNode - }); - this.nodes[id] = node; - - // link next and previous nodes - if (previousNode) { - previousNode.nextNode = node; - } - else { - this.firstNode = node; - } - nextNode.previousNode = node; - - // link to the new the scope - nextNode.scope.parentScope = node.scope; - - // update this node and all dependent nodes - var ids = this.getDependencies(id); - if (ids.indexOf(id) == -1) { - ids.unshift(id); - } - this._update(ids); - - return id; - }; - - /** - * insert an expression after an existing expression - * @param {String} expression the new expression - * @param {Number} afterId id of an existing expression - * @return {Number} id id of the created expression - */ - Workspace.prototype.insertAfter = function (expression, afterId) { - var previousNode = this.nodes[afterId]; - if (!previousNode) { - throw 'Node with id "' + afterId + '" not found'; - } - - if (previousNode == this.lastNode) { - return this.append(expression); - } - else { - return this.insertBefore(afterId + 1, expression); - } - }; - - - /** - * remove an expression. If the expression is not found, no action will - * be taken. - * @param {Number} id id of an existing expression - */ - Workspace.prototype.remove = function (id) { - var node = this.nodes[id]; - if (!node) { - throw 'Node with id "' + id + '" not found'; - } - - // get the dependencies (needed to update them after deletion of this node) - var dependentIds = this.getDependencies(id); - - // adjust links to previous and next nodes - var previousNode = node.previousNode; - var nextNode = node.nextNode; - if (previousNode) { - previousNode.nextNode = nextNode; - } - else { - this.firstNode = nextNode; - } - if (nextNode) { - nextNode.previousNode = previousNode; - } - else { - this.lastNode = previousNode; - } - - // re-link the scope - var previousScope = previousNode ? previousNode.scope : this.scope; - if (nextNode) { - nextNode.scope.parentScope = previousScope; - } - - // remove the node - delete this.nodes[id]; - - // update all dependent nodes - this._update(dependentIds); - }; - - - /** - * replace an existing expression - * @param {String} expression the new expression - * @param {Number} id id of an existing expression - */ - Workspace.prototype.replace = function (expression, id) { - var node = this.nodes[id]; - if (!node) { - throw 'Node with id "' + id + '" not found'; - } - - // get the dependencies - var dependentIds = [id]; - Workspace._merge(dependentIds, this.getDependencies(id)); - - var previousNode = node.previousNode; - var nextNode = node.nextNode; - var previousScope = previousNode ? previousNode.scope : this.scope; - - // replace the expression - node.setExpr(expression); - - // add the new dependencies - Workspace._merge(dependentIds, this.getDependencies(id)); - - // update all dependencies - this._update(dependentIds); - }; - - /** - * @constructor Workspace.Node - * @param {Object} params Object containing parameters: - * {Number} id - * {String} expression An expression, for example "2+3" - * {Parser} parser - * {Scope} scope - * {Workspace.Node} nextNode - * {Workspace.Node} previousNode - */ - Workspace.Node = function (params) { - this.id = params.id; - this.parser = params.parser; - this.scope = params.scope; - this.nextNode = params.nextNode; - this.previousNode = params.previousNode; - // TODO: throw error when id, parser, or scope is not given - - this.updateSeq = 0; - this.result = undefined; - this.setExpr(params.expression); - }; - - /** - * set the node's expression - * @param {String} expression - */ - Workspace.Node.prototype.setExpr = function (expression) { - this.expression = expression || ''; - this.scope.clear(); - this._parse(); - }; - - /** - * get the node's expression - * @return {String} expression - */ - Workspace.Node.prototype.getExpr = function () { - return this.expression; - }; - - /** - * get the result of the nodes expression - * @return {*} result - */ - Workspace.Node.prototype.getResult = function () { - // TODO: automatically evaluate when not up to date? - return this.result; - }; - - /** - * parse the node's expression - * @private - */ - Workspace.Node.prototype._parse = function () { - try { - this.fn = this.parser.parse(this.expression, this.scope); - } - catch (err) { - var value = 'Error: ' + String(err.message || err); - this.fn = new Constant(value); - } - }; - - /** - * Evaluate the node expression - * @return {*} result - */ - Workspace.Node.prototype.eval = function () { - try { - this.scope.init(); - this.result = this.fn.eval(); - } - catch (err) { - this.scope.init(); - this.result = 'Error: ' + String(err.message || err); - } - return this.result; - }; - - /** - * Merge array2 into array1, only adding distinct elements. - * The elements are not sorted. - * @param {Array} array1 - * @param {Array} array2 - * @private - */ - Workspace._merge = function (array1, array2) { - for (var i = 0, iMax = array2.length; i < iMax; i++) { - var elem = array2[i]; - if (array1.indexOf(elem) == -1) { - array1.push(elem); - } - } - }; - - /** - * Retrieve the id's of the nodes which are dependent on this node - * @param {Number} id - * @return {Number[]} id's of dependent nodes. The ids are not ordered - */ - Workspace.prototype.getDependencies = function (id) { - var ids = [], - name; - - var node = this.nodes[id]; - if (node) { - // create a list with all symbol names defined/updated in this scope - var defs = node.scope.defs; - var updates = node.scope.updates; - var symbolNames = []; - for (name in defs) { - if (defs.hasOwnProperty(name)) { - symbolNames.push(name); - } - } - for (name in updates) { - if (updates.hasOwnProperty(name) && symbolNames.indexOf(name) == -1) { - symbolNames.push(name); - } - } - - // loop through the nodes and retrieve the ids of nodes dependent on - // these values. We start at current node - var n = node.nextNode; - while (n && symbolNames.length) { - var scope = n.scope; - // loop through each of the parameters and check if the scope - // contains bindings to this parameter func - var i = 0; - while (i < symbolNames.length) { - name = symbolNames[i]; - - // check if this scope contains a link to the current symbol name - if (scope.hasLink(name) || scope.hasUpdate(name)) { - if (ids.indexOf(n.id) == -1) { - ids.push(n.id); - - // recursively check the dependencies of this id - var childIds = this.getDependencies(n.id); - Workspace._merge(ids, childIds); - } - } - - // stop propagation of the current symbol name as soon as it is - // redefined in one of the next scopes (not if it is updated) - if (scope.hasDef(name)) { - symbolNames.splice(i, 1); - i--; - } - - i++; - } - - n = n.nextNode; - } - } - - return ids; - }; - - /** - * Retrieve an expression, the original string - * @param {Number} id Id of the expression to be retrieved - * @return {String} The original expression as a string - */ - Workspace.prototype.getExpr = function (id) { - var node = this.nodes[id]; - if (!node) { - throw 'Node with id "' + id + '" not found'; - } - - return node.getExpr(); - }; - - - /** - * get the result of and expression - * @param {Number} id - * @return {*} result - */ - Workspace.prototype.getResult = function (id) { - var node = this.nodes[id]; - if (!node) { - throw 'Node with id "' + id + '" not found'; - } - - return node.getResult(); - }; - - - /** - * Update the results of an expression and all dependent expressions - * @param {Number[]} ids Ids of the expressions to be updated - * @private - */ - Workspace.prototype._update = function (ids) { - this.updateSeq++; - var updateSeq = this.updateSeq; - var nodes = this.nodes; - - for (var i = 0, iMax = ids.length; i < iMax; i++) { - var id = ids[i]; - var node = nodes[id]; - if (node) { - node.eval(); - //console.log('eval node=' + id + ' result=' + node.result.toString()); // TODO: cleanup - node.updateSeq = updateSeq; - } - else { - // TODO: throw error? - } - } - }; - - /** - * Get all changes since an update sequence - * @param {Number} updateSeq. Optional. if not provided, all changes are - * since the creation of the workspace are returned - * @return {Object} ids Object containing two parameters: - * param {Number[]} ids Array containing - * the ids of the changed - * expressions - * param {Number} updateSeq the current update - * sequence - */ - Workspace.prototype.getChanges = function (updateSeq) { - var changedIds = []; - var node = this.firstNode; - updateSeq = updateSeq || 0; - while (node) { - if (node.updateSeq > updateSeq) { - changedIds.push(node.id); - } - node = node.nextNode; - } - return { - 'ids': changedIds, - 'updateSeq': this.updateSeq - }; - }; - - /** - * Return a new, unique id for an expression - * @return {Number} new id - * @private - */ - Workspace.prototype._getNewId = function () { - this.idMax++; - return this.idMax; - }; - - /** - * String representation of the Workspace - * @return {String} description - */ - Workspace.prototype.toString = function () { - return JSON.stringify(this.toJSON()); - }; - - /** - * JSON representation of the Workspace - * @return {Object} description - */ - Workspace.prototype.toJSON = function () { - var json = []; - - var node = this.firstNode; - while (node) { - var desc = { - 'id': node.id, - 'expression': node.expression, - 'dependencies': this.getDependencies(node.id) - }; - - try { - desc.result = node.getResult(); - } catch (err) { - desc.result = 'Error: ' + String(err.message || err); - } - - json.push(desc); - - node = node.nextNode; - } - - return json; - }; - -})(); /** * Backward compatibility stuff */ diff --git a/math.min.js b/math.min.js index 0b7616456..e1127624e 100644 --- a/math.min.js +++ b/math.min.js @@ -24,6 +24,6 @@ * License for the specific language governing permissions and limitations under * the License. */ -(function(){function e(e){return e instanceof Boolean||"boolean"==typeof e}function n(e,t){if(this.constructor!=n)throw new SyntaxError("Complex constructor must be called with the new operator");if(null!=e&&!v(e)||null!=t&&!v(t))throw new TypeError("Two numbers or a single string expected in Complex constructor");this.re=e||0,this.im=t||0}function t(e){if(this.constructor!=t)throw new SyntaxError("Matrix constructor must be called with the new operator");if(e instanceof t||e instanceof w)this._data=e.toArray();else if(e instanceof Array)this._data=e;else{if(null!=e)throw new TypeError("Unsupported type of data ("+Z.typeof(e)+")");this._data=[]}this._size=K.size(this._data)}function r(e,n){if(!v(e)||!g(e))throw new TypeError("Index must be an integer (value: "+e+")");if(1>e)throw new RangeError("Index out of range ("+e+" < 1)");if(n&&e>n)throw new RangeError("Index out of range ("+e+" > "+n+")")}function i(e,n){return r(n,e.length),e[n-1]}function a(e,n){return n.forEach(function(n){e=i(e,n)}),Z.clone(e)}function o(e,n){var t=n[0];return t.map?t.map(function(n){return i(e,n)}):[i(e,t)]}function f(e,n){var t=n[0],r=n[1];if(t.map)return r.map?t.map(function(n){var t=i(e,n);return r.map(function(e){return i(t,e)})}):t.map(function(n){return[i(i(e,n),r)]});if(r.map){var a=i(e,t);return[r.map(function(e){return i(a,e)})]}return[[i(i(e,t),r)]]}function s(e,n,t){var r=t==n.length-1,a=n[t],o=function(a){var o=i(e,a);return r?o:s(o,n,t+1)};return a.map?a.map(o):[o(a)]}function u(e,n,t){if(r(n),t instanceof Array)throw new TypeError("Dimension mismatch, value expected instead of array");e[n-1]=t}function c(e,n,t,i){var a=!1;t.length>n.length&&(a=!0);for(var o=0;t.length>o;o++){var f=t[o];r(f),(null==n[o]||f>n[o])&&(n[o]=f,a=!0)}a&&K.resize(e,n,0);var s=n.length;t.forEach(function(n,t){s-1>t?e=e[n-1]:e[n-1]=i})}function l(e,n,t,i){var a=t[0];r(a),a>n[0]&&K.resize(e,[a],0),e[a-1]=i}function h(e,n,t,i){var a=t[0],o=t[1];r(a),r(o);var f=!1;a>(n[0]||0)&&(n[0]=a,f=!0),o>(n[1]||0)&&(n[1]=o,f=!0),f&&K.resize(e,n,0),e[a-1][o-1]=i}function m(e,n,t,r,i){var a=r==t.length-1,o=t[r],f=function(o,f){if(a)u(e,o,i[f]),e.length>(n[r]||0)&&(n[r]=e.length);else{var s=e[o-1];s instanceof Array||(e[o-1]=s=[s],e.length>(n[r]||0)&&(n[r]=e.length)),m(s,n,t,r+1,i[f])}};if(o.map){var s=o.size&&o.size()||o.length;if(s!=i.length)throw new RangeError("Dimensions mismatch ("+s+" != "+i.length+")");o.map(f)}else f(o,0)}function p(e){for(var n=0,t=e.length;t>n;n++){var r=e[n];r instanceof Array?p(r):void 0==r&&(e[n]=0)}}function v(e){return e instanceof Number||"number"==typeof e}function g(e){return e==Math.round(e)}function w(e,n,t){if(this.constructor!=w)throw new SyntaxError("Range constructor must be called with the new operator");if(null!=e&&!v(e))throw new TypeError("Parameter start must be a number");if(null!=t&&!v(t))throw new TypeError("Parameter end must be a number");if(null!=n&&!v(n))throw new TypeError("Parameter step must be a number");this.start=null!=e?e:0,this.end=null!=t?t:0,this.step=null!=n?n:1}function d(e,n){var t=Z.type.Selector,r=Array.prototype.slice;t.prototype[e]="function"==typeof n?function(){var e=[this.value].concat(r.call(arguments,0));return new t(n.apply(this,e))}:new t(n)}function y(e){return e instanceof String||"string"==typeof e}function E(e,n){if(this.constructor!=E)throw Error("Unit constructor must be called with the new operator");if(null!=e&&!v(e))throw Error("First parameter in Unit constructor must be a number");if(null!=n&&!y(n))throw Error("Second parameter in Unit constructor must be a string");if(null!=n){var t=N(n);if(!t)throw Error('String "'+n+'" is no unit');this.unit=t.unit,this.prefix=t.prefix,this.hasUnit=!0}else this.unit=E.UNIT_NONE,this.prefix=E.PREFIX_NONE,this.hasUnit=!1;null!=e?(this.value=this._normalize(e),this.hasValue=!0,this.fixPrefix=!1):(this.value=this._normalize(1),this.hasValue=!1,this.fixPrefix=!0)}function N(e){for(var n=E.UNITS,t=0,r=n.length;r>t;t++){var i=n[t];if(K.endsWith(e,i.name)){var a=e.length-i.name.length,o=e.substring(0,a),f=i.prefixes[o];if(void 0!==f)return{unit:i,prefix:f}}}return null}function O(e,n){var t=void 0;if(2==arguments.length){var r=Z.typeof(n);t="Function "+e+" does not support a parameter of type "+r}else if(arguments.length>2){for(var i=[],a=1;arguments.length>a;a++)i.push(Z.typeof(arguments[a]));t="Function "+e+" does not support a parameters of type "+i.join(", ")}else t="Unsupported parameter in function "+e;return new TypeError(t)}function x(e,n,t,r){var i="Wrong number of arguments in function "+e+" ("+n+" provided, "+t+(void 0!=r?"-"+r:"")+" expected)";return new SyntaxError(i)}function b(e,t){var r=t.re*t.re+t.im*t.im;return new n((e.re*t.re+e.im*t.im)/r,(e.im*t.re-e.re*t.im)/r)}function M(e,t){return new n(e.re*t.re-e.im*t.im,e.re*t.im+e.im*t.re)}function A(e,n){var t=Z.log(e),r=Z.multiply(t,n);return Z.exp(r)}function S(e,n){var t=Math.pow(10,void 0!=n?n:Z.options.precision);return Math.round(e*t)/t}function T(e,n,t,r){if(t>r){if(e.length!=n.length)throw Error("Dimensions mismatch ("+e.length+" != "+n.length+")");for(var i=[],a=0;e.length>a;a++)i[a]=T(e[a],n[a],t,r+1);return i}return e.concat(n)}function U(e,n,t){var r=Z.multiply,i=Z.subtract;if(1==n)return e[0][0];if(2==n)return i(r(e[0][0],e[1][1]),r(e[1][0],e[0][1]));for(var a=0,o=0;t>o;o++){var f=L(e,n,t,0,o);a+=r(r((o+1)%2+(o+1)%2-1,e[0][o]),U(f,n-1,t-1))}return a}function L(e,n,t,r,i){for(var a,o=[],f=0;n>f;f++)if(f!=r){a=o[f-(f>r)]=[];for(var s=0;t>s;s++)s!=i&&(a[s-(s>i)]=e[f][s])}return o}function R(e,n,t){var r,i,a,o,f,s=Z.add,u=Z.unaryminus,c=Z.multiply,l=Z.divide;if(1==n){if(o=e[0][0],0==o)throw Error("Cannot calculate inverse, determinant is zero");return[[l(1,o)]]}if(2==n){var h=Z.det(e);if(0==h)throw Error("Cannot calculate inverse, determinant is zero");return[[l(e[1][1],h),l(u(e[0][1]),h)],[l(u(e[1][0]),h),l(e[0][0],h)]]}var m=e.concat();for(r=0;n>r;r++)m[r]=m[r].concat();for(var p=Z.eye(n).valueOf(),v=0;t>v;v++){for(r=v;n>r&&0==m[r][v];)r++;if(r==n||0==m[r][v])throw Error("Cannot calculate inverse, determinant is zero");r!=v&&(f=m[v],m[v]=m[r],m[r]=f,f=p[v],p[v]=p[r],p[r]=f);var g=m[v],w=p[v];for(r=0;n>r;r++){var d=m[r],y=p[r];if(r!=v){if(0!=d[v]){for(a=l(u(d[v]),g[v]),i=v;t>i;i++)d[i]=s(d[i],c(a,g[i]));for(i=0;t>i;i++)y[i]=s(y[i],c(a,w[i]))}}else{for(a=g[v],i=v;t>i;i++)d[i]=l(d[i],a);for(i=0;t>i;i++)y[i]=l(y[i],a)}}}return p}function _(e){if(1==e.length)return _(e[0]);for(var n=0,t=e.length;t>n;n++){var r=e[n];r instanceof Array&&(e[n]=_(r))}return e}function z(e){for(var n=Z.larger,t=e[0],r=1,i=e.length;i>r;r++){var a=e[r];n(a,t)&&(t=a)}return t}function q(e,n,t){for(var r=Z.larger,i=[],a=0;t>a;a++){for(var o=e[0][a],f=1;n>f;f++){var s=e[f][a];r(s,o)&&(o=s)}i[a]=o}return i}function I(e){for(var n=Z.smaller,t=e[0],r=1,i=e.length;i>r;r++){var a=e[r];n(a,t)&&(t=a)}return t}function P(e,n,t){for(var r=Z.smaller,i=[],a=0;t>a;a++){for(var o=e[0][a],f=1;n>f;f++){var s=e[f][a];r(s,o)&&(o=s)}i[a]=o}return i}function B(e,n){Z[e]=n,d(e,n)}function C(e){return"function"==typeof e||v(e)||y(e)||e instanceof n||e instanceof E}function G(){}function V(e,n,t){this.name=e,this.fn=n,this.params=t}function D(e){this.value=e}function k(e){this.nodes=e||[]}function F(){this.params=[],this.visible=[]}function j(e,n,t,r){this.name=e,this.params=n,this.expr=t,this.result=r}function H(e,n){this.object=e,this.params=n}function Y(e,n,t,r,i){this.name=e,this.variables=t,this.values=[];for(var a=0,o=this.variables.length;o>a;a++)this.values[a]=function(){var e=function(){return e.value};return e.value=void 0,e}();this.def=this.createFunction(e,n,t,r),this.result=i}function W(e,n){throw Error('Constructor "'+e+'" has been replaced by '+'constructor method "'+n+'" in math.js v0.5.0')}var Z={type:{},expr:{node:{}},options:{precision:10}};"undefined"!=typeof module&&module.exports!==void 0&&(module.exports=Z),"undefined"!=typeof exports&&(exports=Z),"undefined"!=typeof require&&"undefined"!=typeof define&&define(function(){return Z}),"undefined"!=typeof window&&(window.math=Z);var K=function(){function e(n){if(n instanceof Array){var t=n.length;if(t){var r=e(n[0]);return 0==r[0]?[0].concat(r):[t].concat(r)}return[t]}return[]}function n(e,t,r){var i,a=e.length;if(a!=t[r])throw new RangeError("Dimension mismatch ("+a+" != "+t[r]+")");if(t.length-1>r){var o=r+1;for(i=0;a>i;i++){var f=e[i];if(!(f instanceof Array))throw new RangeError("Dimension mismatch ("+(t.length-1)+" < "+t.length+")");n(e[i],t,o)}}else for(i=0;a>i;i++)if(e[i]instanceof Array)throw new RangeError("Dimension mismatch ("+(t.length+1)+" > "+t.length+")")}function r(e,n,t){if(n.length-1>t){var i=e[0];if(1!=e.length||!(i instanceof Array))throw new RangeError("Dimension mismatch ("+e.length+" > 0)");r(i,n,t+1)}else if(e.length)throw new RangeError("Dimension mismatch ("+e.length+" > 0)")}function i(e,n,t,r){if(!(e instanceof Array))throw new TypeError("Array expected");var a=e.length,o=n[t];if(a!=o){if(o>e.length)for(var f=e.length;o>f;f++)e[f]=r?Z.clone(r):0;else e.length=n[t];a=e.length}if(n.length-1>t){var s=t+1;for(f=0;a>f;f++)u=e[f],u instanceof Array||(u=[u],e[f]=u),i(u,n,s,r)}else for(f=0;a>f;f++){for(var u=e[f];u instanceof Array;)u=u[0];e[f]=u}}var a={};return a.formatNumber=function(e,n){if(1/0===e)return"Infinity";if(e===-1/0)return"-Infinity";if(0/0===e)return"NaN";var t=Math.abs(e);if(t>1e-4&&1e6>t||0==t)return S(e,n)+"";var r=Math.round(Math.log(t)/Math.LN10),i=e/Math.pow(10,r);return S(i,n)+"E"+r},a.formatArray=function(e){if(e instanceof Array){for(var n="[",t=e.length,r=0;t>r;r++)0!=r&&(n+=", "),n+=a.formatArray(e[r]);return n+="]"}return Z.format(e)},a.formatArray2d=function(e){var n="[",t=a.size(e);if(2!=t.length)throw new RangeError("Array must be two dimensional (size: "+a.formatArray(t)+")");for(var r=t[0],i=t[1],o=0;r>o;o++){0!=o&&(n+="; ");for(var f=e[o],s=0;i>s;s++){0!=s&&(n+=", ");var u=f[s];void 0!=u&&(n+=Z.format(u))}}return n+="]"},a.argsToArray=function(e){var n;if(0==e.length)n=[];else if(1==e.length)n=e[0],n instanceof t&&(n=n.toVector()),n instanceof w&&(n=n.valueOf()),n instanceof Array||(n=[n]);else{n=[];for(var r=0;e.length>r;r++)n[r]=e[r]}return n},a.endsWith=function(e,n){var t=e.length-n.length,r=e.length;return e.substring(t,r)===n},a.randomUUID=function(){var e=function(){return Math.floor(65536*Math.random()).toString(16)};return e()+e()+"-"+e()+"-"+e()+"-"+e()+"-"+e()+e()+e()},a.map=function(e,n){if(e instanceof Array||e instanceof t||e instanceof w)return e.map(function(e){return n(e)});throw new TypeError("Array expected")},a.map2=function(e,n,r){var i,o,f;if(e instanceof t||n instanceof t)return new t(a.map2(e.valueOf(),n.valueOf(),r));if(e instanceof w||n instanceof w)return new t(a.map2(e.valueOf(),n.valueOf(),r));if(e instanceof Array)if(n instanceof Array){if(e.length!=n.length)throw new RangeError("Dimension mismatch ("+e.length+" != "+n.length+")");for(i=[],o=e.length,f=0;o>f;f++)i[f]=r(e[f],n[f])}else for(i=[],o=e.length,f=0;o>f;f++)i[f]=r(e[f],n);else if(n instanceof Array)for(i=[],o=n.length,f=0;o>f;f++)i[f]=r(e,n[f]);else i=r(e,n);return i},a.forEach=function(e,n){if(e instanceof Array)e.forEach(n);else for(var t in e)e.hasOwnProperty(t)&&n(e[t],t,e)},a.mapObject=function(e,n){var t={};for(var r in e)e.hasOwnProperty(r)&&(t[r]=n(e[r]));return t},a.deepEqual=function(e,n){var t,r,i;if(e instanceof Array){if(!(n instanceof Array))return!1;for(r=0,i=e.length;i>r;r++)if(!a.deepEqual(e[r],n[r]))return!1;return!0}if(e instanceof Object){if(n instanceof Array||!(n instanceof Object))return!1;for(t in e)if(e.hasOwnProperty(t)&&!a.deepEqual(e[t],n[t]))return!1;for(t in n)if(n.hasOwnProperty(t)&&!a.deepEqual(e[t],n[t]))return!1;return!0}return e.valueOf()==n.valueOf()},a.size=function(n){var t=e(n);return a.validate(n,t),t},a.validate=function(e,t){var i=0==t.length;if(i){if(e instanceof Array)throw new RangeError("Dimension mismatch ("+e.length+" != 0)")}else{var o=-1!=t.indexOf(0);o?(t.forEach(function(e){if(0!=e)throw new RangeError("Invalid size, all dimensions must be either zero or non-zero (size: "+a.formatArray(t)+")")}),r(e,t,0)):n(e,t,0)}},a.resize=function(e,n,t){if(!(n instanceof Array))throw new TypeError("Size must be an array (size is "+Z.typeof(n)+")");n.forEach(function(e){if(!v(e)||!g(e)||0>e)throw new TypeError("Invalid size, must contain positive integers (size: "+a.formatArray(n)+")")});var r=-1!=n.indexOf(0);r&&n.forEach(function(e){if(0!=e)throw new RangeError("Invalid size, all dimensions must be either zero or non-zero (size: "+a.formatArray(n)+")")}),i(e,n,0,t)},Array.prototype.indexOf||(Array.prototype.indexOf=function(e){for(var n=0;this.length>n;n++)if(this[n]==e)return n;return-1}),Array.prototype.forEach||(Array.prototype.forEach=function(e,n){for(var t=0,r=this.length;r>t;++t)e.call(n||this,this[t],t,this)}),Array.prototype.map||(Array.prototype.map=function(e,n){var t,r,i;if(null==this)throw new TypeError(" this is null or not defined");var a=Object(this),o=a.length>>>0;if("function"!=typeof e)throw new TypeError(e+" is not a function");for(n&&(t=n),r=Array(o),i=0;o>i;){var f,s;i in a&&(f=a[i],s=e.call(t,f,i,a),r[i]=s),i++}return r}),Array.prototype.every||(Array.prototype.every=function(e){"use strict";if(null==this)throw new TypeError;var n=Object(this),t=n.length>>>0;if("function"!=typeof e)throw new TypeError;for(var r=arguments[1],i=0;t>i;i++)if(i in n&&!e.call(r,n[i],i,n))return!1;return!0}),Array.prototype.some||(Array.prototype.some=function(e){"use strict";if(null==this)throw new TypeError;var n=Object(this),t=n.length>>>0;if("function"!=typeof e)throw new TypeError;for(var r=arguments[1],i=0;t>i;i++)if(i in n&&e.call(r,n[i],i,n))return!0;return!1}),a}();Z.type.Complex=n,function(){function e(){for(;" "==c||" "==c;)i()}function t(e){return e>="0"&&"9">=e||"."==e}function r(e){return e>="0"&&"9">=e}function i(){u++,c=s[u]}function a(e){u=e,c=s[u]}function o(){var e="",n=u;if("+"==c?i():"-"==c&&(e+=c,i()),!t(c))return a(n),null;for(;t(c);)e+=c,i();if("E"==c||"e"==c){if(e+=c,i(),("+"==c||"-"==c)&&(e+=c,i()),!r(c))return a(n),null;for(;r(c);)e+=c,i()}return e}function f(){var e=s[u+1];if("I"==c||"i"==c)return i(),"1";if(!("+"!=c&&"-"!=c||"I"!=e&&"i"!=e)){var n="+"==c?"1":"-1";return i(),i(),n}return null}var s,u,c;n.parse=function(t){if(s=t,u=-1,c="",!y(s))return null;i(),e();var r=o();if(r){if("I"==c||"i"==c)return i(),e(),c?null:new n(0,Number(r));e();var a=c;if("+"!=a&&"-"!=a)return e(),c?null:new n(Number(r),0);i(),e();var l=o();if(l){if("I"!=c&&"i"!=c)return null;i()}else if(l=f(),!l)return null;return"-"==a&&(l="-"==l[0]?"+"+l.substring(1):"-"+l),i(),e(),c?null:new n(Number(r),Number(l))}return(r=f())?(e(),c?null:new n(0,Number(r))):null}}(),n.prototype.clone=function(){return new n(this.re,this.im)},n.prototype.toString=function(){var e="",n=K.formatNumber(this.re),t=K.formatNumber(this.im);return e=0==this.im?n:0==this.re?1==this.im?"i":-1==this.im?"-i":t+"i":this.im>0?1==this.im?n+" + i":n+" + "+t+"i":-1==this.im?n+" - i":n+" - "+K.formatNumber(Math.abs(this.im))+"i"},Z.type.Matrix=t,t.prototype.get=function(e){var n;if(e instanceof t)n=e.isVector(),e=e.valueOf();else{if(!(e instanceof Array))throw new TypeError("Unsupported type of index "+Z.typeof(e));n=!e.some(function(e){return e.forEach})}if(e.length!=this._size.length)throw new RangeError("Dimension mismatch ("+e.length+" != "+this._size.length+")");if(n)switch(e.length){case 1:return i(this._data,e[0]);case 2:return i(i(this._data,e[0]),e[1]);default:return a(this._data,e)}else switch(e.length){case 1:return new t(o(this._data,e));case 2:return new t(f(this._data,e));default:return new t(s(this._data,e,0))}},t.prototype.set=function(e,n){var r;if(e instanceof t)r=e.isVector(),e=e.valueOf();else{if(!(e instanceof Array))throw new TypeError("Unsupported type of index "+Z.typeof(e));r=!e.some(function(e){return e.forEach})}if((n instanceof t||n instanceof w)&&(n=n.valueOf()),e.length=e})},t.prototype.toVector=function(){var e=0,n=void 0,t=[];if(this._size.forEach(function(r,i){r>1&&(e++,n=i),t[i]=0}),0==e){var r=this.toScalar();return r?[r]:[]}if(1==e){var i=[],a=function(e){e instanceof Array?e.forEach(a):i.push(e)};return a(this._data),i}return null},t.prototype.isVector=function(){var e=0;return this._size.forEach(function(n){n>1&&e++}),1>=e},t.prototype.toArray=function(){return Z.clone(this._data)},t.prototype.valueOf=function(){return this._data},t.prototype.toString=function(){return K.formatArray(this._data)},Z.type.Range=w,w.parse=function(e){if(!y(e))return null;var n=e.split(":"),t=n.map(function(e){return Number(e)}),r=t.some(function(e){return isNaN(e)});if(r)return null;switch(t.length){case 2:return new w(t[0],1,t[1]);case 3:return new w(t[0],t[1],t[2]);default:return null}},w.prototype.clone=function(){return new w(this.start,this.step,this.end)},w.prototype.size=function(){var e=0,n=Number(this.start),t=Number(this.step),r=Number(this.end),i=r-n;return Z.sign(t)==Z.sign(i)?e=Math.floor(i/t)+1:0==i&&(e=1),isNaN(e)&&(e=0),[e]},w.prototype.forEach=function(e){var n=Number(this.start),t=Number(this.step),r=Number(this.end),i=0;if(t>0)for(;r>=n;)e(n,i,this),n+=t,i++;else if(0>t)for(;n>=r;)e(n,i,this),n+=t,i++},w.prototype.map=function(e){var n=[];return this.forEach(function(t,r,i){n[r]=e(t,r,i)}),n},w.prototype.toMatrix=function(){return new t(this.toArray())},w.prototype.toArray=function(){var e=[];return this.forEach(function(n,t){e[t]=n}),e},w.prototype.toVector=w.prototype.toArray,w.prototype.isVector=function(){return!0},w.prototype.toScalar=function(){var e=this.toArray();return 1==e.length?e[0]:null},w.prototype.isScalar=function(){return 1==this.size()[0]},w.prototype.valueOf=function(){return this.toArray()},w.prototype.toString=function(){var e=Z.format(Number(this.start));return 1!=this.step&&(e+=":"+Z.format(Number(this.step))),e+=":"+Z.format(Number(this.end))},Z.type.Selector=function X(e){if(!(this instanceof X))throw new SyntaxError("Selector constructor must be called with the new operator");this.value=e instanceof Z.type.Selector?e.value:e||void 0},Z.type.Selector.prototype={done:function(){return this.value},get:function(){var e=this.value;if(!e)throw Error("Selector value is undefined");if(e.get)return new Z.type.Selector(e.get.apply(e,arguments));if(e instanceof Array)return e=new t(e),new Z.type.Selector(e.get.apply(e,arguments).valueOf());throw Error("Selector value has no method get")},set:function(){var e=this.value;if(!e)throw Error("Selector value is undefined");if(e.set)return new Z.type.Selector(e.set.apply(e,arguments));if(e instanceof Array)return e=new t(e),new Z.type.Selector(e.set.apply(e,arguments).valueOf());throw Error("Selector value has no method set")},valueOf:function(){return this.value},toString:function(){return Z.format(this.value)}},Z.type.Unit=E,function(){function e(){for(;" "==u||" "==u;)r()}function n(e){return e>="0"&&"9">=e||"."==e}function t(e){return e>="0"&&"9">=e}function r(){s++,u=f[s]}function i(e){s=e,u=f[s]}function a(){var e="",a=s;if("+"==u?r():"-"==u&&(e+=u,r()),!n(u))return i(a),null;for(;n(u);)e+=u,r();if("E"==u||"e"==u){if(e+=u,r(),("+"==u||"-"==u)&&(e+=u,r()),!t(u))return i(a),null;for(;t(u);)e+=u,r()}return e}function o(){var n="";for(e();u&&" "!=u&&" "!=u;)n+=u,r();return n||null}var f,s,u;E.parse=function(n){if(f=n,s=-1,u="",!y(f))return null;r(),e();var t,i=a();return i?(t=o(),r(),e(),u?null:i&&t?new E(Number(i),t):null):(t=o(),r(),e(),u?null:new E(null,t))}}(),E.prototype.clone=function(){var e=new E;for(var n in this)this.hasOwnProperty(n)&&(e[n]=this[n]);return e},E.prototype._normalize=function(e){return(e+this.unit.offset)*this.unit.value*this.prefix.value},E.prototype._unnormalize=function(e,n){return void 0==n?e/this.unit.value/this.prefix.value-this.unit.offset:e/this.unit.value/n-this.unit.offset},E.isPlainUnit=function(e){return null!=N(e)},E.prototype.hasBase=function(e){return void 0===this.unit.base?void 0===e:this.unit.base===e},E.prototype.equalBase=function(e){return this.unit.base===e.unit.base},E.prototype.equals=function(e){return this.equalBase(e)&&this.value==e.value},E.prototype.in=function(e){var n;if(y(e)){if(n=new E(null,e),!this.equalBase(n))throw Error("Units do not match");return n.value=this.value,n}if(e instanceof E){if(!this.equalBase(e))throw Error("Units do not match");if(e.hasValue)throw Error("Cannot convert to a unit with a value");if(!e.hasUnit)throw Error("Unit expected on the right hand side of function in");return n=e.clone(),n.value=this.value,n.fixPrefix=!0,n}throw Error("String or Unit expected as parameter")},E.prototype.toNumber=function(e){var n=this.in(e),t=this.fixPrefix?n._bestPrefix():n.prefix;return n._unnormalize(n.value,t.value)},E.prototype.toString=function(){var e;if(this.fixPrefix)return e=this._unnormalize(this.value),K.formatNumber(e)+" "+this.prefix.name+this.unit.name;var n=this._bestPrefix();return e=this._unnormalize(this.value,n.value),K.formatNumber(e)+" "+n.name+this.unit.name},E.prototype._bestPrefix=function(){var e=Math.abs(this.value/this.unit.value),n=E.PREFIX_NONE,t=Math.abs(Math.log(e/n.value)/Math.LN10-1.2),r=this.unit.prefixes;for(var i in r)if(r.hasOwnProperty(i)){var a=r[i];if(a.scientific){var o=Math.abs(Math.log(e/a.value)/Math.LN10-1.2);t>o&&(n=a,t=o)}}return n},E.PREFIXES={NONE:{"":{name:"",value:1,scientific:!0}},SHORT:{"":{name:"",value:1,scientific:!0},da:{name:"da",value:10,scientific:!1},h:{name:"h",value:100,scientific:!1},k:{name:"k",value:1e3,scientific:!0},M:{name:"M",value:1e6,scientific:!0},G:{name:"G",value:1e9,scientific:!0},T:{name:"T",value:1e12,scientific:!0},P:{name:"P",value:1e15,scientific:!0},E:{name:"E",value:1e18,scientific:!0},Z:{name:"Z",value:1e21,scientific:!0},Y:{name:"Y",value:1e24,scientific:!0},d:{name:"d",value:.1,scientific:!1},c:{name:"c",value:.01,scientific:!1},m:{name:"m",value:.001,scientific:!0},u:{name:"u",value:1e-6,scientific:!0},n:{name:"n",value:1e-9,scientific:!0},p:{name:"p",value:1e-12,scientific:!0},f:{name:"f",value:1e-15,scientific:!0},a:{name:"a",value:1e-18,scientific:!0},z:{name:"z",value:1e-21,scientific:!0},y:{name:"y",value:1e-24,scientific:!0}},LONG:{"":{name:"",value:1,scientific:!0},deca:{name:"deca",value:10,scientific:!1},hecto:{name:"hecto",value:100,scientific:!1},kilo:{name:"kilo",value:1e3,scientific:!0},mega:{name:"mega",value:1e6,scientific:!0},giga:{name:"giga",value:1e9,scientific:!0},tera:{name:"tera",value:1e12,scientific:!0},peta:{name:"peta",value:1e15,scientific:!0},exa:{name:"exa",value:1e18,scientific:!0},zetta:{name:"zetta",value:1e21,scientific:!0},yotta:{name:"yotta",value:1e24,scientific:!0},deci:{name:"deci",value:.1,scientific:!1},centi:{name:"centi",value:.01,scientific:!1},milli:{name:"milli",value:.001,scientific:!0},micro:{name:"micro",value:1e-6,scientific:!0},nano:{name:"nano",value:1e-9,scientific:!0},pico:{name:"pico",value:1e-12,scientific:!0},femto:{name:"femto",value:1e-15,scientific:!0},atto:{name:"atto",value:1e-18,scientific:!0},zepto:{name:"zepto",value:1e-21,scientific:!0},yocto:{name:"yocto",value:1e-24,scientific:!0}},BINARY_SHORT:{"":{name:"",value:1,scientific:!0},k:{name:"k",value:1024,scientific:!0},M:{name:"M",value:Math.pow(1024,2),scientific:!0},G:{name:"G",value:Math.pow(1024,3),scientific:!0},T:{name:"T",value:Math.pow(1024,4),scientific:!0},P:{name:"P",value:Math.pow(1024,5),scientific:!0},E:{name:"E",value:Math.pow(1024,6),scientific:!0},Z:{name:"Z",value:Math.pow(1024,7),scientific:!0},Y:{name:"Y",value:Math.pow(1024,8),scientific:!0},Ki:{name:"Ki",value:1024,scientific:!0},Mi:{name:"Mi",value:Math.pow(1024,2),scientific:!0},Gi:{name:"Gi",value:Math.pow(1024,3),scientific:!0},Ti:{name:"Ti",value:Math.pow(1024,4),scientific:!0},Pi:{name:"Pi",value:Math.pow(1024,5),scientific:!0},Ei:{name:"Ei",value:Math.pow(1024,6),scientific:!0},Zi:{name:"Zi",value:Math.pow(1024,7),scientific:!0},Yi:{name:"Yi",value:Math.pow(1024,8),scientific:!0}},BINARY_LONG:{"":{name:"",value:1,scientific:!0},kilo:{name:"kilo",value:1024,scientific:!0},mega:{name:"mega",value:Math.pow(1024,2),scientific:!0},giga:{name:"giga",value:Math.pow(1024,3),scientific:!0},tera:{name:"tera",value:Math.pow(1024,4),scientific:!0},peta:{name:"peta",value:Math.pow(1024,5),scientific:!0},exa:{name:"exa",value:Math.pow(1024,6),scientific:!0},zetta:{name:"zetta",value:Math.pow(1024,7),scientific:!0},yotta:{name:"yotta",value:Math.pow(1024,8),scientific:!0},kibi:{name:"kibi",value:1024,scientific:!0},mebi:{name:"mebi",value:Math.pow(1024,2),scientific:!0},gibi:{name:"gibi",value:Math.pow(1024,3),scientific:!0},tebi:{name:"tebi",value:Math.pow(1024,4),scientific:!0},pebi:{name:"pebi",value:Math.pow(1024,5),scientific:!0},exi:{name:"exi",value:Math.pow(1024,6),scientific:!0},zebi:{name:"zebi",value:Math.pow(1024,7),scientific:!0},yobi:{name:"yobi",value:Math.pow(1024,8),scientific:!0}}},E.PREFIX_NONE={name:"",value:1,scientific:!0},E.BASE_UNITS={NONE:{},LENGTH:{},MASS:{},TIME:{},CURRENT:{},TEMPERATURE:{},LUMINOUS_INTENSITY:{},AMOUNT_OF_SUBSTANCE:{},FORCE:{},SURFACE:{},VOLUME:{},ANGLE:{},BIT:{}};var Q=E.BASE_UNITS,J=E.PREFIXES;E.BASE_UNIT_NONE={},E.UNIT_NONE={name:"",base:E.BASE_UNIT_NONE,value:1,offset:0},E.UNITS=[{name:"meter",base:Q.LENGTH,prefixes:J.LONG,value:1,offset:0},{name:"inch",base:Q.LENGTH,prefixes:J.NONE,value:.0254,offset:0},{name:"foot",base:Q.LENGTH,prefixes:J.NONE,value:.3048,offset:0},{name:"yard",base:Q.LENGTH,prefixes:J.NONE,value:.9144,offset:0},{name:"mile",base:Q.LENGTH,prefixes:J.NONE,value:1609.344,offset:0},{name:"link",base:Q.LENGTH,prefixes:J.NONE,value:.201168,offset:0},{name:"rod",base:Q.LENGTH,prefixes:J.NONE,value:5.02921,offset:0},{name:"chain",base:Q.LENGTH,prefixes:J.NONE,value:20.1168,offset:0},{name:"angstrom",base:Q.LENGTH,prefixes:J.NONE,value:1e-10,offset:0},{name:"m",base:Q.LENGTH,prefixes:J.SHORT,value:1,offset:0},{name:"ft",base:Q.LENGTH,prefixes:J.NONE,value:.3048,offset:0},{name:"yd",base:Q.LENGTH,prefixes:J.NONE,value:.9144,offset:0},{name:"mi",base:Q.LENGTH,prefixes:J.NONE,value:1609.344,offset:0},{name:"li",base:Q.LENGTH,prefixes:J.NONE,value:.201168,offset:0},{name:"rd",base:Q.LENGTH,prefixes:J.NONE,value:5.02921,offset:0},{name:"ch",base:Q.LENGTH,prefixes:J.NONE,value:20.1168,offset:0},{name:"mil",base:Q.LENGTH,prefixes:J.NONE,value:254e-7,offset:0},{name:"m2",base:Q.SURFACE,prefixes:J.SHORT,value:1,offset:0},{name:"sqin",base:Q.SURFACE,prefixes:J.NONE,value:64516e-8,offset:0},{name:"sqft",base:Q.SURFACE,prefixes:J.NONE,value:.09290304,offset:0},{name:"sqyd",base:Q.SURFACE,prefixes:J.NONE,value:.83612736,offset:0},{name:"sqmi",base:Q.SURFACE,prefixes:J.NONE,value:2589988.110336,offset:0},{name:"sqrd",base:Q.SURFACE,prefixes:J.NONE,value:25.29295,offset:0},{name:"sqch",base:Q.SURFACE,prefixes:J.NONE,value:404.6873,offset:0},{name:"sqmil",base:Q.SURFACE,prefixes:J.NONE,value:6.4516e-10,offset:0},{name:"m3",base:Q.VOLUME,prefixes:J.SHORT,value:1,offset:0},{name:"L",base:Q.VOLUME,prefixes:J.SHORT,value:.001,offset:0},{name:"litre",base:Q.VOLUME,prefixes:J.LONG,value:.001,offset:0},{name:"cuin",base:Q.VOLUME,prefixes:J.NONE,value:16387064e-12,offset:0},{name:"cuft",base:Q.VOLUME,prefixes:J.NONE,value:.028316846592,offset:0},{name:"cuyd",base:Q.VOLUME,prefixes:J.NONE,value:.764554857984,offset:0},{name:"teaspoon",base:Q.VOLUME,prefixes:J.NONE,value:5e-6,offset:0},{name:"tablespoon",base:Q.VOLUME,prefixes:J.NONE,value:15e-6,offset:0},{name:"minim",base:Q.VOLUME,prefixes:J.NONE,value:6.161152e-8,offset:0},{name:"fluiddram",base:Q.VOLUME,prefixes:J.NONE,value:36966911e-13,offset:0},{name:"fluidounce",base:Q.VOLUME,prefixes:J.NONE,value:2957353e-11,offset:0},{name:"gill",base:Q.VOLUME,prefixes:J.NONE,value:.0001182941,offset:0},{name:"cup",base:Q.VOLUME,prefixes:J.NONE,value:.0002365882,offset:0},{name:"pint",base:Q.VOLUME,prefixes:J.NONE,value:.0004731765,offset:0},{name:"quart",base:Q.VOLUME,prefixes:J.NONE,value:.0009463529,offset:0},{name:"gallon",base:Q.VOLUME,prefixes:J.NONE,value:.003785412,offset:0},{name:"beerbarrel",base:Q.VOLUME,prefixes:J.NONE,value:.1173478,offset:0},{name:"oilbarrel",base:Q.VOLUME,prefixes:J.NONE,value:.1589873,offset:0},{name:"hogshead",base:Q.VOLUME,prefixes:J.NONE,value:.238481,offset:0},{name:"fldr",base:Q.VOLUME,prefixes:J.NONE,value:36966911e-13,offset:0},{name:"floz",base:Q.VOLUME,prefixes:J.NONE,value:2957353e-11,offset:0},{name:"gi",base:Q.VOLUME,prefixes:J.NONE,value:.0001182941,offset:0},{name:"cp",base:Q.VOLUME,prefixes:J.NONE,value:.0002365882,offset:0},{name:"pt",base:Q.VOLUME,prefixes:J.NONE,value:.0004731765,offset:0},{name:"qt",base:Q.VOLUME,prefixes:J.NONE,value:.0009463529,offset:0},{name:"gal",base:Q.VOLUME,prefixes:J.NONE,value:.003785412,offset:0},{name:"bbl",base:Q.VOLUME,prefixes:J.NONE,value:.1173478,offset:0},{name:"obl",base:Q.VOLUME,prefixes:J.NONE,value:.1589873,offset:0},{name:"g",base:Q.MASS,prefixes:J.SHORT,value:.001,offset:0},{name:"gram",base:Q.MASS,prefixes:J.LONG,value:.001,offset:0},{name:"ton",base:Q.MASS,prefixes:J.SHORT,value:907.18474,offset:0},{name:"tonne",base:Q.MASS,prefixes:J.SHORT,value:1e3,offset:0},{name:"grain",base:Q.MASS,prefixes:J.NONE,value:6479891e-11,offset:0},{name:"dram",base:Q.MASS,prefixes:J.NONE,value:.0017718451953125,offset:0},{name:"ounce",base:Q.MASS,prefixes:J.NONE,value:.028349523125,offset:0},{name:"poundmass",base:Q.MASS,prefixes:J.NONE,value:.45359237,offset:0},{name:"hundredweight",base:Q.MASS,prefixes:J.NONE,value:45.359237,offset:0},{name:"stick",base:Q.MASS,prefixes:J.NONE,value:.115,offset:0},{name:"gr",base:Q.MASS,prefixes:J.NONE,value:6479891e-11,offset:0},{name:"dr",base:Q.MASS,prefixes:J.NONE,value:.0017718451953125,offset:0},{name:"oz",base:Q.MASS,prefixes:J.NONE,value:.028349523125,offset:0},{name:"lbm",base:Q.MASS,prefixes:J.NONE,value:.45359237,offset:0},{name:"cwt",base:Q.MASS,prefixes:J.NONE,value:45.359237,offset:0},{name:"s",base:Q.TIME,prefixes:J.SHORT,value:1,offset:0},{name:"min",base:Q.TIME,prefixes:J.NONE,value:60,offset:0},{name:"h",base:Q.TIME,prefixes:J.NONE,value:3600,offset:0},{name:"seconds",base:Q.TIME,prefixes:J.LONG,value:1,offset:0},{name:"second",base:Q.TIME,prefixes:J.LONG,value:1,offset:0},{name:"sec",base:Q.TIME,prefixes:J.LONG,value:1,offset:0},{name:"minutes",base:Q.TIME,prefixes:J.NONE,value:60,offset:0},{name:"minute",base:Q.TIME,prefixes:J.NONE,value:60,offset:0},{name:"hours",base:Q.TIME,prefixes:J.NONE,value:3600,offset:0},{name:"hour",base:Q.TIME,prefixes:J.NONE,value:3600,offset:0},{name:"day",base:Q.TIME,prefixes:J.NONE,value:86400,offset:0},{name:"days",base:Q.TIME,prefixes:J.NONE,value:86400,offset:0},{name:"rad",base:Q.ANGLE,prefixes:J.NONE,value:1,offset:0},{name:"deg",base:Q.ANGLE,prefixes:J.NONE,value:.017453292519943295,offset:0},{name:"grad",base:Q.ANGLE,prefixes:J.NONE,value:.015707963267948967,offset:0},{name:"cycle",base:Q.ANGLE,prefixes:J.NONE,value:6.283185307179586,offset:0},{name:"A",base:Q.CURRENT,prefixes:J.SHORT,value:1,offset:0},{name:"ampere",base:Q.CURRENT,prefixes:J.LONG,value:1,offset:0},{name:"K",base:Q.TEMPERATURE,prefixes:J.NONE,value:1,offset:0},{name:"degC",base:Q.TEMPERATURE,prefixes:J.NONE,value:1,offset:273.15},{name:"degF",base:Q.TEMPERATURE,prefixes:J.NONE,value:1/1.8,offset:459.67},{name:"degR",base:Q.TEMPERATURE,prefixes:J.NONE,value:1/1.8,offset:0},{name:"kelvin",base:Q.TEMPERATURE,prefixes:J.NONE,value:1,offset:0},{name:"celsius",base:Q.TEMPERATURE,prefixes:J.NONE,value:1,offset:273.15},{name:"fahrenheit",base:Q.TEMPERATURE,prefixes:J.NONE,value:1/1.8,offset:459.67},{name:"rankine",base:Q.TEMPERATURE,prefixes:J.NONE,value:1/1.8,offset:0},{name:"mol",base:Q.AMOUNT_OF_SUBSTANCE,prefixes:J.NONE,value:1,offset:0},{name:"mole",base:Q.AMOUNT_OF_SUBSTANCE,prefixes:J.NONE,value:1,offset:0},{name:"cd",base:Q.LUMINOUS_INTENSITY,prefixes:J.NONE,value:1,offset:0},{name:"candela",base:Q.LUMINOUS_INTENSITY,prefixes:J.NONE,value:1,offset:0},{name:"N",base:Q.FORCE,prefixes:J.SHORT,value:1,offset:0},{name:"newton",base:Q.FORCE,prefixes:J.LONG,value:1,offset:0},{name:"lbf",base:Q.FORCE,prefixes:J.NONE,value:4.4482216152605,offset:0},{name:"poundforce",base:Q.FORCE,prefixes:J.NONE,value:4.4482216152605,offset:0},{name:"b",base:Q.BIT,prefixes:J.BINARY_SHORT,value:1,offset:0},{name:"bits",base:Q.BIT,prefixes:J.BINARY_LONG,value:1,offset:0},{name:"B",base:Q.BIT,prefixes:J.BINARY_SHORT,value:8,offset:0},{name:"bytes",base:Q.BIT,prefixes:J.BINARY_LONG,value:8,offset:0}],Z.E=Math.E,Z.LN2=Math.LN2,Z.LN10=Math.LN10,Z.LOG2E=Math.LOG2E,Z.LOG10E=Math.LOG10E,Z.PI=Math.PI,Z.SQRT1_2=Math.SQRT1_2,Z.SQRT2=Math.SQRT2,Z.I=new n(0,1),Z.pi=Z.PI,Z.e=Z.E,Z.i=Z.I,Z.abs=function(e){if(1!=arguments.length)throw x("abs",arguments.length,1); -if(v(e))return Math.abs(e);if(e instanceof n)return Math.sqrt(e.re*e.re+e.im*e.im);if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.abs);if(e.valueOf()!==e)return Z.abs(e.valueOf());throw O("abs",e)},Z.add=function(e,r){if(2!=arguments.length)throw x("add",arguments.length,2);if(v(e)){if(v(r))return e+r;if(r instanceof n)return new n(e+r.re,r.im)}else if(e instanceof n){if(v(r))return new n(e.re+r,e.im);if(r instanceof n)return new n(e.re+r.re,e.im+r.im)}else if(e instanceof E&&r instanceof E){if(!e.equalBase(r))throw Error("Units do not match");if(!e.hasValue)throw Error("Unit on left hand side of operator + has no value");if(!r.hasValue)throw Error("Unit on right hand side of operator + has no value");var i=e.clone();return i.value+=r.value,i.fixPrefix=!1,i}if(y(e)||y(r))return e+r;if(e instanceof Array||e instanceof t||e instanceof w||r instanceof Array||r instanceof t||r instanceof w)return K.map2(e,r,Z.add);if(e.valueOf()!==e||r.valueOf()!==r)return Z.add(e.valueOf(),r.valueOf());throw O("add",e,r)},Z.ceil=function(e){if(1!=arguments.length)throw x("ceil",arguments.length,1);if(v(e))return Math.ceil(e);if(e instanceof n)return new n(Math.ceil(e.re),Math.ceil(e.im));if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.ceil);if(e.valueOf()!==e)return Z.ceil(e.valueOf());throw O("ceil",e)},Z.cube=function(e){if(1!=arguments.length)throw x("cube",arguments.length,1);if(v(e))return e*e*e;if(e instanceof n)return Z.multiply(Z.multiply(e,e),e);if(e instanceof Array||e instanceof t||e instanceof w)return Z.multiply(Z.multiply(e,e),e);if(e.valueOf()!==e)return Z.cube(e.valueOf());throw O("cube",e)},Z.divide=function(e,r){if(2!=arguments.length)throw x("divide",arguments.length,2);if(v(e)){if(v(r))return e/r;if(r instanceof n)return b(new n(e,0),r)}if(e instanceof n){if(v(r))return b(e,new n(r,0));if(r instanceof n)return b(e,r)}if(e instanceof E&&v(r)){var i=e.clone();return i.value/=r,i}if(e instanceof Array||e instanceof t)return r instanceof Array||r instanceof t?Z.multiply(e,Z.inv(r)):K.map2(e,r,Z.divide);if(r instanceof Array||r instanceof t)return Z.multiply(e,Z.inv(r));if(e.valueOf()!==e||r.valueOf()!==r)return Z.divide(e.valueOf(),r.valueOf());throw O("divide",e,r)},Z.equal=function $(e,r){if(2!=arguments.length)throw x("equal",arguments.length,2);if(v(e)){if(v(r))return e==r;if(r instanceof n)return e==r.re&&0==r.im}if(e instanceof n){if(v(r))return e.re==r&&0==e.im;if(r instanceof n)return e.re==r.re&&e.im==r.im}if(e instanceof E&&r instanceof E){if(!e.equalBase(r))throw Error("Cannot compare units with different base");return e.value==r.value}if(y(e)||y(r))return e==r;if(e instanceof Array||e instanceof t||e instanceof w||r instanceof Array||r instanceof t||r instanceof w)return K.map2(e,r,Z.equal);if(e.valueOf()!==e||r.valueOf()!==r)return $(e.valueOf(),r.valueOf());throw O("equal",e,r)},Z.exp=function(e){if(1!=arguments.length)throw x("exp",arguments.length,1);if(v(e))return Math.exp(e);if(e instanceof n){var r=Math.exp(e.re);return new n(r*Math.cos(e.im),r*Math.sin(e.im))}if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.exp);if(e.valueOf()!==e)return Z.exp(e.valueOf());throw O("exp",e)},Z.fix=function(e){if(1!=arguments.length)throw x("fix",arguments.length,1);if(v(e))return e>0?Math.floor(e):Math.ceil(e);if(e instanceof n)return new n(e.re>0?Math.floor(e.re):Math.ceil(e.re),e.im>0?Math.floor(e.im):Math.ceil(e.im));if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.fix);if(e.valueOf()!==e)return Z.fix(e.valueOf());throw O("fix",e)},Z.floor=function(e){if(1!=arguments.length)throw x("floor",arguments.length,1);if(v(e))return Math.floor(e);if(e instanceof n)return new n(Math.floor(e.re),Math.floor(e.im));if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.floor);if(e.valueOf()!==e)return Z.floor(e.valueOf());throw O("floor",e)},Z.gcd=function(){var e,n=arguments[0],r=arguments[1];if(2==arguments.length){if(v(n)&&v(r)){if(!g(n)||!g(r))throw Error("Parameters in function gcd must be integer numbers");for(;0!=r;)e=r,r=n%e,n=e;return Math.abs(n)}if(n instanceof Array||n instanceof t||r instanceof Array||r instanceof t)return K.map2(n,r,Z.gcd);if(n.valueOf()!==n||r.valueOf()!==r)return Z.gcd(n.valueOf(),r.valueOf());throw O("gcd",n,r)}if(arguments.length>2){for(var i=1;arguments.length>i;i++)n=Z.gcd(n,arguments[i]);return n}throw new SyntaxError("Function gcd expects two or more arguments")},Z.larger=function(e,r){if(2!=arguments.length)throw x("larger",arguments.length,2);if(v(e)){if(v(r))return e>r;if(r instanceof n)return e>Z.abs(r)}if(e instanceof n){if(v(r))return Z.abs(e)>r;if(r instanceof n)return Z.abs(e)>Z.abs(r)}if(e instanceof E&&r instanceof E){if(!e.equalBase(r))throw Error("Cannot compare units with different base");return e.value>r.value}if(y(e)||y(r))return e>r;if(e instanceof Array||e instanceof t||e instanceof w||r instanceof Array||r instanceof t||r instanceof w)return K.map2(e,r,Z.larger);if(e.valueOf()!==e||r.valueOf()!==r)return Z.larger(e.valueOf(),r.valueOf());throw O("larger",e,r)},Z.largereq=function(e,r){if(2!=arguments.length)throw x("largereq",arguments.length,2);if(v(e)){if(v(r))return e>=r;if(r instanceof n)return e>=Z.abs(r)}if(e instanceof n){if(v(r))return Z.abs(e)>=r;if(r instanceof n)return Z.abs(e)>=Z.abs(r)}if(e instanceof E&&r instanceof E){if(!e.equalBase(r))throw Error("Cannot compare units with different base");return e.value>=r.value}if(y(e)||y(r))return e>=r;if(e instanceof Array||e instanceof t||e instanceof w||r instanceof Array||r instanceof t||r instanceof w)return K.map2(e,r,Z.largereq);if(e.valueOf()!==e||r.valueOf()!==r)return Z.largereq(e.valueOf(),r.valueOf());throw O("largereq",e,r)},Z.lcm=function(){var e,n=arguments[0],r=arguments[1];if(2==arguments.length){if(v(n)&&v(r)){if(!g(n)||!g(r))throw Error("Parameters in function lcm must be integer numbers");for(var i=n*r;0!=r;)e=r,r=n%e,n=e;return Math.abs(i/n)}if(n instanceof Array||n instanceof t||r instanceof Array||r instanceof t)return K.map2(n,r,Z.lcm);if(n.valueOf()!==n||r.valueOf()!==r)return Z.lcm(n.valueOf(),r.valueOf());throw O("lcm",n,r)}if(arguments.length>2){for(var a=1;arguments.length>a;a++)n=Z.lcm(n,arguments[a]);return n}throw new SyntaxError("Function lcm expects two or more arguments")},Z.log=function(e,r){if(1!=arguments.length&&2!=arguments.length)throw x("log",arguments.length,1,2);if(void 0!==r)return Z.divide(Z.log(e),Z.log(r));if(v(e))return e>=0?Math.log(e):Z.log(new n(e,0));if(e instanceof n)return new n(Math.log(Math.sqrt(e.re*e.re+e.im*e.im)),Math.atan2(e.im,e.re));if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.log);if(e.valueOf()!==e||r.valueOf()!==r)return Z.log(e.valueOf(),r.valueOf());throw O("log",e,r)},Z.log10=function(e){if(1!=arguments.length)throw x("log10",arguments.length,1);if(v(e))return e>=0?Math.log(e)/Math.LN10:Z.log10(new n(e,0));if(e instanceof n)return new n(Math.log(Math.sqrt(e.re*e.re+e.im*e.im))/Math.LN10,Math.atan2(e.im,e.re)/Math.LN10);if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.log10);if(e.valueOf()!==e)return Z.log10(e.valueOf());throw O("log10",e)},Z.mod=function(e,r){if(2!=arguments.length)throw x("mod",arguments.length,2);if(v(e)){if(v(r))return e%r;if(r instanceof n&&0==r.im)return e%r.re}else if(e instanceof n&&0==e.im){if(v(r))return e.re%r;if(r instanceof n&&0==r.im)return e.re%r.re}if(e instanceof Array||e instanceof t||e instanceof w||r instanceof Array||r instanceof t||r instanceof w)return K.map2(e,r,Z.mod);if(e.valueOf()!==e||r.valueOf()!==r)return Z.mod(e.valueOf(),r.valueOf());throw O("mod",e,r)},Z.multiply=function(e,r){if(2!=arguments.length)throw x("multiply",arguments.length,2);if(v(e)){if(v(r))return e*r;if(r instanceof n)return M(new n(e,0),r);if(r instanceof E)return o=r.clone(),o.value*=e,o}else if(e instanceof n){if(v(r))return M(e,new n(r,0));if(r instanceof n)return M(e,r)}else if(e instanceof E){if(v(r))return o=e.clone(),o.value*=r,o}else{if(e instanceof Array){if(r instanceof Array){var i=K.size(e),a=K.size(r);if(2!=i.length)throw Error("Can only multiply a 2 dimensional matrix (A has "+i.length+" dimensions)");if(2!=a.length)throw Error("Can only multiply a 2 dimensional matrix (B has "+a.length+" dimensions)");if(i[1]!=a[0])throw new RangeError("Dimensions mismatch in multiplication. Columns of A must match rows of B (A is "+i[0]+"x"+i[1]+", B is "+a[0]+"x"+a[1]+", "+a[1]+" != "+a[0]+")");for(var o=[],f=i[0],s=a[1],u=i[1],c=Z.multiply,l=Z.add,h=0;f>h;h++){o[h]=[];for(var m=0;s>m;m++){for(var p=null,g=0;u>g;g++){var w=c(e[h][g],r[g][m]);p=null==p?w:l(p,w)}o[h][m]=p}}return o}return r instanceof t?new t(Z.multiply(e.valueOf(),r.valueOf())):K.map2(e,r,Z.multiply)}if(e instanceof t)return new t(Z.multiply(e.valueOf(),r.valueOf()))}if(r instanceof Array)return K.map2(e,r,Z.multiply);if(r instanceof t)return new t(Z.multiply(e.valueOf(),r.valueOf()));if(e.valueOf()!==e||r.valueOf()!==r)return Z.multiply(e.valueOf(),r.valueOf());throw O("multiply",e,r)},Z.pow=function(e,r){if(2!=arguments.length)throw x("pow",arguments.length,2);if(v(e)){if(v(r))return g(r)||e>=0?Math.pow(e,r):A(new n(e,0),new n(r,0));if(r instanceof n)return A(new n(e,0),r)}else if(e instanceof n){if(v(r))return A(e,new n(r,0));if(r instanceof n)return A(e,r)}else{if(e instanceof Array){if(!v(r)||!g(r)||0>r)throw new TypeError("For A^b, b must be a positive integer (value is "+r+")");var i=K.size(e);if(2!=i.length)throw Error("For A^b, A must be 2 dimensional (A has "+i.length+" dimensions)");if(i[0]!=i[1])throw Error("For A^b, A must be square (size is "+i[0]+"x"+i[1]+")");if(0==r)return Z.eye(i[0]);for(var a=e,o=1;r>o;o++)a=Z.multiply(e,a);return a}if(e instanceof t)return new t(Z.pow(e.valueOf(),r))}if(e.valueOf()!==e||r.valueOf()!==r)return Z.pow(e.valueOf(),r.valueOf());throw O("pow",e,r)},Z.round=function(e,r){if(1!=arguments.length&&2!=arguments.length)throw x("round",arguments.length,1,2);if(void 0==r){if(v(e))return Math.round(e);if(e instanceof n)return new n(Math.round(e.re),Math.round(e.im));if((e instanceof Array||e instanceof t||e instanceof w)&&K.map(e,Z.round),e.valueOf()!==e)return Z.round(e.valueOf());throw O("round",e)}if(!v(r))throw new TypeError("Number of digits in function round must be an integer");if(r!==Math.round(r))throw new TypeError("Number of digits in function round must be integer");if(0>r||r>9)throw Error("Number of digits in function round must be in te range of 0-9");if(v(e))return S(e,r);if(e instanceof n)return new n(S(e.re,r),S(e.im,r));if(e instanceof Array||e instanceof t||e instanceof w||r instanceof Array||r instanceof t||r instanceof w)return K.map2(e,r,Z.round);if(e.valueOf()!==e||r.valueOf()!==r)return Z.round(e.valueOf(),r.valueOf());throw O("round",e,r)},Z.sign=function(e){if(1!=arguments.length)throw x("sign",arguments.length,1);if(v(e)){var r;return r=e>0?1:0>e?-1:0}if(e instanceof n){var i=Math.sqrt(e.re*e.re+e.im*e.im);return new n(e.re/i,e.im/i)}if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.sign);if(e.valueOf()!==e)return Z.sign(e.valueOf());throw O("sign",e)},Z.smaller=function(e,r){if(2!=arguments.length)throw x("smaller",arguments.length,2);if(v(e)){if(v(r))return r>e;if(r instanceof n)return Z.abs(r)>e}if(e instanceof n){if(v(r))return r>Z.abs(e);if(r instanceof n)return Z.abs(e)e;if(e instanceof Array||e instanceof t||e instanceof w||r instanceof Array||r instanceof t||r instanceof w)return K.map2(e,r,Z.smaller);if(e.valueOf()!==e||r.valueOf()!==r)return Z.smaller(e.valueOf(),r.valueOf());throw O("smaller",e,r)},Z.smallereq=function(e,r){if(2!=arguments.length)throw x("smallereq",arguments.length,2);if(v(e)){if(v(r))return r>=e;if(r instanceof n)return Z.abs(r)>=e}if(e instanceof n){if(v(r))return r>=Z.abs(e);if(r instanceof n)return Z.abs(e)<=Z.abs(r)}if(e instanceof E&&r instanceof E){if(!e.equalBase(r))throw Error("Cannot compare units with different base");return e.value<=r.value}if(y(e)||y(r))return r>=e;if(e instanceof Array||e instanceof t||e instanceof w||r instanceof Array||r instanceof t||r instanceof w)return K.map2(e,r,Z.smallereq);if(e.valueOf()!==e||r.valueOf()!==r)return Z.smallereq(e.valueOf(),r.valueOf());throw O("smallereq",e,r)},Z.sqrt=function(e){if(1!=arguments.length)throw x("sqrt",arguments.length,1);if(v(e))return e>=0?Math.sqrt(e):Z.sqrt(new n(e,0));if(e instanceof n){var r=Math.sqrt(e.re*e.re+e.im*e.im);return e.im>=0?new n(.5*Math.sqrt(2*(r+e.re)),.5*Math.sqrt(2*(r-e.re))):new n(.5*Math.sqrt(2*(r+e.re)),-.5*Math.sqrt(2*(r-e.re)))}if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.sqrt);if(e.valueOf()!==e)return Z.sqrt(e.valueOf());throw O("sqrt",e)},Z.square=function(e){if(1!=arguments.length)throw x("square",arguments.length,1);if(v(e))return e*e;if(e instanceof n)return Z.multiply(e,e);if(e instanceof Array||e instanceof t||e instanceof w)return Z.multiply(e,e);if(e.valueOf()!==e)return Z.square(e.valueOf());throw O("square",e)},Z.subtract=function(e,r){if(2!=arguments.length)throw x("subtract",arguments.length,2);if(v(e)){if(v(r))return e-r;if(r instanceof n)return new n(e-r.re,r.im)}else if(e instanceof n){if(v(r))return new n(e.re-r,e.im);if(r instanceof n)return new n(e.re-r.re,e.im-r.im)}else if(e instanceof E&&r instanceof E){if(!e.equalBase(r))throw Error("Units do not match");if(!e.hasValue)throw Error("Unit on left hand side of operator - has no value");if(!r.hasValue)throw Error("Unit on right hand side of operator - has no value");var i=e.clone();return i.value-=r.value,i.fixPrefix=!1,i}if(e instanceof Array||e instanceof t||e instanceof w||r instanceof Array||r instanceof t||r instanceof w)return K.map2(e,r,Z.subtract);if(e.valueOf()!==e||r.valueOf()!==r)return Z.subtract(e.valueOf(),r.valueOf());throw O("subtract",e,r)},Z.unaryminus=function(e){if(1!=arguments.length)throw x("unaryminus",arguments.length,1);if(v(e))return-e;if(e instanceof n)return new n(-e.re,-e.im);if(e instanceof E){var r=e.clone();return r.value=-e.value,r}if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.unaryminus);if(e.valueOf()!==e)return Z.unaryminus(e.valueOf());throw O("unaryminus",e)},Z.unequal=function(e,r){if(2!=arguments.length)throw x("unequal",arguments.length,2);if(v(e)){if(v(r))return e==r;if(r instanceof n)return e==r.re&&0==r.im}if(e instanceof n){if(v(r))return e.re==r&&0==e.im;if(r instanceof n)return e.re==r.re&&e.im==r.im}if(e instanceof E&&r instanceof E){if(!e.equalBase(r))throw Error("Cannot compare units with different base");return e.value==r.value}if(y(e)||y(r))return e==r;if(e instanceof Array||e instanceof t||e instanceof w||r instanceof Array||r instanceof t||r instanceof w)return K.map2(e,r,Z.unequal);if(e.valueOf()!==e||r.valueOf()!==r)return Z.unequal(e.valueOf(),r.valueOf());throw O("unequal",e,r)},Z.arg=function(e){if(1!=arguments.length)throw x("arg",arguments.length,1);if(v(e))return Math.atan2(0,e);if(e instanceof n)return Math.atan2(e.im,e.re);if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.arg);if(e.valueOf()!==e)return Z.arg(e.valueOf());throw O("arg",e)},Z.conj=function(e){if(1!=arguments.length)throw x("conj",arguments.length,1);if(v(e))return e;if(e instanceof n)return new n(e.re,-e.im);if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.conj);if(e.valueOf()!==e)return Z.conj(e.valueOf());throw O("conj",e)},Z.im=function(e){if(1!=arguments.length)throw x("im",arguments.length,1);if(v(e))return 0;if(e instanceof n)return e.im;if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.im);if(e.valueOf()!==e)return Z.im(e.valueOf());throw O("im",e)},Z.re=function(e){if(1!=arguments.length)throw x("re",arguments.length,1);if(v(e))return e;if(e instanceof n)return e.re;if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.re);if(e.valueOf()!==e)return Z.re(e.valueOf());throw O("re",e)},Z.complex=function(){switch(arguments.length){case 0:return new n(0,0);case 1:var e=arguments[0];if(!y(e))throw new TypeError("Two numbers or a single string expected in function complex");var t=n.parse(e);if(t)return t;throw new SyntaxError('String "'+e+'" is no valid complex number');case 2:return new n(arguments[0],arguments[1]);default:throw x("complex",arguments.length,0,2)}},Z.matrix=function(e){if(arguments.length>1)throw x("matrix",arguments.length,0,1);return new t(e)},Z.parser=function(){return new Z.expr.Parser},Z.range=function(e){switch(arguments.length){case 1:if(!y(e))throw new TypeError("Two or three numbers or a single string expected in function range");var n=w.parse(e);if(n)return n;throw new SyntaxError('String "'+n+'" is no valid range');case 2:return new w(arguments[0],null,arguments[1]);case 3:return new w(arguments[0],arguments[1],arguments[2]);default:throw x("range",arguments.length,2,3)}},Z.unit=function(){switch(arguments.length){case 1:var e=arguments[0];if(!y(e))throw new TypeError("A string or a number and string expected in function unit");if(E.isPlainUnit(e))return new E(null,e);var n=E.parse(e);if(n)return n;throw new SyntaxError('String "'+e+'" is no valid unit');case 2:return new E(arguments[0],arguments[1]);default:throw x("unit",arguments.length,1,2)}},Z.workspace=function(){return new Z.expr.Workspace},Z.concat=function(){var e,n,r=arguments.length,i=-1,a=!1,o=[];for(e=0;r>e;e++){var f=arguments[e];if(f instanceof t&&(a=!0),e==r-1&&v(f)){if(n=i,i=f,!g(i)||1>i)throw new TypeError("Dimension number must be a positive integer (dim = "+i+")");if(e>0&&i>n)throw new RangeError("Dimension out of range ("+i+" > "+n+")")}else{if(!(f instanceof Array||f instanceof t))throw O("concat",f);var s=Z.clone(f.valueOf()),u=Z.size(f);if(o[e]=s,n=i,i=u.length,e>0&&i!=n)throw new RangeError("Dimension mismatch ("+n+" != "+i+")")}}if(0==o.length)throw new SyntaxError("At least one matrix expected");for(var c=o.shift();o.length;)c=T(c,o.shift(),i-1,0);return a?new t(c):c},Z.det=function(e){if(1!=arguments.length)throw x("det",arguments.length,1);var n=Z.size(e);switch(n.length){case 0:return Z.clone(e);case 1:if(1==n[0])return Z.clone(e.valueOf()[0]);throw new RangeError("Matrix must be square (size: "+Z.format(n)+")");case 2:var t=n[0],r=n[1];if(t==r)return U(e.valueOf(),t,r);throw new RangeError("Matrix must be square (size: "+Z.format(n)+")");default:throw new RangeError("Matrix must be two dimensional (size: "+Z.format(n)+")")}},Z.diag=function(e,n){var r,i,a,o;if(1!=arguments.length&&2!=arguments.length)throw x("diag",arguments.length,1,2);if(n){if(!v(n)||!g(n))throw new TypeError("Second parameter in function diag must be an integer")}else n=0;var f=n>0?n:0,s=0>n?-n:0;e instanceof t||e instanceof w||(e=new t(e));var u;switch(e.isVector()?(e=e.toVector(),u=[e.length]):u=e.size(),u.length){case 1:i=e.valueOf();var c=new t;for(c.resize([i.length+s,i.length+f]),r=c.valueOf(),o=i.length,a=0;o>a;a++)r[a+s][a+f]=Z.clone(i[a]);return c;case 2:for(i=[],r=e.valueOf(),o=Math.min(u[0]-s,u[1]-f),a=0;o>a;a++)i[a]=Z.clone(r[a+s][a+f]);return new t(i);default:throw new RangeError("Matrix for function diag must be 2 dimensional")}},Z.eye=function(){var e=K.argsToArray(arguments);if(0==e.length)e=[1,1];else if(1==e.length)e[1]=e[0];else if(e.length>2)throw x("eye",e.length,0,2);var n=e[0],r=e[1];if(!v(n)||!g(n)||1>n)throw Error("Parameters in function eye must be positive integers");if(r&&(!v(r)||!g(r)||1>r))throw Error("Parameters in function eye must be positive integers");var i=new t;i.resize(e);for(var a=Z.min(e),o=i.valueOf(),f=0;a>f;f++)o[f][f]=1;return i},Z.inv=function(e){if(1!=arguments.length)throw x("inv",arguments.length,1);var n=Z.size(e);switch(n.length){case 0:return Z.divide(1,e);case 1:if(1==n[0])return e instanceof t?new t([Z.divide(1,e.valueOf()[0])]):[Z.divide(1,e[0])];throw new RangeError("Matrix must be square (size: "+Z.format(n)+")");case 2:var r=n[0],i=n[1];if(r==i)return e instanceof t?new t(R(e.valueOf(),r,i)):R(e,r,i);throw new RangeError("Matrix must be square (size: "+Z.format(n)+")");default:throw new RangeError("Matrix must be two dimensional (size: "+Z.format(n)+")")}},Z.ones=function(){var e=K.argsToArray(arguments);0==e.length?e=[1,1]:1==e.length&&(e[1]=e[0]);var n=new t,r=1;return n.resize(e,r),n},Z.size=function(e){if(1!=arguments.length)throw x("size",arguments.length,1);if(v(e)||e instanceof n||e instanceof E||null==e)return[];if(y(e))return[e.length];if(e instanceof Array)return K.size(e);if(e instanceof t||e instanceof w)return e.size();if(e.valueOf()!==e)return Z.size(e.valueOf());throw O("size",e)},Z.squeeze=function(e){if(1!=arguments.length)throw x("squeeze",arguments.length,1);return e instanceof t||e instanceof w?_(e.toArray()):e instanceof Array?_(Z.clone(e)):Z.clone(e)},Z.transpose=function(e){if(1!=arguments.length)throw x("transpose",arguments.length,1);var n=Z.size(e);switch(n.length){case 0:return Z.clone(e);case 1:return Z.clone(e);case 2:for(var r,i=n[1],a=n[0],o=e instanceof t,f=e.valueOf(),s=[],u=Z.clone,c=0;i>c;c++){r=s[c]=[];for(var l=0;a>l;l++)r[l]=u(f[l][c])}return 0==a&&(s[0]=[]),o?new t(s):s;default:throw new RangeError("Matrix must be two dimensional (size: "+Z.format(n)+")")}},Z.zeros=function(){var e=K.argsToArray(arguments);0==e.length?e=[1,1]:1==e.length&&(e[1]=e[0]);var n=new t;return n.resize(e),n},Z.factorial=function(e){if(1!=arguments.length)throw x("factorial",arguments.length,1);if(v(e)){if(!g(e))throw new TypeError("Function factorial can only handle integer values");var n=e,r=n;for(n--;n>1;)r*=n,n--;return 0==r&&(r=1),r}if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.factorial);if(e.valueOf()!==e)return Z.factorial(e.valueOf());throw O("factorial",e)},Z.random=function(){if(0!=arguments.length)throw x("random",arguments.length,0);return Math.random()},Z.max=function(e){if(0==arguments.length)throw Error("Function max requires one or more parameters (0 provided)");if(e instanceof Array||e instanceof t||e instanceof w){if(arguments.length>1)throw Error("Wrong number of parameters (1 matrix or multiple scalars expected)");var n=Z.size(e);if(1==n.length){if(0==e.length)throw Error("Cannot calculate max of an empty vector");return z(e.valueOf())}if(2==n.length){if(0==n[0]||0==n[1])throw Error("Cannot calculate max of an empty matrix");if(e instanceof Array)return q(e,n[0],n[1]);if(e instanceof t||e instanceof w)return new t(q(e.valueOf(),n[0],n[1]));throw O("max",e)}throw new RangeError("Cannot calculate max for multi dimensional matrix")}return z(arguments)},Z.min=function(e){if(0==arguments.length)throw Error("Function min requires one or more parameters (0 provided)");if(e instanceof Array||e instanceof t||e instanceof w){if(arguments.length>1)throw Error("Wrong number of parameters (1 matrix or multiple scalars expected)");var n=Z.size(e);if(1==n.length){if(0==e.length)throw Error("Cannot calculate min of an empty vector");return I(e.valueOf())}if(2==n.length){if(0==n[0]||0==n[1])throw Error("Cannot calculate min of an empty matrix");if(e instanceof Array)return P(e,n[0],n[1]);if(e instanceof t||e instanceof w)return new t(P(e.valueOf(),n[0],n[1]));throw O("min",e)}throw new RangeError("Cannot calculate min for multi dimensional matrix")}return I(arguments)},Z.acos=function(e){if(1!=arguments.length)throw x("acos",arguments.length,1);if(v(e))return e>=-1&&1>=e?Math.acos(e):Z.acos(new n(e,0));if(e instanceof n){var r=new n(e.im*e.im-e.re*e.re+1,-2*e.re*e.im),i=Z.sqrt(r),a=new n(i.re-e.im,i.im+e.re),o=Z.log(a);return new n(1.5707963267948966-o.im,o.re)}if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.acos);if(e.valueOf()!==e)return Z.acos(e.valueOf());throw O("acos",e)},Z.asin=function(e){if(1!=arguments.length)throw x("asin",arguments.length,1);if(v(e))return e>=-1&&1>=e?Math.asin(e):Z.asin(new n(e,0));if(e instanceof n){var r=e.re,i=e.im,a=new n(i*i-r*r+1,-2*r*i),o=Z.sqrt(a),f=new n(o.re-i,o.im+r),s=Z.log(f);return new n(s.im,-s.re)}if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.asin);if(e.valueOf()!==e)return Z.asin(e.valueOf());throw O("asin",e)},Z.atan=function(e){if(1!=arguments.length)throw x("atan",arguments.length,1);if(v(e))return Math.atan(e);if(e instanceof n){var r=e.re,i=e.im,a=r*r+(1-i)*(1-i),o=new n((1-i*i-r*r)/a,-2*r/a),f=Z.log(o);return new n(-.5*f.im,.5*f.re)}if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.atan);if(e.valueOf()!==e)return Z.atan(e.valueOf());throw O("atan",e)},Z.atan2=function(e,r){if(2!=arguments.length)throw x("atan2",arguments.length,2);if(v(e)){if(v(r))return Math.atan2(e,r);if(r instanceof n)return Math.atan2(e,r.re)}else if(e instanceof n){if(v(r))return Math.atan2(e.re,r);if(r instanceof n)return Math.atan2(e.re,r.re)}if(e instanceof Array||e instanceof t||e instanceof w||r instanceof Array||r instanceof t||r instanceof w)return K.map2(e,r,Z.atan2);if(r.valueOf()!==r||e.valueOf()!==e)return Z.atan2(e.valueOf(),r.valueOf());throw O("atan2",e,r)},Z.cos=function(e){if(1!=arguments.length)throw x("cos",arguments.length,1);if(v(e))return Math.cos(e);if(e instanceof n)return new n(.5*Math.cos(e.re)*(Math.exp(-e.im)+Math.exp(e.im)),.5*Math.sin(e.re)*(Math.exp(-e.im)-Math.exp(e.im)));if(e instanceof E){if(!e.hasBase(E.BASE_UNITS.ANGLE))throw new TypeError("Unit in function cos is no angle");return Math.cos(e.value)}if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.cos);if(e.valueOf()!==e)return Z.cos(e.valueOf());throw O("cos",e)},Z.cot=function(e){if(1!=arguments.length)throw x("cot",arguments.length,1);if(v(e))return 1/Math.tan(e);if(e instanceof n){var r=Math.exp(-4*e.im)-2*Math.exp(-2*e.im)*Math.cos(2*e.re)+1;return new n(2*Math.exp(-2*e.im)*Math.sin(2*e.re)/r,(Math.exp(-4*e.im)-1)/r)}if(e instanceof E){if(!e.hasBase(E.BASE_UNITS.ANGLE))throw new TypeError("Unit in function cot is no angle");return 1/Math.tan(e.value)}if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.cot);if(e.valueOf()!==e)return Z.cot(e.valueOf());throw O("cot",e)},Z.csc=function(e){if(1!=arguments.length)throw x("csc",arguments.length,1);if(v(e))return 1/Math.sin(e);if(e instanceof n){var r=.25*(Math.exp(-2*e.im)+Math.exp(2*e.im))-.5*Math.cos(2*e.re);return new n(.5*Math.sin(e.re)*(Math.exp(-e.im)+Math.exp(e.im))/r,.5*Math.cos(e.re)*(Math.exp(-e.im)-Math.exp(e.im))/r)}if(e instanceof E){if(!e.hasBase(E.BASE_UNITS.ANGLE))throw new TypeError("Unit in function csc is no angle");return 1/Math.sin(e.value)}if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.csc);if(e.valueOf()!==e)return Z.csc(e.valueOf());throw O("csc",e)},Z.sec=function(e){if(1!=arguments.length)throw x("sec",arguments.length,1);if(v(e))return 1/Math.cos(e);if(e instanceof n){var r=.25*(Math.exp(-2*e.im)+Math.exp(2*e.im))+.5*Math.cos(2*e.re);return new n(.5*Math.cos(e.re)*(Math.exp(-e.im)+Math.exp(e.im))/r,.5*Math.sin(e.re)*(Math.exp(e.im)-Math.exp(-e.im))/r)}if(e instanceof E){if(!e.hasBase(E.BASE_UNITS.ANGLE))throw new TypeError("Unit in function sec is no angle");return 1/Math.cos(e.value)}if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.sec);if(e.valueOf()!==e)return Z.sec(e.valueOf());throw O("sec",e)},Z.sin=function(e){if(1!=arguments.length)throw x("sin",arguments.length,1);if(v(e))return Math.sin(e);if(e instanceof n)return new n(.5*Math.sin(e.re)*(Math.exp(-e.im)+Math.exp(e.im)),.5*Math.cos(e.re)*(Math.exp(e.im)-Math.exp(-e.im)));if(e instanceof E){if(!e.hasBase(E.BASE_UNITS.ANGLE))throw new TypeError("Unit in function cos is no angle");return Math.sin(e.value)}if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.sin);if(e.valueOf()!==e)return Z.sin(e.valueOf());throw O("sin",e)},Z.tan=function(e){if(1!=arguments.length)throw x("tan",arguments.length,1);if(v(e))return Math.tan(e);if(e instanceof n){var r=Math.exp(-4*e.im)+2*Math.exp(-2*e.im)*Math.cos(2*e.re)+1;return new n(2*Math.exp(-2*e.im)*Math.sin(2*e.re)/r,(1-Math.exp(-4*e.im))/r)}if(e instanceof E){if(!e.hasBase(E.BASE_UNITS.ANGLE))throw new TypeError("Unit in function tan is no angle");return Math.tan(e.value)}if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.tan);if(e.valueOf()!==e)return Z.tan(e.valueOf());throw O("tan",e)},Z["in"]=function(e,n){if(2!=arguments.length)throw x("in",arguments.length,2);if(e instanceof E&&(n instanceof E||y(n)))return e.in(n);if(e instanceof Array||e instanceof t||e instanceof w||n instanceof Array||n instanceof t||n instanceof w)return K.map2(e,n,Z["in"]);if(e.valueOf()!==e)return Z["in"](e.valueOf());throw O("in",e,n)},Z.clone=function(n){if(1!=arguments.length)throw x("clone",arguments.length,1);if(null==n)return n;if("function"==typeof n.clone)return n.clone();if(v(n)||y(n)||e(n))return n;if(n instanceof Array){var t=Z.clone;return n.map(function(e){return t(e)})}if(n instanceof Object)return K.mapObject(n,Z.clone);throw O("clone",n)},Z.format=function(e,n){var t=arguments.length;if(1!=t&&2!=t)throw x("format",t,1,2);if(1==t){var r=arguments[0];return v(r)?K.formatNumber(r):r instanceof Array?K.formatArray(r):y(r)?'"'+r+'"':r instanceof Object?""+r:r+""}if(!y(e))throw new TypeError("String expected as first parameter in function format");if(!(n instanceof Object))throw new TypeError("Object expected as first parameter in function format");return e.replace(/\$([\w\.]+)/g,function(e,t){for(var r=t.split("."),i=n[r.shift()];r.length&&void 0!=i;){var a=r.shift();i=a?i[a]:i+"."}return void 0!=i?i:e})},Z["import"]=function(e,n){var t;if(y(e)){if("undefined"==typeof require)throw Error("Cannot load file: require not available.");var r=require(e);Z["import"](r)}else if(C(e)){if(t=e.name,!t)throw Error("Cannot import an unnamed function or object");(n||void 0===Z[t])&&B(t,e)}else if(e instanceof Object)for(t in e)if(e.hasOwnProperty(t)){var i=e[t];C(i)?(n||void 0===Z[t])&&B(t,i):Z["import"](i)}},Z.select=function(e){return new Z.type.Selector(e)},Z["typeof"]=function(e){if(1!=arguments.length)throw x("typeof",arguments.length,1);var n,t=typeof e;if("object"==t){if(null==e)return"null";if(e.constructor){for(n in Z)if(Z.hasOwnProperty(n)&&e.constructor==Z[n])return n.toLowerCase();for(n in Z.type)if(Z.type.hasOwnProperty(n)&&e.constructor==Z.type[n])return n.toLowerCase();if(e.constructor.name)return e.constructor.name.toLowerCase()}}return t},Z.expr.node.Node=G,G.prototype.eval=function(){throw Error("Cannot evaluate a Node interface")},G.prototype.toString=function(){return""},V.prototype=new G,Z.expr.node.Symbol=V,V.prototype.hasParams=function(){return void 0!=this.params&&this.params.length>0},V.prototype.eval=function(){var e=this.fn;if(void 0===e)throw Error("Undefined symbol "+this.name);var n=this.params.map(function(e){return e.eval()});return e.apply(this,n)},V.prototype.toString=function(){if(this.name&&!this.params)return this.name;var e=this.name;return this.params&&this.params.length&&(e+="("+this.params.join(", ")+")"),e},D.prototype=new G,Z.expr.node.Constant=D,D.prototype.eval=function(){return this.value},D.prototype.toString=function(){return this.value?Z.format(this.value):""},k.prototype=new G,Z.expr.node.MatrixNode=k,function(){function e(n){return n.map(function(n){return n instanceof Array?e(n):n.eval()})}function n(e){for(var n=[],r=e.length,i=0;r>i;i++){for(var a=e[i],o=a.length,f=null,s=null,u=0;o>u;u++){var c,l=Z.clone(a[u]);if(l instanceof t){if(c=l.size(),l=l.valueOf(),1==c.length)l=[l],c=[1,c[0]];else if(c.length>2)throw Error("Cannot merge a multi dimensional matrix")}else l instanceof w?(l=[l.valueOf()],c=[1,l[0].length]):(c=[1,1],l=[[l]]);if(null==f)f=l,s=c[0];else{if(c[0]!=s)throw Error("Dimension mismatch ("+c[0]+" != "+s+")");for(var h=0;s>h;h++)f[h]=f[h].concat(l[h])}}n=n.concat(f)}return n}function r(e){return e.some(function(e){return e instanceof t||e instanceof w?!0:e instanceof Array?r(e):!1})}k.prototype.eval=function(){var i=e(this.nodes); -return r(i)&&(i=n(i)),new t(i)},k.prototype.toString=function(){return K.formatArray(this.nodes)}}(),F.prototype=new G,Z.expr.node.Block=F,F.prototype.add=function(e,n){var t=this.params.length;this.params[t]=e,this.visible[t]=void 0!=n?n:!0},F.prototype.eval=function(){for(var e=[],n=0,t=this.params.length;t>n;n++){var r=this.params[n].eval();this.visible[n]&&e.push(r)}return e},F.prototype.toString=function(){for(var e=[],n=0,t=this.params.length;t>n;n++)this.visible[n]&&e.push("\n "+(""+this.params[n]));return"["+e.join(",")+"\n]"},j.prototype=new G,Z.expr.node.Assignment=j,j.prototype.eval=function(){if(void 0===this.expr)throw Error("Undefined symbol "+this.name);var e,n=this.params;if(n&&n.length){var t=[];this.params.forEach(function(e){t.push(e.eval())});var r=this.expr.eval();if(void 0==this.result.value)throw Error("Undefined symbol "+this.name);var i=this.result();if(!i.set)throw new TypeError("Cannot apply a subset to object of type "+Z.typeof(i));e=i.set(t,r),this.result.value=e}else e=this.expr.eval(),this.result.value=e;return e},j.prototype.toString=function(){var e="";return e+=this.name,this.params&&this.params.length&&(e+="("+this.params.join(", ")+")"),e+=" = ",e+=""+this.expr},H.prototype=new G,Z.expr.node.Arguments=H,H.prototype.eval=function(){var e=this.object;if(void 0==e)throw Error("Node undefined");for(var n=e.eval(),t=this.params,r=[],i=0,a=t.length;a>i;i++)r[i]=t[i].eval();if(!n.get)throw new TypeError("Cannot apply arguments to object of type "+Z.typeof(n));return n.get(r)},H.prototype.toString=function(){var e=this.object?""+this.object:"";return this.params&&(e+="("+this.params.join(", ")+")"),e},Y.prototype=new G,Z.expr.node.FunctionAssignment=Y,Y.prototype.createFunction=function(e,n,t,r){var i=function(){var n=t?t.length:0,i=arguments?arguments.length:0;if(n!=i)throw x(e,i,n);if(n>0)for(var a=0;n>a;a++)t[a].value=arguments[a];return r.eval()};return i.toString=function(){return e+"("+n.join(", ")+")"},i},Y.prototype.eval=function(){for(var e=this.variables,n=this.values,t=0,r=e.length;r>t;t++)e[t].value=n[t];return this.result.value=this.def,this.def},Y.prototype.toString=function(){return""+this.def},Z.expr.Scope=function(e){this.parentScope=e,this.nestedScopes=void 0,this.symbols={},this.defs={},this.updates={},this.links={}},Z.expr.Scope.prototype={createNestedScope:function(){var e=new Z.expr.Scope(this);return this.nestedScopes||(this.nestedScopes=[]),this.nestedScopes.push(e),e},clear:function(){if(this.symbols={},this.defs={},this.links={},this.updates={},this.nestedScopes)for(var e=this.nestedScopes,n=0,t=e.length;t>n;n++)e[n].clear()},createSymbol:function(e){var n=this.symbols[e];if(!n){var t=this.findDef(e);n=this.newSymbol(e,t),this.symbols[e]=n}return n},newSymbol:function(e,n){var r=this,i=function(){var n,a;if(!i.value&&(i.value=r.findDef(e),!i.value))throw Error("Undefined symbol "+e);if("function"==typeof i.value)return i.value.apply(null,arguments);if(i.value instanceof t||i.value instanceof w||i.value instanceof Array){if(arguments.length){var o=i.value instanceof Array?new t(i.value):i.value;for(n=[],a=0;arguments.length>a;a++)n[a]=arguments[a];return o.get(n)}return i.value}return i.value};return i.value=n,i.toString=function(){return i.value?""+i.value:""},i},createLink:function(e){var n=this.links[e];return n||(n=this.createSymbol(e),this.links[e]=n),n},createDef:function(e,n){var t=this.defs[e];return t||(t=this.createSymbol(e),this.defs[e]=t),t&&void 0!=n&&(t.value=n),t},createUpdate:function(e){var n=this.updates[e];return n||(n=this.createLink(e),this.updates[e]=n),n},createConstant:function(e,n){var t=this.newSymbol(e,n);return this.symbols[e]=t,this.defs[e]=t,t},findDef:function(e){var n;if(n=this.defs[e])return n;if(n=this.updates[e])return n;if(this.parentScope)return this.parentScope.findDef(e);var t=Z[e];if(t)return this.createConstant(e,t);if(E.isPlainUnit(e)){var r=new E(null,e);return this.createConstant(e,r)}return void 0},removeLink:function(e){delete this.links[e]},removeDef:function(e){delete this.defs[e]},removeUpdate:function(e){delete this.updates[e]},init:function(){var e=this.symbols,n=this.parentScope;for(var t in e)if(e.hasOwnProperty(t)){var r=e[t];r.value=n?n.findDef(t):void 0}this.nestedScopes&&this.nestedScopes.forEach(function(e){e.init()})},hasLink:function(e){if(this.links[e])return!0;if(this.nestedScopes)for(var n=this.nestedScopes,t=0,r=n.length;r>t;t++)if(n[t].hasLink(e))return!0;return!1},hasDef:function(e){return void 0!=this.defs[e]},hasUpdate:function(e){return void 0!=this.updates[e]},getUndefinedSymbols:function(){var e=this.symbols,n=[];for(var t in e)if(e.hasOwnProperty(t)){var r=e[t];void 0==r.value&&n.push(r)}return this.nestedScopes&&this.nestedScopes.forEach(function(e){n=n.concat(e.getUndefinedSymbols())}),n}},function(){function e(){W++,K=H.charAt(W)}function t(){W=0,K=H.charAt(0)}function r(){for(Q=G.NULL,X="";" "==K||" "==K;)e();if("#"==K)for(;"\n"!=K&&""!=K;)e();if(""==K)return Q=G.DELIMITER,void 0;if("-"==K||","==K||"("==K||")"==K||"["==K||"]"==K||'"'==K||"\n"==K||";"==K||":"==K||"!"==K||"'"==K)return Q=G.DELIMITER,X+=K,e(),void 0;if(i(K))for(Q=G.DELIMITER;i(K);)X+=K,e();else if(o(K)){for(Q=G.NUMBER;o(K);)X+=K,e();if("E"==K||"e"==K)for(X+=K,e(),("+"==K||"-"==K)&&(X+=K,e()),f(K)||(Q=G.UNKNOWN);f(K);)X+=K,e()}else{if(!a(K)){for(Q=G.UNKNOWN;""!=K;)X+=K,e();throw I('Syntax error in part "'+X+'"')}for(Q=G.SYMBOL;a(K)||f(K);)X+=K,e()}}function i(e){return"&"==e||"|"==e||"<"==e||">"==e||"="==e||"+"==e||"/"==e||"*"==e||"%"==e||"^"==e||","==e||";"==e||"\n"==e||"!"==e||"'"==e}function a(e){return e>="a"&&"z">=e||e>="A"&&"Z">=e||"_"==e}function o(e){return e>="0"&&"9">=e||"."==e}function f(e){return e>="0"&&"9">=e}function s(e){t(),r();var n;if(n=""==X?new D(void 0):u(e),""!=X)throw Q==G.DELIMITER?B("Unknown operator "+X):I('Unexpected part "'+X+'"');return n}function u(e){var n,t,i;for("\n"!=X&&";"!=X&&""!=X&&(n=c(e));"\n"==X||";"==X;)t||(t=new F,n&&(i=";"!=X,t.add(n,i))),r(),"\n"!=X&&";"!=X&&""!=X&&(n=c(e),i=";"!=X,t.add(n,i));return t?t:(n||(n=c(e)),n)}function c(e){var n=l(e);if(!(n instanceof j)){var t="ans",r=void 0,i=e.createDef(t);return new j(t,r,n,i)}return n}function l(e){if(Q==G.SYMBOL&&"function"==X){if(r(),Q!=G.SYMBOL)throw I("Function name expected");var n=X;if(r(),"("!=X)throw I("Opening parenthesis ( expected");for(var t=e.createNestedScope(),i=[],a=[];;){if(r(),Q!=G.SYMBOL)throw I("Variable name expected");var o=X,f=t.createDef(o);if(i.push(o),a.push(f),r(),","!=X){if(")"==X)break;throw I('Comma , or closing parenthesis ) expected"')}}if(r(),"="!=X)throw I("Equal sign = expected");r();var s=m(t),u=e.createDef(n);return new Y(n,i,a,s,u)}return h(e)}function h(e){var n=!1;Q==G.SYMBOL&&(n=e.hasLink(X));var t=m(e);if("="==X){if(!(t instanceof V))throw I("Symbol expected at the left hand side of assignment operator =");var i=t.name,a=t.params;n||e.removeLink(i),r();var o=m(e),f=t.hasParams()?e.createUpdate(i):e.createDef(i);return new j(i,a,o,f)}return t}function m(e){var n=p(e);if(":"==X){for(var t=[n];":"==X;)r(),t.push(p(e));if(t.length>3)throw new TypeError("Invalid range");var i="range",a=Z.range;n=new V(i,a,t)}return n}function p(e){for(var n=v(e),t={"in":"in"};void 0!==t[X];){var i=X,a=Z[t[i]];r();var o=[n,v(e)];n=new V(i,a,o)}return n}function v(e){var n=g(e);return n}function g(e){for(var n=w(e),t={"==":"equal","!=":"unequal","<":"smaller",">":"larger","<=":"smallereq",">=":"largereq"};void 0!==t[X];){var i=X,a=Z[t[i]];r();var o=[n,w(e)];n=new V(i,a,o)}return n}function w(e){for(var n=d(e),t={"+":"add","-":"subtract"};void 0!==t[X];){var i=X,a=Z[t[i]];r();var o=[n,d(e)];n=new V(i,a,o)}return n}function d(e){for(var n=y(e),t={"*":"multiply","/":"divide","%":"mod",mod:"mod"};void 0!==t[X];){var i=X,a=Z[t[i]];r();var o=[n,y(e)];n=new V(i,a,o)}return n}function y(e){if("-"==X){var n=X,t=Z.unaryminus;r();var i=[N(e)];return new V(n,t,i)}return N(e)}function N(e){for(var n=[O(e)];"^"==X;)r(),n.push(O(e));for(var t=n.pop();n.length;){var i=n.pop(),a="^",o=Z.pow,f=[i,t];t=new V(a,o,f)}return t}function O(e){for(var n=x(e);"!"==X;){var t=X,i=Z.factorial;r();var a=[n];n=new V(t,i,a)}return n}function x(e){for(var n=b(e);"'"==X;){var t=X,i=Z.transpose;r();var a=[n];n=new V(t,i,a)}return n}function b(e){return M(e)}function M(e){if(Q==G.SYMBOL){var n=X;r();var t=e.createLink(n),i=A(e),a=new V(n,t,i);return a}return S(e)}function A(e){var n=[];if("("==X){if(r(),")"!=X)for(n.push(m(e));","==X;)r(),n.push(m(e));if(")"!=X)throw I("Parenthesis ) missing");r()}return n}function S(n){if('"'==X){for(var t="",i="";""!=K&&('"'!=K||"\\"==i);)t+=K,i=K,e();if(r(),'"'!=X)throw I('End of string " missing');r();var a=new D(t);return a}return T(n)}function T(e){if("["==X){var n;for(r();"\n"==X;)r();if("]"!=X){var t=[],i=0,a=0;for(t[0]=[m(e)];","==X||";"==X;){for(","==X?a++:(i++,a=0,t[i]=[]),r();"\n"==X;)r();for(t[i][a]=m(e);"\n"==X;)r()}var o=t.length,f=t.length>0?t[0].length:0;for(i=1;o>i;i++)if(t[i].length!=f)throw B("Number of columns must match ("+t[i].length+" != "+f+")");if("]"!=X)throw I("End of matrix ] missing");r(),n=new k(t)}else r(),n=new k([[]]);return n}return U(e)}function U(e){if(Q==G.NUMBER){var t;t="."==X?0:Number(X),r();var i;if(Q==G.SYMBOL){if("i"==X||"I"==X)return i=new n(0,t),r(),new D(i);if(E.isPlainUnit(X))return i=new E(t,X),r(),new D(i);throw P('Unknown unit "'+X+'"')}var a=new D(t);return a}return L(e)}function L(e){if("("==X){r();var n=m(e);if(")"!=X)throw I("Parenthesis ) expected");return r(),n}return R(e)}function R(){throw""==X?I("Unexpected end of expression"):I("Value expected")}function _(){return void 0}function z(){return W-X.length+1}function q(e){var n=_(),t=z();return void 0===n?void 0===t?e:e+" (char "+t+")":e+" (line "+n+", char "+t+")"}function I(e){return new SyntaxError(q(e))}function P(e){return new TypeError(q(e))}function B(e){return Error(q(e))}Z.expr.Parser=function C(){if(this.constructor!=C)throw new SyntaxError("Parser constructor must be called with the new operator");this.scope=new Z.expr.Scope},Z.expr.Parser.prototype.parse=function(e,n){return H=e||"",n||(n=this.scope),s(n)},Z.expr.Parser.prototype.eval=function(e){var n=this.parse(e);return n.eval()},Z.expr.Parser.prototype.get=function(e){var n=this.scope.findDef(e);return n?n.value:void 0},Z.expr.Parser.prototype.set=function(e,n){this.scope.createDef(e,n)},Z.expr.Parser.prototype.clear=function(){this.scope.clear()};var G={NULL:0,DELIMITER:1,NUMBER:2,SYMBOL:3,UNKNOWN:4},H="",W=0,K="",X="",Q=G.NULL}(),function(){function e(){this.idMax=-1,this.updateSeq=0,this.parser=new Z.expr.Parser,this.scope=new Z.expr.Scope,this.nodes={},this.firstNode=void 0,this.lastNode=void 0}Z.expr.Workspace=e,e.prototype.clear=function(){this.nodes={},this.firstNode=void 0,this.lastNode=void 0},e.prototype.append=function(n){var t=this._getNewId(),r=this.lastNode?this.lastNode.scope:this.scope,i=new Z.expr.Scope(r),a=new e.Node({id:t,expression:n,parser:this.parser,scope:i,nextNode:void 0,previousNode:this.lastNode});return this.nodes[t]=a,this.firstNode||(this.firstNode=a),this.lastNode&&(this.lastNode.nextNode=a),this.lastNode=a,this._update([t]),t},e.prototype.insertBefore=function(n,t){var r=this.nodes[t];if(!r)throw'Node with id "'+t+'" not found';var i=r.previousNode,a=this._getNewId(),o=i?i.scope:this.scope,f=new Z.expr.Scope(o),s=new e.Node({id:a,expression:n,parser:this.parser,scope:f,nextNode:r,previousNode:i});this.nodes[a]=s,i?i.nextNode=s:this.firstNode=s,r.previousNode=s,r.scope.parentScope=s.scope;var u=this.getDependencies(a);return-1==u.indexOf(a)&&u.unshift(a),this._update(u),a},e.prototype.insertAfter=function(e,n){var t=this.nodes[n];if(!t)throw'Node with id "'+n+'" not found';return t==this.lastNode?this.append(e):this.insertBefore(n+1,e)},e.prototype.remove=function(e){var n=this.nodes[e];if(!n)throw'Node with id "'+e+'" not found';var t=this.getDependencies(e),r=n.previousNode,i=n.nextNode;r?r.nextNode=i:this.firstNode=i,i?i.previousNode=r:this.lastNode=r;var a=r?r.scope:this.scope;i&&(i.scope.parentScope=a),delete this.nodes[e],this._update(t)},e.prototype.replace=function(n,t){var r=this.nodes[t];if(!r)throw'Node with id "'+t+'" not found';var i=[t];e._merge(i,this.getDependencies(t));var a=r.previousNode;r.nextNode,a?a.scope:this.scope,r.setExpr(n),e._merge(i,this.getDependencies(t)),this._update(i)},e.Node=function(e){this.id=e.id,this.parser=e.parser,this.scope=e.scope,this.nextNode=e.nextNode,this.previousNode=e.previousNode,this.updateSeq=0,this.result=void 0,this.setExpr(e.expression)},e.Node.prototype.setExpr=function(e){this.expression=e||"",this.scope.clear(),this._parse()},e.Node.prototype.getExpr=function(){return this.expression},e.Node.prototype.getResult=function(){return this.result},e.Node.prototype._parse=function(){try{this.fn=this.parser.parse(this.expression,this.scope)}catch(e){var n="Error: "+((e.message||e)+"");this.fn=new D(n)}},e.Node.prototype.eval=function(){try{this.scope.init(),this.result=this.fn.eval()}catch(e){this.scope.init(),this.result="Error: "+((e.message||e)+"")}return this.result},e._merge=function(e,n){for(var t=0,r=n.length;r>t;t++){var i=n[t];-1==e.indexOf(i)&&e.push(i)}},e.prototype.getDependencies=function(n){var t,r=[],i=this.nodes[n];if(i){var a=i.scope.defs,o=i.scope.updates,f=[];for(t in a)a.hasOwnProperty(t)&&f.push(t);for(t in o)o.hasOwnProperty(t)&&-1==f.indexOf(t)&&f.push(t);for(var s=i.nextNode;s&&f.length;){for(var u=s.scope,c=0;f.length>c;){if(t=f[c],(u.hasLink(t)||u.hasUpdate(t))&&-1==r.indexOf(s.id)){r.push(s.id);var l=this.getDependencies(s.id);e._merge(r,l)}u.hasDef(t)&&(f.splice(c,1),c--),c++}s=s.nextNode}}return r},e.prototype.getExpr=function(e){var n=this.nodes[e];if(!n)throw'Node with id "'+e+'" not found';return n.getExpr()},e.prototype.getResult=function(e){var n=this.nodes[e];if(!n)throw'Node with id "'+e+'" not found';return n.getResult()},e.prototype._update=function(e){this.updateSeq++;for(var n=this.updateSeq,t=this.nodes,r=0,i=e.length;i>r;r++){var a=e[r],o=t[a];o&&(o.eval(),o.updateSeq=n)}},e.prototype.getChanges=function(e){var n=[],t=this.firstNode;for(e=e||0;t;)t.updateSeq>e&&n.push(t.id),t=t.nextNode;return{ids:n,updateSeq:this.updateSeq}},e.prototype._getNewId=function(){return this.idMax++,this.idMax},e.prototype.toString=function(){return JSON.stringify(this.toJSON())},e.prototype.toJSON=function(){for(var e=[],n=this.firstNode;n;){var t={id:n.id,expression:n.expression,dependencies:this.getDependencies(n.id)};try{t.result=n.getResult()}catch(r){t.result="Error: "+((r.message||r)+"")}e.push(t),n=n.nextNode}return e}}(),Z.Complex=function(){W("new math.Complex()","math.complex()")},Z.Unit=function(){W("new math.Unit()","math.unit()")},Z.parser.Parser=function(){W("new math.parser.Parser()","math.parser()")},Z.parser.Workspace=function(){W("new math.parser.Workspace()","math.workspace()")};for(var en in Z)Z.hasOwnProperty(en)&&en&&d(en,Z[en])})(); \ No newline at end of file +(function(){function e(e){return e instanceof Boolean||"boolean"==typeof e}function n(e,t){if(this.constructor!=n)throw new SyntaxError("Complex constructor must be called with the new operator");if(null!=e&&!v(e)||null!=t&&!v(t))throw new TypeError("Two numbers or a single string expected in Complex constructor");this.re=e||0,this.im=t||0}function t(e){if(this.constructor!=t)throw new SyntaxError("Matrix constructor must be called with the new operator");if(e instanceof t||e instanceof w)this._data=e.toArray();else if(e instanceof Array)this._data=e;else{if(null!=e)throw new TypeError("Unsupported type of data ("+Z.typeof(e)+")");this._data=[]}this._size=K.size(this._data)}function r(e,n){if(!v(e)||!g(e))throw new TypeError("Index must be an integer (value: "+e+")");if(1>e)throw new RangeError("Index out of range ("+e+" < 1)");if(n&&e>n)throw new RangeError("Index out of range ("+e+" > "+n+")")}function i(e,n){return r(n,e.length),e[n-1]}function a(e,n){return n.forEach(function(n){e=i(e,n)}),Z.clone(e)}function o(e,n){var t=n[0];return t.map?t.map(function(n){return i(e,n)}):[i(e,t)]}function s(e,n){var t=n[0],r=n[1];if(t.map)return r.map?t.map(function(n){var t=i(e,n);return r.map(function(e){return i(t,e)})}):t.map(function(n){return[i(i(e,n),r)]});if(r.map){var a=i(e,t);return[r.map(function(e){return i(a,e)})]}return[[i(i(e,t),r)]]}function f(e,n,t){var r=t==n.length-1,a=n[t],o=function(a){var o=i(e,a);return r?o:f(o,n,t+1)};return a.map?a.map(o):[o(a)]}function u(e,n,t){if(r(n),t instanceof Array)throw new TypeError("Dimension mismatch, value expected instead of array");e[n-1]=t}function c(e,n,t,i){var a=!1;t.length>n.length&&(a=!0);for(var o=0;t.length>o;o++){var s=t[o];r(s),(null==n[o]||s>n[o])&&(n[o]=s,a=!0)}a&&K.resize(e,n,0);var f=n.length;t.forEach(function(n,t){f-1>t?e=e[n-1]:e[n-1]=i})}function l(e,n,t,i){var a=t[0];r(a),a>n[0]&&K.resize(e,[a],0),e[a-1]=i}function h(e,n,t,i){var a=t[0],o=t[1];r(a),r(o);var s=!1;a>(n[0]||0)&&(n[0]=a,s=!0),o>(n[1]||0)&&(n[1]=o,s=!0),s&&K.resize(e,n,0),e[a-1][o-1]=i}function m(e,n,t,r,i){var a=r==t.length-1,o=t[r],s=function(o,s){if(a)u(e,o,i[s]),e.length>(n[r]||0)&&(n[r]=e.length);else{var f=e[o-1];f instanceof Array||(e[o-1]=f=[f],e.length>(n[r]||0)&&(n[r]=e.length)),m(f,n,t,r+1,i[s])}};if(o.map){var f=o.size&&o.size()||o.length;if(f!=i.length)throw new RangeError("Dimensions mismatch ("+f+" != "+i.length+")");o.map(s)}else s(o,0)}function p(e){for(var n=0,t=e.length;t>n;n++){var r=e[n];r instanceof Array?p(r):void 0==r&&(e[n]=0)}}function v(e){return e instanceof Number||"number"==typeof e}function g(e){return e==Math.round(e)}function w(e,n,t){if(this.constructor!=w)throw new SyntaxError("Range constructor must be called with the new operator");if(null!=e&&!v(e))throw new TypeError("Parameter start must be a number");if(null!=t&&!v(t))throw new TypeError("Parameter end must be a number");if(null!=n&&!v(n))throw new TypeError("Parameter step must be a number");this.start=null!=e?e:0,this.end=null!=t?t:0,this.step=null!=n?n:1}function d(e,n){var t=Z.type.Selector,r=Array.prototype.slice;t.prototype[e]="function"==typeof n?function(){var e=[this.value].concat(r.call(arguments,0));return new t(n.apply(this,e))}:new t(n)}function y(e){return e instanceof String||"string"==typeof e}function E(e,n){if(this.constructor!=E)throw Error("Unit constructor must be called with the new operator");if(null!=e&&!v(e))throw Error("First parameter in Unit constructor must be a number");if(null!=n&&!y(n))throw Error("Second parameter in Unit constructor must be a string");if(null!=n){var t=N(n);if(!t)throw Error('String "'+n+'" is no unit');this.unit=t.unit,this.prefix=t.prefix,this.hasUnit=!0}else this.unit=E.UNIT_NONE,this.prefix=E.PREFIX_NONE,this.hasUnit=!1;null!=e?(this.value=this._normalize(e),this.hasValue=!0,this.fixPrefix=!1):(this.value=this._normalize(1),this.hasValue=!1,this.fixPrefix=!0)}function N(e){for(var n=E.UNITS,t=0,r=n.length;r>t;t++){var i=n[t];if(K.endsWith(e,i.name)){var a=e.length-i.name.length,o=e.substring(0,a),s=i.prefixes[o];if(void 0!==s)return{unit:i,prefix:s}}}return null}function O(e,n){var t=void 0;if(2==arguments.length){var r=Z.typeof(n);t="Function "+e+" does not support a parameter of type "+r}else if(arguments.length>2){for(var i=[],a=1;arguments.length>a;a++)i.push(Z.typeof(arguments[a]));t="Function "+e+" does not support a parameters of type "+i.join(", ")}else t="Unsupported parameter in function "+e;return new TypeError(t)}function x(e,n,t,r){var i="Wrong number of arguments in function "+e+" ("+n+" provided, "+t+(void 0!=r?"-"+r:"")+" expected)";return new SyntaxError(i)}function b(){}function M(e,n,t){this.name=e,this.fn=n,this.params=t}function A(e){this.value=e}function S(e){this.nodes=e||[]}function T(){this.params=[],this.visible=[]}function U(e,n,t,r){this.name=e,this.params=n,this.expr=t,this.result=r}function L(e,n){this.object=e,this.params=n}function R(e,n,t,r,i){this.name=e,this.variables=t,this.values=[];for(var a=0,o=this.variables.length;o>a;a++)this.values[a]=function(){var e=function(){return e.value};return e.value=void 0,e}();this.def=this.createFunction(e,n,t,r),this.result=i}function _(e,t){var r=t.re*t.re+t.im*t.im;return new n((e.re*t.re+e.im*t.im)/r,(e.im*t.re-e.re*t.im)/r)}function z(e,t){return new n(e.re*t.re-e.im*t.im,e.re*t.im+e.im*t.re)}function q(e,n){var t=Z.log(e),r=Z.multiply(t,n);return Z.exp(r)}function I(e,n){var t=Math.pow(10,void 0!=n?n:Z.options.precision);return Math.round(e*t)/t}function P(e,n,t,r){if(t>r){if(e.length!=n.length)throw Error("Dimensions mismatch ("+e.length+" != "+n.length+")");for(var i=[],a=0;e.length>a;a++)i[a]=P(e[a],n[a],t,r+1);return i}return e.concat(n)}function C(e,n,t){var r=Z.multiply,i=Z.subtract;if(1==n)return e[0][0];if(2==n)return i(r(e[0][0],e[1][1]),r(e[1][0],e[0][1]));for(var a=0,o=0;t>o;o++){var s=B(e,n,t,0,o);a+=r(r((o+1)%2+(o+1)%2-1,e[0][o]),C(s,n-1,t-1))}return a}function B(e,n,t,r,i){for(var a,o=[],s=0;n>s;s++)if(s!=r){a=o[s-(s>r)]=[];for(var f=0;t>f;f++)f!=i&&(a[f-(f>i)]=e[s][f])}return o}function G(e,n,t){var r,i,a,o,s,f=Z.add,u=Z.unaryminus,c=Z.multiply,l=Z.divide;if(1==n){if(o=e[0][0],0==o)throw Error("Cannot calculate inverse, determinant is zero");return[[l(1,o)]]}if(2==n){var h=Z.det(e);if(0==h)throw Error("Cannot calculate inverse, determinant is zero");return[[l(e[1][1],h),l(u(e[0][1]),h)],[l(u(e[1][0]),h),l(e[0][0],h)]]}var m=e.concat();for(r=0;n>r;r++)m[r]=m[r].concat();for(var p=Z.eye(n).valueOf(),v=0;t>v;v++){for(r=v;n>r&&0==m[r][v];)r++;if(r==n||0==m[r][v])throw Error("Cannot calculate inverse, determinant is zero");r!=v&&(s=m[v],m[v]=m[r],m[r]=s,s=p[v],p[v]=p[r],p[r]=s);var g=m[v],w=p[v];for(r=0;n>r;r++){var d=m[r],y=p[r];if(r!=v){if(0!=d[v]){for(a=l(u(d[v]),g[v]),i=v;t>i;i++)d[i]=f(d[i],c(a,g[i]));for(i=0;t>i;i++)y[i]=f(y[i],c(a,w[i]))}}else{for(a=g[v],i=v;t>i;i++)d[i]=l(d[i],a);for(i=0;t>i;i++)y[i]=l(y[i],a)}}}return p}function V(e){if(1==e.length)return V(e[0]);for(var n=0,t=e.length;t>n;n++){var r=e[n];r instanceof Array&&(e[n]=V(r))}return e}function D(e){for(var n=Z.larger,t=e[0],r=1,i=e.length;i>r;r++){var a=e[r];n(a,t)&&(t=a)}return t}function k(e,n,t){for(var r=Z.larger,i=[],a=0;t>a;a++){for(var o=e[0][a],s=1;n>s;s++){var f=e[s][a];r(f,o)&&(o=f)}i[a]=o}return i}function F(e){for(var n=Z.smaller,t=e[0],r=1,i=e.length;i>r;r++){var a=e[r];n(a,t)&&(t=a)}return t}function j(e,n,t){for(var r=Z.smaller,i=[],a=0;t>a;a++){for(var o=e[0][a],s=1;n>s;s++){var f=e[s][a];r(f,o)&&(o=f)}i[a]=o}return i}function H(e,n){Z[e]=n,d(e,n)}function Y(e){return"function"==typeof e||v(e)||y(e)||e instanceof n||e instanceof E}function W(e,n){throw Error('Constructor "'+e+'" has been replaced by '+'constructor method "'+n+'" in math.js v0.5.0')}var Z={type:{},expr:{node:{}},options:{precision:10}};"undefined"!=typeof module&&module.exports!==void 0&&(module.exports=Z),"undefined"!=typeof exports&&(exports=Z),"undefined"!=typeof require&&"undefined"!=typeof define&&define(function(){return Z}),"undefined"!=typeof window&&(window.math=Z);var K=function(){function e(n){if(n instanceof Array){var t=n.length;if(t){var r=e(n[0]);return 0==r[0]?[0].concat(r):[t].concat(r)}return[t]}return[]}function n(e,t,r){var i,a=e.length;if(a!=t[r])throw new RangeError("Dimension mismatch ("+a+" != "+t[r]+")");if(t.length-1>r){var o=r+1;for(i=0;a>i;i++){var s=e[i];if(!(s instanceof Array))throw new RangeError("Dimension mismatch ("+(t.length-1)+" < "+t.length+")");n(e[i],t,o)}}else for(i=0;a>i;i++)if(e[i]instanceof Array)throw new RangeError("Dimension mismatch ("+(t.length+1)+" > "+t.length+")")}function r(e,n,t){if(n.length-1>t){var i=e[0];if(1!=e.length||!(i instanceof Array))throw new RangeError("Dimension mismatch ("+e.length+" > 0)");r(i,n,t+1)}else if(e.length)throw new RangeError("Dimension mismatch ("+e.length+" > 0)")}function i(e,n,t,r){if(!(e instanceof Array))throw new TypeError("Array expected");var a=e.length,o=n[t];if(a!=o){if(o>e.length)for(var s=e.length;o>s;s++)e[s]=r?Z.clone(r):0;else e.length=n[t];a=e.length}if(n.length-1>t){var f=t+1;for(s=0;a>s;s++)u=e[s],u instanceof Array||(u=[u],e[s]=u),i(u,n,f,r)}else for(s=0;a>s;s++){for(var u=e[s];u instanceof Array;)u=u[0];e[s]=u}}var a={};return a.formatNumber=function(e,n){if(1/0===e)return"Infinity";if(e===-1/0)return"-Infinity";if(0/0===e)return"NaN";var t=Math.abs(e);if(t>1e-4&&1e6>t||0==t)return I(e,n)+"";var r=Math.round(Math.log(t)/Math.LN10),i=e/Math.pow(10,r);return I(i,n)+"E"+r},a.formatArray=function(e){if(e instanceof Array){for(var n="[",t=e.length,r=0;t>r;r++)0!=r&&(n+=", "),n+=a.formatArray(e[r]);return n+="]"}return Z.format(e)},a.formatArray2d=function(e){var n="[",t=a.size(e);if(2!=t.length)throw new RangeError("Array must be two dimensional (size: "+a.formatArray(t)+")");for(var r=t[0],i=t[1],o=0;r>o;o++){0!=o&&(n+="; ");for(var s=e[o],f=0;i>f;f++){0!=f&&(n+=", ");var u=s[f];void 0!=u&&(n+=Z.format(u))}}return n+="]"},a.argsToArray=function(e){var n;if(0==e.length)n=[];else if(1==e.length)n=e[0],n instanceof t&&(n=n.toVector()),n instanceof w&&(n=n.valueOf()),n instanceof Array||(n=[n]);else{n=[];for(var r=0;e.length>r;r++)n[r]=e[r]}return n},a.endsWith=function(e,n){var t=e.length-n.length,r=e.length;return e.substring(t,r)===n},a.randomUUID=function(){var e=function(){return Math.floor(65536*Math.random()).toString(16)};return e()+e()+"-"+e()+"-"+e()+"-"+e()+"-"+e()+e()+e()},a.map=function(e,n){if(e instanceof Array||e instanceof t||e instanceof w)return e.map(function(e){return n(e)});throw new TypeError("Array expected")},a.map2=function(e,n,r){var i,o,s;if(e instanceof t||n instanceof t)return new t(a.map2(e.valueOf(),n.valueOf(),r));if(e instanceof w||n instanceof w)return new t(a.map2(e.valueOf(),n.valueOf(),r));if(e instanceof Array)if(n instanceof Array){if(e.length!=n.length)throw new RangeError("Dimension mismatch ("+e.length+" != "+n.length+")");for(i=[],o=e.length,s=0;o>s;s++)i[s]=r(e[s],n[s])}else for(i=[],o=e.length,s=0;o>s;s++)i[s]=r(e[s],n);else if(n instanceof Array)for(i=[],o=n.length,s=0;o>s;s++)i[s]=r(e,n[s]);else i=r(e,n);return i},a.forEach=function(e,n){if(e instanceof Array)e.forEach(n);else for(var t in e)e.hasOwnProperty(t)&&n(e[t],t,e)},a.mapObject=function(e,n){var t={};for(var r in e)e.hasOwnProperty(r)&&(t[r]=n(e[r]));return t},a.deepEqual=function(e,n){var t,r,i;if(e instanceof Array){if(!(n instanceof Array))return!1;for(r=0,i=e.length;i>r;r++)if(!a.deepEqual(e[r],n[r]))return!1;return!0}if(e instanceof Object){if(n instanceof Array||!(n instanceof Object))return!1;for(t in e)if(e.hasOwnProperty(t)&&!a.deepEqual(e[t],n[t]))return!1;for(t in n)if(n.hasOwnProperty(t)&&!a.deepEqual(e[t],n[t]))return!1;return!0}return e.valueOf()==n.valueOf()},a.size=function(n){var t=e(n);return a.validate(n,t),t},a.validate=function(e,t){var i=0==t.length;if(i){if(e instanceof Array)throw new RangeError("Dimension mismatch ("+e.length+" != 0)")}else{var o=-1!=t.indexOf(0);o?(t.forEach(function(e){if(0!=e)throw new RangeError("Invalid size, all dimensions must be either zero or non-zero (size: "+a.formatArray(t)+")")}),r(e,t,0)):n(e,t,0)}},a.resize=function(e,n,t){if(!(n instanceof Array))throw new TypeError("Size must be an array (size is "+Z.typeof(n)+")");n.forEach(function(e){if(!v(e)||!g(e)||0>e)throw new TypeError("Invalid size, must contain positive integers (size: "+a.formatArray(n)+")")});var r=-1!=n.indexOf(0);r&&n.forEach(function(e){if(0!=e)throw new RangeError("Invalid size, all dimensions must be either zero or non-zero (size: "+a.formatArray(n)+")")}),i(e,n,0,t)},Array.prototype.indexOf||(Array.prototype.indexOf=function(e){for(var n=0;this.length>n;n++)if(this[n]==e)return n;return-1}),Array.prototype.forEach||(Array.prototype.forEach=function(e,n){for(var t=0,r=this.length;r>t;++t)e.call(n||this,this[t],t,this)}),Array.prototype.map||(Array.prototype.map=function(e,n){var t,r,i;if(null==this)throw new TypeError(" this is null or not defined");var a=Object(this),o=a.length>>>0;if("function"!=typeof e)throw new TypeError(e+" is not a function");for(n&&(t=n),r=Array(o),i=0;o>i;){var s,f;i in a&&(s=a[i],f=e.call(t,s,i,a),r[i]=f),i++}return r}),Array.prototype.every||(Array.prototype.every=function(e){"use strict";if(null==this)throw new TypeError;var n=Object(this),t=n.length>>>0;if("function"!=typeof e)throw new TypeError;for(var r=arguments[1],i=0;t>i;i++)if(i in n&&!e.call(r,n[i],i,n))return!1;return!0}),Array.prototype.some||(Array.prototype.some=function(e){"use strict";if(null==this)throw new TypeError;var n=Object(this),t=n.length>>>0;if("function"!=typeof e)throw new TypeError;for(var r=arguments[1],i=0;t>i;i++)if(i in n&&e.call(r,n[i],i,n))return!0;return!1}),a}();Z.type.Complex=n,function(){function e(){for(;" "==c||" "==c;)i()}function t(e){return e>="0"&&"9">=e||"."==e}function r(e){return e>="0"&&"9">=e}function i(){u++,c=f[u]}function a(e){u=e,c=f[u]}function o(){var e="",n=u;if("+"==c?i():"-"==c&&(e+=c,i()),!t(c))return a(n),null;for(;t(c);)e+=c,i();if("E"==c||"e"==c){if(e+=c,i(),("+"==c||"-"==c)&&(e+=c,i()),!r(c))return a(n),null;for(;r(c);)e+=c,i()}return e}function s(){var e=f[u+1];if("I"==c||"i"==c)return i(),"1";if(!("+"!=c&&"-"!=c||"I"!=e&&"i"!=e)){var n="+"==c?"1":"-1";return i(),i(),n}return null}var f,u,c;n.parse=function(t){if(f=t,u=-1,c="",!y(f))return null;i(),e();var r=o();if(r){if("I"==c||"i"==c)return i(),e(),c?null:new n(0,Number(r));e();var a=c;if("+"!=a&&"-"!=a)return e(),c?null:new n(Number(r),0);i(),e();var l=o();if(l){if("I"!=c&&"i"!=c)return null;i()}else if(l=s(),!l)return null;return"-"==a&&(l="-"==l[0]?"+"+l.substring(1):"-"+l),i(),e(),c?null:new n(Number(r),Number(l))}return(r=s())?(e(),c?null:new n(0,Number(r))):null}}(),n.prototype.clone=function(){return new n(this.re,this.im)},n.prototype.toString=function(){var e="",n=K.formatNumber(this.re),t=K.formatNumber(this.im);return e=0==this.im?n:0==this.re?1==this.im?"i":-1==this.im?"-i":t+"i":this.im>0?1==this.im?n+" + i":n+" + "+t+"i":-1==this.im?n+" - i":n+" - "+K.formatNumber(Math.abs(this.im))+"i"},Z.type.Matrix=t,t.prototype.get=function(e){var n;if(e instanceof t)n=e.isVector(),e=e.valueOf();else{if(!(e instanceof Array))throw new TypeError("Unsupported type of index "+Z.typeof(e));n=!e.some(function(e){return e.forEach})}if(e.length!=this._size.length)throw new RangeError("Dimension mismatch ("+e.length+" != "+this._size.length+")");if(n)switch(e.length){case 1:return i(this._data,e[0]);case 2:return i(i(this._data,e[0]),e[1]);default:return a(this._data,e)}else switch(e.length){case 1:return new t(o(this._data,e));case 2:return new t(s(this._data,e));default:return new t(f(this._data,e,0))}},t.prototype.set=function(e,n){var r;if(e instanceof t)r=e.isVector(),e=e.valueOf();else{if(!(e instanceof Array))throw new TypeError("Unsupported type of index "+Z.typeof(e));r=!e.some(function(e){return e.forEach})}if((n instanceof t||n instanceof w)&&(n=n.valueOf()),e.length=e})},t.prototype.toVector=function(){var e=0,n=void 0,t=[];if(this._size.forEach(function(r,i){r>1&&(e++,n=i),t[i]=0}),0==e){var r=this.toScalar();return r?[r]:[]}if(1==e){var i=[],a=function(e){e instanceof Array?e.forEach(a):i.push(e)};return a(this._data),i}return null},t.prototype.isVector=function(){var e=0;return this._size.forEach(function(n){n>1&&e++}),1>=e},t.prototype.toArray=function(){return Z.clone(this._data)},t.prototype.valueOf=function(){return this._data},t.prototype.toString=function(){return K.formatArray(this._data)},Z.type.Range=w,w.parse=function(e){if(!y(e))return null;var n=e.split(":"),t=n.map(function(e){return Number(e)}),r=t.some(function(e){return isNaN(e)});if(r)return null;switch(t.length){case 2:return new w(t[0],1,t[1]);case 3:return new w(t[0],t[1],t[2]);default:return null}},w.prototype.clone=function(){return new w(this.start,this.step,this.end)},w.prototype.size=function(){var e=0,n=Number(this.start),t=Number(this.step),r=Number(this.end),i=r-n;return Z.sign(t)==Z.sign(i)?e=Math.floor(i/t)+1:0==i&&(e=1),isNaN(e)&&(e=0),[e]},w.prototype.forEach=function(e){var n=Number(this.start),t=Number(this.step),r=Number(this.end),i=0;if(t>0)for(;r>=n;)e(n,i,this),n+=t,i++;else if(0>t)for(;n>=r;)e(n,i,this),n+=t,i++},w.prototype.map=function(e){var n=[];return this.forEach(function(t,r,i){n[r]=e(t,r,i)}),n},w.prototype.toMatrix=function(){return new t(this.toArray())},w.prototype.toArray=function(){var e=[];return this.forEach(function(n,t){e[t]=n}),e},w.prototype.toVector=w.prototype.toArray,w.prototype.isVector=function(){return!0},w.prototype.toScalar=function(){var e=this.toArray();return 1==e.length?e[0]:null},w.prototype.isScalar=function(){return 1==this.size()[0]},w.prototype.valueOf=function(){return this.toArray()},w.prototype.toString=function(){var e=Z.format(Number(this.start));return 1!=this.step&&(e+=":"+Z.format(Number(this.step))),e+=":"+Z.format(Number(this.end))},Z.type.Selector=function X(e){if(!(this instanceof X))throw new SyntaxError("Selector constructor must be called with the new operator");this.value=e instanceof Z.type.Selector?e.value:e||void 0},Z.type.Selector.prototype={done:function(){return this.value},get:function(){var e=this.value;if(!e)throw Error("Selector value is undefined");if(e.get)return new Z.type.Selector(e.get.apply(e,arguments));if(e instanceof Array)return e=new t(e),new Z.type.Selector(e.get.apply(e,arguments).valueOf());throw Error("Selector value has no method get")},set:function(){var e=this.value;if(!e)throw Error("Selector value is undefined");if(e.set)return new Z.type.Selector(e.set.apply(e,arguments));if(e instanceof Array)return e=new t(e),new Z.type.Selector(e.set.apply(e,arguments).valueOf());throw Error("Selector value has no method set")},valueOf:function(){return this.value},toString:function(){return Z.format(this.value)}},Z.type.Unit=E,function(){function e(){for(;" "==u||" "==u;)r()}function n(e){return e>="0"&&"9">=e||"."==e}function t(e){return e>="0"&&"9">=e}function r(){f++,u=s[f]}function i(e){f=e,u=s[f]}function a(){var e="",a=f;if("+"==u?r():"-"==u&&(e+=u,r()),!n(u))return i(a),null;for(;n(u);)e+=u,r();if("E"==u||"e"==u){if(e+=u,r(),("+"==u||"-"==u)&&(e+=u,r()),!t(u))return i(a),null;for(;t(u);)e+=u,r()}return e}function o(){var n="";for(e();u&&" "!=u&&" "!=u;)n+=u,r();return n||null}var s,f,u;E.parse=function(n){if(s=n,f=-1,u="",!y(s))return null;r(),e();var t,i=a();return i?(t=o(),r(),e(),u?null:i&&t?new E(Number(i),t):null):(t=o(),r(),e(),u?null:new E(null,t))}}(),E.prototype.clone=function(){var e=new E;for(var n in this)this.hasOwnProperty(n)&&(e[n]=this[n]);return e},E.prototype._normalize=function(e){return(e+this.unit.offset)*this.unit.value*this.prefix.value},E.prototype._unnormalize=function(e,n){return void 0==n?e/this.unit.value/this.prefix.value-this.unit.offset:e/this.unit.value/n-this.unit.offset},E.isPlainUnit=function(e){return null!=N(e)},E.prototype.hasBase=function(e){return void 0===this.unit.base?void 0===e:this.unit.base===e},E.prototype.equalBase=function(e){return this.unit.base===e.unit.base},E.prototype.equals=function(e){return this.equalBase(e)&&this.value==e.value},E.prototype.in=function(e){var n;if(y(e)){if(n=new E(null,e),!this.equalBase(n))throw Error("Units do not match");return n.value=this.value,n}if(e instanceof E){if(!this.equalBase(e))throw Error("Units do not match");if(e.hasValue)throw Error("Cannot convert to a unit with a value");if(!e.hasUnit)throw Error("Unit expected on the right hand side of function in");return n=e.clone(),n.value=this.value,n.fixPrefix=!0,n}throw Error("String or Unit expected as parameter")},E.prototype.toNumber=function(e){var n=this.in(e),t=this.fixPrefix?n._bestPrefix():n.prefix;return n._unnormalize(n.value,t.value)},E.prototype.toString=function(){var e;if(this.fixPrefix)return e=this._unnormalize(this.value),K.formatNumber(e)+" "+this.prefix.name+this.unit.name;var n=this._bestPrefix();return e=this._unnormalize(this.value,n.value),K.formatNumber(e)+" "+n.name+this.unit.name},E.prototype._bestPrefix=function(){var e=Math.abs(this.value/this.unit.value),n=E.PREFIX_NONE,t=Math.abs(Math.log(e/n.value)/Math.LN10-1.2),r=this.unit.prefixes;for(var i in r)if(r.hasOwnProperty(i)){var a=r[i];if(a.scientific){var o=Math.abs(Math.log(e/a.value)/Math.LN10-1.2);t>o&&(n=a,t=o)}}return n},E.PREFIXES={NONE:{"":{name:"",value:1,scientific:!0}},SHORT:{"":{name:"",value:1,scientific:!0},da:{name:"da",value:10,scientific:!1},h:{name:"h",value:100,scientific:!1},k:{name:"k",value:1e3,scientific:!0},M:{name:"M",value:1e6,scientific:!0},G:{name:"G",value:1e9,scientific:!0},T:{name:"T",value:1e12,scientific:!0},P:{name:"P",value:1e15,scientific:!0},E:{name:"E",value:1e18,scientific:!0},Z:{name:"Z",value:1e21,scientific:!0},Y:{name:"Y",value:1e24,scientific:!0},d:{name:"d",value:.1,scientific:!1},c:{name:"c",value:.01,scientific:!1},m:{name:"m",value:.001,scientific:!0},u:{name:"u",value:1e-6,scientific:!0},n:{name:"n",value:1e-9,scientific:!0},p:{name:"p",value:1e-12,scientific:!0},f:{name:"f",value:1e-15,scientific:!0},a:{name:"a",value:1e-18,scientific:!0},z:{name:"z",value:1e-21,scientific:!0},y:{name:"y",value:1e-24,scientific:!0}},LONG:{"":{name:"",value:1,scientific:!0},deca:{name:"deca",value:10,scientific:!1},hecto:{name:"hecto",value:100,scientific:!1},kilo:{name:"kilo",value:1e3,scientific:!0},mega:{name:"mega",value:1e6,scientific:!0},giga:{name:"giga",value:1e9,scientific:!0},tera:{name:"tera",value:1e12,scientific:!0},peta:{name:"peta",value:1e15,scientific:!0},exa:{name:"exa",value:1e18,scientific:!0},zetta:{name:"zetta",value:1e21,scientific:!0},yotta:{name:"yotta",value:1e24,scientific:!0},deci:{name:"deci",value:.1,scientific:!1},centi:{name:"centi",value:.01,scientific:!1},milli:{name:"milli",value:.001,scientific:!0},micro:{name:"micro",value:1e-6,scientific:!0},nano:{name:"nano",value:1e-9,scientific:!0},pico:{name:"pico",value:1e-12,scientific:!0},femto:{name:"femto",value:1e-15,scientific:!0},atto:{name:"atto",value:1e-18,scientific:!0},zepto:{name:"zepto",value:1e-21,scientific:!0},yocto:{name:"yocto",value:1e-24,scientific:!0}},BINARY_SHORT:{"":{name:"",value:1,scientific:!0},k:{name:"k",value:1024,scientific:!0},M:{name:"M",value:Math.pow(1024,2),scientific:!0},G:{name:"G",value:Math.pow(1024,3),scientific:!0},T:{name:"T",value:Math.pow(1024,4),scientific:!0},P:{name:"P",value:Math.pow(1024,5),scientific:!0},E:{name:"E",value:Math.pow(1024,6),scientific:!0},Z:{name:"Z",value:Math.pow(1024,7),scientific:!0},Y:{name:"Y",value:Math.pow(1024,8),scientific:!0},Ki:{name:"Ki",value:1024,scientific:!0},Mi:{name:"Mi",value:Math.pow(1024,2),scientific:!0},Gi:{name:"Gi",value:Math.pow(1024,3),scientific:!0},Ti:{name:"Ti",value:Math.pow(1024,4),scientific:!0},Pi:{name:"Pi",value:Math.pow(1024,5),scientific:!0},Ei:{name:"Ei",value:Math.pow(1024,6),scientific:!0},Zi:{name:"Zi",value:Math.pow(1024,7),scientific:!0},Yi:{name:"Yi",value:Math.pow(1024,8),scientific:!0}},BINARY_LONG:{"":{name:"",value:1,scientific:!0},kilo:{name:"kilo",value:1024,scientific:!0},mega:{name:"mega",value:Math.pow(1024,2),scientific:!0},giga:{name:"giga",value:Math.pow(1024,3),scientific:!0},tera:{name:"tera",value:Math.pow(1024,4),scientific:!0},peta:{name:"peta",value:Math.pow(1024,5),scientific:!0},exa:{name:"exa",value:Math.pow(1024,6),scientific:!0},zetta:{name:"zetta",value:Math.pow(1024,7),scientific:!0},yotta:{name:"yotta",value:Math.pow(1024,8),scientific:!0},kibi:{name:"kibi",value:1024,scientific:!0},mebi:{name:"mebi",value:Math.pow(1024,2),scientific:!0},gibi:{name:"gibi",value:Math.pow(1024,3),scientific:!0},tebi:{name:"tebi",value:Math.pow(1024,4),scientific:!0},pebi:{name:"pebi",value:Math.pow(1024,5),scientific:!0},exi:{name:"exi",value:Math.pow(1024,6),scientific:!0},zebi:{name:"zebi",value:Math.pow(1024,7),scientific:!0},yobi:{name:"yobi",value:Math.pow(1024,8),scientific:!0}}},E.PREFIX_NONE={name:"",value:1,scientific:!0},E.BASE_UNITS={NONE:{},LENGTH:{},MASS:{},TIME:{},CURRENT:{},TEMPERATURE:{},LUMINOUS_INTENSITY:{},AMOUNT_OF_SUBSTANCE:{},FORCE:{},SURFACE:{},VOLUME:{},ANGLE:{},BIT:{}};var Q=E.BASE_UNITS,J=E.PREFIXES;E.BASE_UNIT_NONE={},E.UNIT_NONE={name:"",base:E.BASE_UNIT_NONE,value:1,offset:0},E.UNITS=[{name:"meter",base:Q.LENGTH,prefixes:J.LONG,value:1,offset:0},{name:"inch",base:Q.LENGTH,prefixes:J.NONE,value:.0254,offset:0},{name:"foot",base:Q.LENGTH,prefixes:J.NONE,value:.3048,offset:0},{name:"yard",base:Q.LENGTH,prefixes:J.NONE,value:.9144,offset:0},{name:"mile",base:Q.LENGTH,prefixes:J.NONE,value:1609.344,offset:0},{name:"link",base:Q.LENGTH,prefixes:J.NONE,value:.201168,offset:0},{name:"rod",base:Q.LENGTH,prefixes:J.NONE,value:5.02921,offset:0},{name:"chain",base:Q.LENGTH,prefixes:J.NONE,value:20.1168,offset:0},{name:"angstrom",base:Q.LENGTH,prefixes:J.NONE,value:1e-10,offset:0},{name:"m",base:Q.LENGTH,prefixes:J.SHORT,value:1,offset:0},{name:"ft",base:Q.LENGTH,prefixes:J.NONE,value:.3048,offset:0},{name:"yd",base:Q.LENGTH,prefixes:J.NONE,value:.9144,offset:0},{name:"mi",base:Q.LENGTH,prefixes:J.NONE,value:1609.344,offset:0},{name:"li",base:Q.LENGTH,prefixes:J.NONE,value:.201168,offset:0},{name:"rd",base:Q.LENGTH,prefixes:J.NONE,value:5.02921,offset:0},{name:"ch",base:Q.LENGTH,prefixes:J.NONE,value:20.1168,offset:0},{name:"mil",base:Q.LENGTH,prefixes:J.NONE,value:254e-7,offset:0},{name:"m2",base:Q.SURFACE,prefixes:J.SHORT,value:1,offset:0},{name:"sqin",base:Q.SURFACE,prefixes:J.NONE,value:64516e-8,offset:0},{name:"sqft",base:Q.SURFACE,prefixes:J.NONE,value:.09290304,offset:0},{name:"sqyd",base:Q.SURFACE,prefixes:J.NONE,value:.83612736,offset:0},{name:"sqmi",base:Q.SURFACE,prefixes:J.NONE,value:2589988.110336,offset:0},{name:"sqrd",base:Q.SURFACE,prefixes:J.NONE,value:25.29295,offset:0},{name:"sqch",base:Q.SURFACE,prefixes:J.NONE,value:404.6873,offset:0},{name:"sqmil",base:Q.SURFACE,prefixes:J.NONE,value:6.4516e-10,offset:0},{name:"m3",base:Q.VOLUME,prefixes:J.SHORT,value:1,offset:0},{name:"L",base:Q.VOLUME,prefixes:J.SHORT,value:.001,offset:0},{name:"litre",base:Q.VOLUME,prefixes:J.LONG,value:.001,offset:0},{name:"cuin",base:Q.VOLUME,prefixes:J.NONE,value:16387064e-12,offset:0},{name:"cuft",base:Q.VOLUME,prefixes:J.NONE,value:.028316846592,offset:0},{name:"cuyd",base:Q.VOLUME,prefixes:J.NONE,value:.764554857984,offset:0},{name:"teaspoon",base:Q.VOLUME,prefixes:J.NONE,value:5e-6,offset:0},{name:"tablespoon",base:Q.VOLUME,prefixes:J.NONE,value:15e-6,offset:0},{name:"minim",base:Q.VOLUME,prefixes:J.NONE,value:6.161152e-8,offset:0},{name:"fluiddram",base:Q.VOLUME,prefixes:J.NONE,value:36966911e-13,offset:0},{name:"fluidounce",base:Q.VOLUME,prefixes:J.NONE,value:2957353e-11,offset:0},{name:"gill",base:Q.VOLUME,prefixes:J.NONE,value:.0001182941,offset:0},{name:"cup",base:Q.VOLUME,prefixes:J.NONE,value:.0002365882,offset:0},{name:"pint",base:Q.VOLUME,prefixes:J.NONE,value:.0004731765,offset:0},{name:"quart",base:Q.VOLUME,prefixes:J.NONE,value:.0009463529,offset:0},{name:"gallon",base:Q.VOLUME,prefixes:J.NONE,value:.003785412,offset:0},{name:"beerbarrel",base:Q.VOLUME,prefixes:J.NONE,value:.1173478,offset:0},{name:"oilbarrel",base:Q.VOLUME,prefixes:J.NONE,value:.1589873,offset:0},{name:"hogshead",base:Q.VOLUME,prefixes:J.NONE,value:.238481,offset:0},{name:"fldr",base:Q.VOLUME,prefixes:J.NONE,value:36966911e-13,offset:0},{name:"floz",base:Q.VOLUME,prefixes:J.NONE,value:2957353e-11,offset:0},{name:"gi",base:Q.VOLUME,prefixes:J.NONE,value:.0001182941,offset:0},{name:"cp",base:Q.VOLUME,prefixes:J.NONE,value:.0002365882,offset:0},{name:"pt",base:Q.VOLUME,prefixes:J.NONE,value:.0004731765,offset:0},{name:"qt",base:Q.VOLUME,prefixes:J.NONE,value:.0009463529,offset:0},{name:"gal",base:Q.VOLUME,prefixes:J.NONE,value:.003785412,offset:0},{name:"bbl",base:Q.VOLUME,prefixes:J.NONE,value:.1173478,offset:0},{name:"obl",base:Q.VOLUME,prefixes:J.NONE,value:.1589873,offset:0},{name:"g",base:Q.MASS,prefixes:J.SHORT,value:.001,offset:0},{name:"gram",base:Q.MASS,prefixes:J.LONG,value:.001,offset:0},{name:"ton",base:Q.MASS,prefixes:J.SHORT,value:907.18474,offset:0},{name:"tonne",base:Q.MASS,prefixes:J.SHORT,value:1e3,offset:0},{name:"grain",base:Q.MASS,prefixes:J.NONE,value:6479891e-11,offset:0},{name:"dram",base:Q.MASS,prefixes:J.NONE,value:.0017718451953125,offset:0},{name:"ounce",base:Q.MASS,prefixes:J.NONE,value:.028349523125,offset:0},{name:"poundmass",base:Q.MASS,prefixes:J.NONE,value:.45359237,offset:0},{name:"hundredweight",base:Q.MASS,prefixes:J.NONE,value:45.359237,offset:0},{name:"stick",base:Q.MASS,prefixes:J.NONE,value:.115,offset:0},{name:"gr",base:Q.MASS,prefixes:J.NONE,value:6479891e-11,offset:0},{name:"dr",base:Q.MASS,prefixes:J.NONE,value:.0017718451953125,offset:0},{name:"oz",base:Q.MASS,prefixes:J.NONE,value:.028349523125,offset:0},{name:"lbm",base:Q.MASS,prefixes:J.NONE,value:.45359237,offset:0},{name:"cwt",base:Q.MASS,prefixes:J.NONE,value:45.359237,offset:0},{name:"s",base:Q.TIME,prefixes:J.SHORT,value:1,offset:0},{name:"min",base:Q.TIME,prefixes:J.NONE,value:60,offset:0},{name:"h",base:Q.TIME,prefixes:J.NONE,value:3600,offset:0},{name:"seconds",base:Q.TIME,prefixes:J.LONG,value:1,offset:0},{name:"second",base:Q.TIME,prefixes:J.LONG,value:1,offset:0},{name:"sec",base:Q.TIME,prefixes:J.LONG,value:1,offset:0},{name:"minutes",base:Q.TIME,prefixes:J.NONE,value:60,offset:0},{name:"minute",base:Q.TIME,prefixes:J.NONE,value:60,offset:0},{name:"hours",base:Q.TIME,prefixes:J.NONE,value:3600,offset:0},{name:"hour",base:Q.TIME,prefixes:J.NONE,value:3600,offset:0},{name:"day",base:Q.TIME,prefixes:J.NONE,value:86400,offset:0},{name:"days",base:Q.TIME,prefixes:J.NONE,value:86400,offset:0},{name:"rad",base:Q.ANGLE,prefixes:J.NONE,value:1,offset:0},{name:"deg",base:Q.ANGLE,prefixes:J.NONE,value:.017453292519943295,offset:0},{name:"grad",base:Q.ANGLE,prefixes:J.NONE,value:.015707963267948967,offset:0},{name:"cycle",base:Q.ANGLE,prefixes:J.NONE,value:6.283185307179586,offset:0},{name:"A",base:Q.CURRENT,prefixes:J.SHORT,value:1,offset:0},{name:"ampere",base:Q.CURRENT,prefixes:J.LONG,value:1,offset:0},{name:"K",base:Q.TEMPERATURE,prefixes:J.NONE,value:1,offset:0},{name:"degC",base:Q.TEMPERATURE,prefixes:J.NONE,value:1,offset:273.15},{name:"degF",base:Q.TEMPERATURE,prefixes:J.NONE,value:1/1.8,offset:459.67},{name:"degR",base:Q.TEMPERATURE,prefixes:J.NONE,value:1/1.8,offset:0},{name:"kelvin",base:Q.TEMPERATURE,prefixes:J.NONE,value:1,offset:0},{name:"celsius",base:Q.TEMPERATURE,prefixes:J.NONE,value:1,offset:273.15},{name:"fahrenheit",base:Q.TEMPERATURE,prefixes:J.NONE,value:1/1.8,offset:459.67},{name:"rankine",base:Q.TEMPERATURE,prefixes:J.NONE,value:1/1.8,offset:0},{name:"mol",base:Q.AMOUNT_OF_SUBSTANCE,prefixes:J.NONE,value:1,offset:0},{name:"mole",base:Q.AMOUNT_OF_SUBSTANCE,prefixes:J.NONE,value:1,offset:0},{name:"cd",base:Q.LUMINOUS_INTENSITY,prefixes:J.NONE,value:1,offset:0},{name:"candela",base:Q.LUMINOUS_INTENSITY,prefixes:J.NONE,value:1,offset:0},{name:"N",base:Q.FORCE,prefixes:J.SHORT,value:1,offset:0},{name:"newton",base:Q.FORCE,prefixes:J.LONG,value:1,offset:0},{name:"lbf",base:Q.FORCE,prefixes:J.NONE,value:4.4482216152605,offset:0},{name:"poundforce",base:Q.FORCE,prefixes:J.NONE,value:4.4482216152605,offset:0},{name:"b",base:Q.BIT,prefixes:J.BINARY_SHORT,value:1,offset:0},{name:"bits",base:Q.BIT,prefixes:J.BINARY_LONG,value:1,offset:0},{name:"B",base:Q.BIT,prefixes:J.BINARY_SHORT,value:8,offset:0},{name:"bytes",base:Q.BIT,prefixes:J.BINARY_LONG,value:8,offset:0}],Z.E=Math.E,Z.LN2=Math.LN2,Z.LN10=Math.LN10,Z.LOG2E=Math.LOG2E,Z.LOG10E=Math.LOG10E,Z.PI=Math.PI,Z.SQRT1_2=Math.SQRT1_2,Z.SQRT2=Math.SQRT2,Z.I=new n(0,1),Z.pi=Z.PI,Z.e=Z.E,Z.i=Z.I,Z.expr.node.Node=b,b.prototype.eval=function(){throw Error("Cannot evaluate a Node interface") +},b.prototype.toString=function(){return""},M.prototype=new b,Z.expr.node.Symbol=M,M.prototype.hasParams=function(){return void 0!=this.params&&this.params.length>0},M.prototype.eval=function(){var e=this.fn;if(void 0===e)throw Error("Undefined symbol "+this.name);var n=this.params.map(function(e){return e.eval()});return e.apply(this,n)},M.prototype.toString=function(){if(this.name&&!this.params)return this.name;var e=this.name;return this.params&&this.params.length&&(e+="("+this.params.join(", ")+")"),e},A.prototype=new b,Z.expr.node.Constant=A,A.prototype.eval=function(){return this.value},A.prototype.toString=function(){return this.value?Z.format(this.value):""},S.prototype=new b,Z.expr.node.MatrixNode=S,function(){function e(n){return n.map(function(n){return n instanceof Array?e(n):n.eval()})}function n(e){for(var n=[],r=e.length,i=0;r>i;i++){for(var a=e[i],o=a.length,s=null,f=null,u=0;o>u;u++){var c,l=Z.clone(a[u]);if(l instanceof t){if(c=l.size(),l=l.valueOf(),1==c.length)l=[l],c=[1,c[0]];else if(c.length>2)throw Error("Cannot merge a multi dimensional matrix")}else l instanceof w?(l=[l.valueOf()],c=[1,l[0].length]):(c=[1,1],l=[[l]]);if(null==s)s=l,f=c[0];else{if(c[0]!=f)throw Error("Dimension mismatch ("+c[0]+" != "+f+")");for(var h=0;f>h;h++)s[h]=s[h].concat(l[h])}}n=n.concat(s)}return n}function r(e){return e.some(function(e){return e instanceof t||e instanceof w?!0:e instanceof Array?r(e):!1})}S.prototype.eval=function(){var i=e(this.nodes);return r(i)&&(i=n(i)),new t(i)},S.prototype.toString=function(){return K.formatArray(this.nodes)}}(),T.prototype=new b,Z.expr.node.Block=T,T.prototype.add=function(e,n){var t=this.params.length;this.params[t]=e,this.visible[t]=void 0!=n?n:!0},T.prototype.eval=function(){for(var e=[],n=0,t=this.params.length;t>n;n++){var r=this.params[n].eval();this.visible[n]&&e.push(r)}return e},T.prototype.toString=function(){for(var e=[],n=0,t=this.params.length;t>n;n++)this.visible[n]&&e.push("\n "+(""+this.params[n]));return"["+e.join(",")+"\n]"},U.prototype=new b,Z.expr.node.Assignment=U,U.prototype.eval=function(){if(void 0===this.expr)throw Error("Undefined symbol "+this.name);var e,n=this.params;if(n&&n.length){var t=[];this.params.forEach(function(e){t.push(e.eval())});var r=this.expr.eval();if(void 0==this.result.value)throw Error("Undefined symbol "+this.name);var i=this.result();if(!i.set)throw new TypeError("Cannot apply a subset to object of type "+Z.typeof(i));e=i.set(t,r),this.result.value=e}else e=this.expr.eval(),this.result.value=e;return e},U.prototype.toString=function(){var e="";return e+=this.name,this.params&&this.params.length&&(e+="("+this.params.join(", ")+")"),e+=" = ",e+=""+this.expr},L.prototype=new b,Z.expr.node.Arguments=L,L.prototype.eval=function(){var e=this.object;if(void 0==e)throw Error("Node undefined");for(var n=e.eval(),t=this.params,r=[],i=0,a=t.length;a>i;i++)r[i]=t[i].eval();if(!n.get)throw new TypeError("Cannot apply arguments to object of type "+Z.typeof(n));return n.get(r)},L.prototype.toString=function(){var e=this.object?""+this.object:"";return this.params&&(e+="("+this.params.join(", ")+")"),e},R.prototype=new b,Z.expr.node.FunctionAssignment=R,R.prototype.createFunction=function(e,n,t,r){var i=function(){var n=t?t.length:0,i=arguments?arguments.length:0;if(n!=i)throw x(e,i,n);if(n>0)for(var a=0;n>a;a++)t[a].value=arguments[a];return r.eval()};return i.toString=function(){return e+"("+n.join(", ")+")"},i},R.prototype.eval=function(){for(var e=this.variables,n=this.values,t=0,r=e.length;r>t;t++)e[t].value=n[t];return this.result.value=this.def,this.def},R.prototype.toString=function(){return""+this.def},Z.expr.Scope=function(e,n){this.readonly=!1,n&&void 0!=n.readonly&&(this.readonly=n.readonly),this.parentScope=e,this.nestedScopes=void 0,this.symbols={},this.defs={},this.updates={},this.links={}},Z.expr.Scope.prototype={createNestedScope:function(){if(this.readonly)throw Error("Cannot create nested scope: Scope is read-only");var e=new Z.expr.Scope(this);return this.nestedScopes||(this.nestedScopes=[]),this.nestedScopes.push(e),e},clear:function(){if(this.readonly)throw Error("Cannot clear scope: Scope is read-only");if(this.symbols={},this.defs={},this.links={},this.updates={},this.nestedScopes)for(var e=this.nestedScopes,n=0,t=e.length;t>n;n++)e[n].clear()},createSymbol:function(e){var n=this.symbols[e];if(!n){var t=this.findDef(e);n=this.newSymbol(e,t),this.symbols[e]=n}return n},newSymbol:function(e,n){var r=this,i=function(){var n,a;if(!i.value&&(i.value=r.findDef(e),!i.value))throw Error("Undefined symbol "+e);if("function"==typeof i.value)return i.value.apply(null,arguments);if(i.value instanceof t||i.value instanceof w||i.value instanceof Array){if(arguments.length){var o=i.value instanceof Array?new t(i.value):i.value;for(n=[],a=0;arguments.length>a;a++)n[a]=arguments[a];return o.get(n)}return i.value}return i.value};return i.value=n,i.toString=function(){return i.value?""+i.value:""},i},createLink:function(e){var n=this.links[e];return n||(n=this.createSymbol(e),this.links[e]=n),n},createDef:function(e,n){if(this.readonly)throw Error("Cannot create variable: Scope is read-only");var t=this.defs[e];return t||(t=this.createSymbol(e),this.defs[e]=t),t&&void 0!=n&&(t.value=n),t},createUpdate:function(e){if(this.readonly)throw Error("Cannot update variable: Scope is read-only");var n=this.updates[e];return n||(n=this.createLink(e),this.updates[e]=n),n},createConstant:function(e,n){var t=this.newSymbol(e,n);return this.symbols[e]=t,this.defs[e]=t,t},findDef:function(e){var n;if(n=this.defs[e])return n;if(n=this.updates[e])return n;if(this.parentScope)return this.parentScope.findDef(e);var t=Z[e];if(t)return this.createConstant(e,t);if(E.isPlainUnit(e)){var r=new E(null,e);return this.createConstant(e,r)}return void 0},removeLink:function(e){delete this.links[e]},removeDef:function(e){delete this.defs[e]},removeUpdate:function(e){delete this.updates[e]},init:function(){var e=this.symbols,n=this.parentScope;for(var t in e)if(e.hasOwnProperty(t)){var r=e[t];r.value=n?n.findDef(t):void 0}this.nestedScopes&&this.nestedScopes.forEach(function(e){e.init()})},hasLink:function(e){if(this.links[e])return!0;if(this.nestedScopes)for(var n=this.nestedScopes,t=0,r=n.length;r>t;t++)if(n[t].hasLink(e))return!0;return!1},hasDef:function(e){return void 0!=this.defs[e]},hasUpdate:function(e){return void 0!=this.updates[e]},getUndefinedSymbols:function(){var e=this.symbols,n=[];for(var t in e)if(e.hasOwnProperty(t)){var r=e[t];void 0==r.value&&n.push(r)}return this.nestedScopes&&this.nestedScopes.forEach(function(e){n=n.concat(e.getUndefinedSymbols())}),n}},function(){function e(){W++,K=Y.charAt(W)}function t(){W=0,K=Y.charAt(0)}function r(){for(Q=H.NULL,X="";" "==K||" "==K;)e();if("#"==K)for(;"\n"!=K&&""!=K;)e();if(""==K)return Q=H.DELIMITER,void 0;if("-"==K||","==K||"("==K||")"==K||"["==K||"]"==K||'"'==K||"\n"==K||";"==K||":"==K||"!"==K||"'"==K)return Q=H.DELIMITER,X+=K,e(),void 0;if(i(K))for(Q=H.DELIMITER;i(K);)X+=K,e();else if(o(K)){for(Q=H.NUMBER;o(K);)X+=K,e();if("E"==K||"e"==K)for(X+=K,e(),("+"==K||"-"==K)&&(X+=K,e()),s(K)||(Q=H.UNKNOWN);s(K);)X+=K,e()}else{if(!a(K)){for(Q=H.UNKNOWN;""!=K;)X+=K,e();throw D('Syntax error in part "'+X+'"')}for(Q=H.SYMBOL;a(K)||s(K);)X+=K,e()}}function i(e){return"&"==e||"|"==e||"<"==e||">"==e||"="==e||"+"==e||"/"==e||"*"==e||"%"==e||"^"==e||","==e||";"==e||"\n"==e||"!"==e||"'"==e}function a(e){return e>="a"&&"z">=e||e>="A"&&"Z">=e||"_"==e}function o(e){return e>="0"&&"9">=e||"."==e}function s(e){return e>="0"&&"9">=e}function f(e){t(),r();var n;if(n=""==X?new A(void 0):u(e),""!=X)throw Q==H.DELIMITER?F("Unknown operator "+X):D('Unexpected part "'+X+'"');return n}function u(e){var n,t,i;for("\n"!=X&&";"!=X&&""!=X&&(n=c(e));"\n"==X||";"==X;)t||(t=new T,n&&(i=";"!=X,t.add(n,i))),r(),"\n"!=X&&";"!=X&&""!=X&&(n=c(e),i=";"!=X,t.add(n,i));return t?t:(n||(n=c(e)),n)}function c(e){var n=l(e);if(!(e.readonly||n instanceof U)){var t="ans",r=void 0,i=e.createDef(t);return new U(t,r,n,i)}return n}function l(e){if(Q==H.SYMBOL&&"function"==X){if(r(),Q!=H.SYMBOL)throw D("Function name expected");var n=X;if(r(),"("!=X)throw D("Opening parenthesis ( expected");for(var t=e.createNestedScope(),i=[],a=[];;){if(r(),Q!=H.SYMBOL)throw D("Variable name expected");var o=X,s=t.createDef(o);if(i.push(o),a.push(s),r(),","!=X){if(")"==X)break;throw D('Comma , or closing parenthesis ) expected"')}}if(r(),"="!=X)throw D("Equal sign = expected");r();var f=m(t),u=e.createDef(n);return new R(n,i,a,f,u)}return h(e)}function h(e){var n=!1;Q==H.SYMBOL&&(n=e.hasLink(X));var t=m(e);if("="==X){if(!(t instanceof M))throw D("Symbol expected at the left hand side of assignment operator =");var i=t.name,a=t.params;n||e.removeLink(i),r();var o=m(e),s=t.hasParams()?e.createUpdate(i):e.createDef(i);return new U(i,a,o,s)}return t}function m(e){var n=p(e);if(":"==X){for(var t=[n];":"==X;)r(),t.push(p(e));if(t.length>3)throw new TypeError("Invalid range");var i="range",a=Z.range;n=new M(i,a,t)}return n}function p(e){for(var n=v(e),t={"in":"in"};void 0!==t[X];){var i=X,a=Z[t[i]];r();var o=[n,v(e)];n=new M(i,a,o)}return n}function v(e){var n=g(e);return n}function g(e){for(var n=w(e),t={"==":"equal","!=":"unequal","<":"smaller",">":"larger","<=":"smallereq",">=":"largereq"};void 0!==t[X];){var i=X,a=Z[t[i]];r();var o=[n,w(e)];n=new M(i,a,o)}return n}function w(e){for(var n=d(e),t={"+":"add","-":"subtract"};void 0!==t[X];){var i=X,a=Z[t[i]];r();var o=[n,d(e)];n=new M(i,a,o)}return n}function d(e){for(var n=y(e),t={"*":"multiply","/":"divide","%":"mod",mod:"mod"};void 0!==t[X];){var i=X,a=Z[t[i]];r();var o=[n,y(e)];n=new M(i,a,o)}return n}function y(e){if("-"==X){var n=X,t=Z.unaryminus;r();var i=[N(e)];return new M(n,t,i)}return N(e)}function N(e){for(var n=[O(e)];"^"==X;)r(),n.push(O(e));for(var t=n.pop();n.length;){var i=n.pop(),a="^",o=Z.pow,s=[i,t];t=new M(a,o,s)}return t}function O(e){for(var n=x(e);"!"==X;){var t=X,i=Z.factorial;r();var a=[n];n=new M(t,i,a)}return n}function x(e){for(var n=b(e);"'"==X;){var t=X,i=Z.transpose;r();var a=[n];n=new M(t,i,a)}return n}function b(e){return L(e)}function L(e){if(Q==H.SYMBOL){var n=X;r();var t=e.createLink(n),i=_(e),a=new M(n,t,i);return a}return z(e)}function _(e){var n=[];if("("==X){if(r(),")"!=X)for(n.push(m(e));","==X;)r(),n.push(m(e));if(")"!=X)throw D("Parenthesis ) missing");r()}return n}function z(n){if('"'==X){for(var t="",i="";""!=K&&('"'!=K||"\\"==i);)t+=K,i=K,e();if(r(),'"'!=X)throw D('End of string " missing');r();var a=new A(t);return a}return q(n)}function q(e){if("["==X){var n;for(r();"\n"==X;)r();if("]"!=X){var t=[],i=0,a=0;for(t[0]=[m(e)];","==X||";"==X;){for(","==X?a++:(i++,a=0,t[i]=[]),r();"\n"==X;)r();for(t[i][a]=m(e);"\n"==X;)r()}var o=t.length,s=t.length>0?t[0].length:0;for(i=1;o>i;i++)if(t[i].length!=s)throw F("Number of columns must match ("+t[i].length+" != "+s+")");if("]"!=X)throw D("End of matrix ] missing");r(),n=new S(t)}else r(),n=new S([[]]);return n}return I(e)}function I(e){if(Q==H.NUMBER){var t;t="."==X?0:Number(X),r();var i;if(Q==H.SYMBOL){if("i"==X||"I"==X)return i=new n(0,t),r(),new A(i);if(E.isPlainUnit(X))return i=new E(t,X),r(),new A(i);throw k('Unknown unit "'+X+'"')}var a=new A(t);return a}return P(e)}function P(e){if("("==X){r();var n=m(e);if(")"!=X)throw D("Parenthesis ) expected");return r(),n}return C(e)}function C(){throw""==X?D("Unexpected end of expression"):D("Value expected")}function B(){return void 0}function G(){return W-X.length+1}function V(e){var n=B(),t=G();return void 0===n?void 0===t?e:e+" (char "+t+")":e+" (line "+n+", char "+t+")"}function D(e){return new SyntaxError(V(e))}function k(e){return new TypeError(V(e))}function F(e){return Error(V(e))}Z.expr.Parser=function j(e){if(this.constructor!=j)throw new SyntaxError("Parser constructor must be called with the new operator");this.scope=new Z.expr.Scope(null,e)},Z.expr.Parser.prototype.parse=function(e,n){return Y=e||"",n||(n=this.scope),f(n)},Z.expr.Parser.prototype.eval=function(e){var n=this.parse(e);return n.eval()},Z.expr.Parser.prototype.get=function(e){var n=this.scope.findDef(e);return n?n.value:void 0},Z.expr.Parser.prototype.set=function(e,n){this.scope.createDef(e,n)},Z.expr.Parser.prototype.clear=function(){this.scope.clear()};var H={NULL:0,DELIMITER:1,NUMBER:2,SYMBOL:3,UNKNOWN:4},Y="",W=0,K="",X="",Q=H.NULL}(),function(){function e(){this.idMax=-1,this.updateSeq=0,this.parser=new Z.expr.Parser,this.scope=new Z.expr.Scope,this.nodes={},this.firstNode=void 0,this.lastNode=void 0}Z.expr.Workspace=e,e.prototype.clear=function(){this.nodes={},this.firstNode=void 0,this.lastNode=void 0},e.prototype.append=function(n){var t=this._getNewId(),r=this.lastNode?this.lastNode.scope:this.scope,i=new Z.expr.Scope(r),a=new e.Node({id:t,expression:n,parser:this.parser,scope:i,nextNode:void 0,previousNode:this.lastNode});return this.nodes[t]=a,this.firstNode||(this.firstNode=a),this.lastNode&&(this.lastNode.nextNode=a),this.lastNode=a,this._update([t]),t},e.prototype.insertBefore=function(n,t){var r=this.nodes[t];if(!r)throw'Node with id "'+t+'" not found';var i=r.previousNode,a=this._getNewId(),o=i?i.scope:this.scope,s=new Z.expr.Scope(o),f=new e.Node({id:a,expression:n,parser:this.parser,scope:s,nextNode:r,previousNode:i});this.nodes[a]=f,i?i.nextNode=f:this.firstNode=f,r.previousNode=f,r.scope.parentScope=f.scope;var u=this.getDependencies(a);return-1==u.indexOf(a)&&u.unshift(a),this._update(u),a},e.prototype.insertAfter=function(e,n){var t=this.nodes[n];if(!t)throw'Node with id "'+n+'" not found';return t==this.lastNode?this.append(e):this.insertBefore(n+1,e)},e.prototype.remove=function(e){var n=this.nodes[e];if(!n)throw'Node with id "'+e+'" not found';var t=this.getDependencies(e),r=n.previousNode,i=n.nextNode;r?r.nextNode=i:this.firstNode=i,i?i.previousNode=r:this.lastNode=r;var a=r?r.scope:this.scope;i&&(i.scope.parentScope=a),delete this.nodes[e],this._update(t)},e.prototype.replace=function(n,t){var r=this.nodes[t];if(!r)throw'Node with id "'+t+'" not found';var i=[t];e._merge(i,this.getDependencies(t));var a=r.previousNode;r.nextNode,a?a.scope:this.scope,r.setExpr(n),e._merge(i,this.getDependencies(t)),this._update(i)},e.Node=function(e){this.id=e.id,this.parser=e.parser,this.scope=e.scope,this.nextNode=e.nextNode,this.previousNode=e.previousNode,this.updateSeq=0,this.result=void 0,this.setExpr(e.expression)},e.Node.prototype.setExpr=function(e){this.expression=e||"",this.scope.clear(),this._parse()},e.Node.prototype.getExpr=function(){return this.expression},e.Node.prototype.getResult=function(){return this.result},e.Node.prototype._parse=function(){try{this.fn=this.parser.parse(this.expression,this.scope)}catch(e){var n="Error: "+((e.message||e)+"");this.fn=new A(n)}},e.Node.prototype.eval=function(){try{this.scope.init(),this.result=this.fn.eval()}catch(e){this.scope.init(),this.result="Error: "+((e.message||e)+"")}return this.result},e._merge=function(e,n){for(var t=0,r=n.length;r>t;t++){var i=n[t];-1==e.indexOf(i)&&e.push(i)}},e.prototype.getDependencies=function(n){var t,r=[],i=this.nodes[n];if(i){var a=i.scope.defs,o=i.scope.updates,s=[];for(t in a)a.hasOwnProperty(t)&&s.push(t);for(t in o)o.hasOwnProperty(t)&&-1==s.indexOf(t)&&s.push(t);for(var f=i.nextNode;f&&s.length;){for(var u=f.scope,c=0;s.length>c;){if(t=s[c],(u.hasLink(t)||u.hasUpdate(t))&&-1==r.indexOf(f.id)){r.push(f.id);var l=this.getDependencies(f.id);e._merge(r,l)}u.hasDef(t)&&(s.splice(c,1),c--),c++}f=f.nextNode}}return r},e.prototype.getExpr=function(e){var n=this.nodes[e];if(!n)throw'Node with id "'+e+'" not found';return n.getExpr()},e.prototype.getResult=function(e){var n=this.nodes[e];if(!n)throw'Node with id "'+e+'" not found';return n.getResult()},e.prototype._update=function(e){this.updateSeq++;for(var n=this.updateSeq,t=this.nodes,r=0,i=e.length;i>r;r++){var a=e[r],o=t[a];o&&(o.eval(),o.updateSeq=n)}},e.prototype.getChanges=function(e){var n=[],t=this.firstNode;for(e=e||0;t;)t.updateSeq>e&&n.push(t.id),t=t.nextNode;return{ids:n,updateSeq:this.updateSeq}},e.prototype._getNewId=function(){return this.idMax++,this.idMax},e.prototype.toString=function(){return JSON.stringify(this.toJSON())},e.prototype.toJSON=function(){for(var e=[],n=this.firstNode;n;){var t={id:n.id,expression:n.expression,dependencies:this.getDependencies(n.id)};try{t.result=n.getResult()}catch(r){t.result="Error: "+((r.message||r)+"")}e.push(t),n=n.nextNode}return e}}(),Z.abs=function(e){if(1!=arguments.length)throw x("abs",arguments.length,1);if(v(e))return Math.abs(e);if(e instanceof n)return Math.sqrt(e.re*e.re+e.im*e.im);if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.abs);if(e.valueOf()!==e)return Z.abs(e.valueOf());throw O("abs",e)},Z.add=function(e,r){if(2!=arguments.length)throw x("add",arguments.length,2);if(v(e)){if(v(r))return e+r;if(r instanceof n)return new n(e+r.re,r.im)}else if(e instanceof n){if(v(r))return new n(e.re+r,e.im);if(r instanceof n)return new n(e.re+r.re,e.im+r.im)}else if(e instanceof E&&r instanceof E){if(!e.equalBase(r))throw Error("Units do not match");if(!e.hasValue)throw Error("Unit on left hand side of operator + has no value");if(!r.hasValue)throw Error("Unit on right hand side of operator + has no value");var i=e.clone();return i.value+=r.value,i.fixPrefix=!1,i}if(y(e)||y(r))return e+r;if(e instanceof Array||e instanceof t||e instanceof w||r instanceof Array||r instanceof t||r instanceof w)return K.map2(e,r,Z.add);if(e.valueOf()!==e||r.valueOf()!==r)return Z.add(e.valueOf(),r.valueOf());throw O("add",e,r)},Z.ceil=function(e){if(1!=arguments.length)throw x("ceil",arguments.length,1);if(v(e))return Math.ceil(e);if(e instanceof n)return new n(Math.ceil(e.re),Math.ceil(e.im));if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.ceil);if(e.valueOf()!==e)return Z.ceil(e.valueOf());throw O("ceil",e)},Z.cube=function(e){if(1!=arguments.length)throw x("cube",arguments.length,1);if(v(e))return e*e*e;if(e instanceof n)return Z.multiply(Z.multiply(e,e),e);if(e instanceof Array||e instanceof t||e instanceof w)return Z.multiply(Z.multiply(e,e),e);if(e.valueOf()!==e)return Z.cube(e.valueOf());throw O("cube",e)},Z.divide=function(e,r){if(2!=arguments.length)throw x("divide",arguments.length,2);if(v(e)){if(v(r))return e/r;if(r instanceof n)return _(new n(e,0),r)}if(e instanceof n){if(v(r))return _(e,new n(r,0));if(r instanceof n)return _(e,r)}if(e instanceof E&&v(r)){var i=e.clone();return i.value/=r,i}if(e instanceof Array||e instanceof t)return r instanceof Array||r instanceof t?Z.multiply(e,Z.inv(r)):K.map2(e,r,Z.divide);if(r instanceof Array||r instanceof t)return Z.multiply(e,Z.inv(r));if(e.valueOf()!==e||r.valueOf()!==r)return Z.divide(e.valueOf(),r.valueOf());throw O("divide",e,r)},Z.equal=function $(e,r){if(2!=arguments.length)throw x("equal",arguments.length,2);if(v(e)){if(v(r))return e==r;if(r instanceof n)return e==r.re&&0==r.im}if(e instanceof n){if(v(r))return e.re==r&&0==e.im;if(r instanceof n)return e.re==r.re&&e.im==r.im}if(e instanceof E&&r instanceof E){if(!e.equalBase(r))throw Error("Cannot compare units with different base");return e.value==r.value}if(y(e)||y(r))return e==r;if(e instanceof Array||e instanceof t||e instanceof w||r instanceof Array||r instanceof t||r instanceof w)return K.map2(e,r,Z.equal);if(e.valueOf()!==e||r.valueOf()!==r)return $(e.valueOf(),r.valueOf());throw O("equal",e,r)},Z.exp=function(e){if(1!=arguments.length)throw x("exp",arguments.length,1);if(v(e))return Math.exp(e);if(e instanceof n){var r=Math.exp(e.re);return new n(r*Math.cos(e.im),r*Math.sin(e.im))}if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.exp);if(e.valueOf()!==e)return Z.exp(e.valueOf());throw O("exp",e)},Z.fix=function(e){if(1!=arguments.length)throw x("fix",arguments.length,1);if(v(e))return e>0?Math.floor(e):Math.ceil(e);if(e instanceof n)return new n(e.re>0?Math.floor(e.re):Math.ceil(e.re),e.im>0?Math.floor(e.im):Math.ceil(e.im));if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.fix);if(e.valueOf()!==e)return Z.fix(e.valueOf());throw O("fix",e)},Z.floor=function(e){if(1!=arguments.length)throw x("floor",arguments.length,1);if(v(e))return Math.floor(e);if(e instanceof n)return new n(Math.floor(e.re),Math.floor(e.im));if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.floor);if(e.valueOf()!==e)return Z.floor(e.valueOf());throw O("floor",e)},Z.gcd=function(){var e,n=arguments[0],r=arguments[1];if(2==arguments.length){if(v(n)&&v(r)){if(!g(n)||!g(r))throw Error("Parameters in function gcd must be integer numbers");for(;0!=r;)e=r,r=n%e,n=e;return Math.abs(n)}if(n instanceof Array||n instanceof t||r instanceof Array||r instanceof t)return K.map2(n,r,Z.gcd);if(n.valueOf()!==n||r.valueOf()!==r)return Z.gcd(n.valueOf(),r.valueOf());throw O("gcd",n,r)}if(arguments.length>2){for(var i=1;arguments.length>i;i++)n=Z.gcd(n,arguments[i]);return n}throw new SyntaxError("Function gcd expects two or more arguments")},Z.larger=function(e,r){if(2!=arguments.length)throw x("larger",arguments.length,2);if(v(e)){if(v(r))return e>r;if(r instanceof n)return e>Z.abs(r)}if(e instanceof n){if(v(r))return Z.abs(e)>r;if(r instanceof n)return Z.abs(e)>Z.abs(r)}if(e instanceof E&&r instanceof E){if(!e.equalBase(r))throw Error("Cannot compare units with different base");return e.value>r.value}if(y(e)||y(r))return e>r;if(e instanceof Array||e instanceof t||e instanceof w||r instanceof Array||r instanceof t||r instanceof w)return K.map2(e,r,Z.larger);if(e.valueOf()!==e||r.valueOf()!==r)return Z.larger(e.valueOf(),r.valueOf());throw O("larger",e,r)},Z.largereq=function(e,r){if(2!=arguments.length)throw x("largereq",arguments.length,2);if(v(e)){if(v(r))return e>=r;if(r instanceof n)return e>=Z.abs(r)}if(e instanceof n){if(v(r))return Z.abs(e)>=r;if(r instanceof n)return Z.abs(e)>=Z.abs(r)}if(e instanceof E&&r instanceof E){if(!e.equalBase(r))throw Error("Cannot compare units with different base");return e.value>=r.value}if(y(e)||y(r))return e>=r;if(e instanceof Array||e instanceof t||e instanceof w||r instanceof Array||r instanceof t||r instanceof w)return K.map2(e,r,Z.largereq);if(e.valueOf()!==e||r.valueOf()!==r)return Z.largereq(e.valueOf(),r.valueOf());throw O("largereq",e,r)},Z.lcm=function(){var e,n=arguments[0],r=arguments[1];if(2==arguments.length){if(v(n)&&v(r)){if(!g(n)||!g(r))throw Error("Parameters in function lcm must be integer numbers");for(var i=n*r;0!=r;)e=r,r=n%e,n=e;return Math.abs(i/n)}if(n instanceof Array||n instanceof t||r instanceof Array||r instanceof t)return K.map2(n,r,Z.lcm);if(n.valueOf()!==n||r.valueOf()!==r)return Z.lcm(n.valueOf(),r.valueOf());throw O("lcm",n,r)}if(arguments.length>2){for(var a=1;arguments.length>a;a++)n=Z.lcm(n,arguments[a]);return n}throw new SyntaxError("Function lcm expects two or more arguments")},Z.log=function(e,r){if(1!=arguments.length&&2!=arguments.length)throw x("log",arguments.length,1,2);if(void 0!==r)return Z.divide(Z.log(e),Z.log(r));if(v(e))return e>=0?Math.log(e):Z.log(new n(e,0));if(e instanceof n)return new n(Math.log(Math.sqrt(e.re*e.re+e.im*e.im)),Math.atan2(e.im,e.re));if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.log);if(e.valueOf()!==e||r.valueOf()!==r)return Z.log(e.valueOf(),r.valueOf());throw O("log",e,r)},Z.log10=function(e){if(1!=arguments.length)throw x("log10",arguments.length,1);if(v(e))return e>=0?Math.log(e)/Math.LN10:Z.log10(new n(e,0));if(e instanceof n)return new n(Math.log(Math.sqrt(e.re*e.re+e.im*e.im))/Math.LN10,Math.atan2(e.im,e.re)/Math.LN10);if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.log10);if(e.valueOf()!==e)return Z.log10(e.valueOf());throw O("log10",e)},Z.mod=function(e,r){if(2!=arguments.length)throw x("mod",arguments.length,2);if(v(e)){if(v(r))return e%r;if(r instanceof n&&0==r.im)return e%r.re}else if(e instanceof n&&0==e.im){if(v(r))return e.re%r;if(r instanceof n&&0==r.im)return e.re%r.re}if(e instanceof Array||e instanceof t||e instanceof w||r instanceof Array||r instanceof t||r instanceof w)return K.map2(e,r,Z.mod);if(e.valueOf()!==e||r.valueOf()!==r)return Z.mod(e.valueOf(),r.valueOf());throw O("mod",e,r)},Z.multiply=function(e,r){if(2!=arguments.length)throw x("multiply",arguments.length,2);if(v(e)){if(v(r))return e*r;if(r instanceof n)return z(new n(e,0),r);if(r instanceof E)return o=r.clone(),o.value*=e,o}else if(e instanceof n){if(v(r))return z(e,new n(r,0));if(r instanceof n)return z(e,r)}else if(e instanceof E){if(v(r))return o=e.clone(),o.value*=r,o}else{if(e instanceof Array){if(r instanceof Array){var i=K.size(e),a=K.size(r);if(2!=i.length)throw Error("Can only multiply a 2 dimensional matrix (A has "+i.length+" dimensions)");if(2!=a.length)throw Error("Can only multiply a 2 dimensional matrix (B has "+a.length+" dimensions)");if(i[1]!=a[0])throw new RangeError("Dimensions mismatch in multiplication. Columns of A must match rows of B (A is "+i[0]+"x"+i[1]+", B is "+a[0]+"x"+a[1]+", "+a[1]+" != "+a[0]+")");for(var o=[],s=i[0],f=a[1],u=i[1],c=Z.multiply,l=Z.add,h=0;s>h;h++){o[h]=[];for(var m=0;f>m;m++){for(var p=null,g=0;u>g;g++){var w=c(e[h][g],r[g][m]);p=null==p?w:l(p,w)}o[h][m]=p}}return o}return r instanceof t?new t(Z.multiply(e.valueOf(),r.valueOf())):K.map2(e,r,Z.multiply)}if(e instanceof t)return new t(Z.multiply(e.valueOf(),r.valueOf()))}if(r instanceof Array)return K.map2(e,r,Z.multiply);if(r instanceof t)return new t(Z.multiply(e.valueOf(),r.valueOf()));if(e.valueOf()!==e||r.valueOf()!==r)return Z.multiply(e.valueOf(),r.valueOf());throw O("multiply",e,r)},Z.pow=function(e,r){if(2!=arguments.length)throw x("pow",arguments.length,2);if(v(e)){if(v(r))return g(r)||e>=0?Math.pow(e,r):q(new n(e,0),new n(r,0));if(r instanceof n)return q(new n(e,0),r)}else if(e instanceof n){if(v(r))return q(e,new n(r,0));if(r instanceof n)return q(e,r)}else{if(e instanceof Array){if(!v(r)||!g(r)||0>r)throw new TypeError("For A^b, b must be a positive integer (value is "+r+")");var i=K.size(e);if(2!=i.length)throw Error("For A^b, A must be 2 dimensional (A has "+i.length+" dimensions)");if(i[0]!=i[1])throw Error("For A^b, A must be square (size is "+i[0]+"x"+i[1]+")");if(0==r)return Z.eye(i[0]);for(var a=e,o=1;r>o;o++)a=Z.multiply(e,a);return a}if(e instanceof t)return new t(Z.pow(e.valueOf(),r))}if(e.valueOf()!==e||r.valueOf()!==r)return Z.pow(e.valueOf(),r.valueOf());throw O("pow",e,r)},Z.round=function(e,r){if(1!=arguments.length&&2!=arguments.length)throw x("round",arguments.length,1,2);if(void 0==r){if(v(e))return Math.round(e);if(e instanceof n)return new n(Math.round(e.re),Math.round(e.im));if((e instanceof Array||e instanceof t||e instanceof w)&&K.map(e,Z.round),e.valueOf()!==e)return Z.round(e.valueOf());throw O("round",e)}if(!v(r))throw new TypeError("Number of digits in function round must be an integer");if(r!==Math.round(r))throw new TypeError("Number of digits in function round must be integer");if(0>r||r>9)throw Error("Number of digits in function round must be in te range of 0-9");if(v(e))return I(e,r);if(e instanceof n)return new n(I(e.re,r),I(e.im,r));if(e instanceof Array||e instanceof t||e instanceof w||r instanceof Array||r instanceof t||r instanceof w)return K.map2(e,r,Z.round);if(e.valueOf()!==e||r.valueOf()!==r)return Z.round(e.valueOf(),r.valueOf());throw O("round",e,r)},Z.sign=function(e){if(1!=arguments.length)throw x("sign",arguments.length,1);if(v(e)){var r;return r=e>0?1:0>e?-1:0}if(e instanceof n){var i=Math.sqrt(e.re*e.re+e.im*e.im);return new n(e.re/i,e.im/i)}if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.sign);if(e.valueOf()!==e)return Z.sign(e.valueOf());throw O("sign",e)},Z.smaller=function(e,r){if(2!=arguments.length)throw x("smaller",arguments.length,2);if(v(e)){if(v(r))return r>e;if(r instanceof n)return Z.abs(r)>e}if(e instanceof n){if(v(r))return r>Z.abs(e);if(r instanceof n)return Z.abs(e)e;if(e instanceof Array||e instanceof t||e instanceof w||r instanceof Array||r instanceof t||r instanceof w)return K.map2(e,r,Z.smaller);if(e.valueOf()!==e||r.valueOf()!==r)return Z.smaller(e.valueOf(),r.valueOf());throw O("smaller",e,r)},Z.smallereq=function(e,r){if(2!=arguments.length)throw x("smallereq",arguments.length,2);if(v(e)){if(v(r))return r>=e;if(r instanceof n)return Z.abs(r)>=e}if(e instanceof n){if(v(r))return r>=Z.abs(e);if(r instanceof n)return Z.abs(e)<=Z.abs(r)}if(e instanceof E&&r instanceof E){if(!e.equalBase(r))throw Error("Cannot compare units with different base");return e.value<=r.value}if(y(e)||y(r))return r>=e;if(e instanceof Array||e instanceof t||e instanceof w||r instanceof Array||r instanceof t||r instanceof w)return K.map2(e,r,Z.smallereq);if(e.valueOf()!==e||r.valueOf()!==r)return Z.smallereq(e.valueOf(),r.valueOf());throw O("smallereq",e,r)},Z.sqrt=function(e){if(1!=arguments.length)throw x("sqrt",arguments.length,1);if(v(e))return e>=0?Math.sqrt(e):Z.sqrt(new n(e,0));if(e instanceof n){var r=Math.sqrt(e.re*e.re+e.im*e.im);return e.im>=0?new n(.5*Math.sqrt(2*(r+e.re)),.5*Math.sqrt(2*(r-e.re))):new n(.5*Math.sqrt(2*(r+e.re)),-.5*Math.sqrt(2*(r-e.re)))}if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.sqrt);if(e.valueOf()!==e)return Z.sqrt(e.valueOf());throw O("sqrt",e)},Z.square=function(e){if(1!=arguments.length)throw x("square",arguments.length,1);if(v(e))return e*e;if(e instanceof n)return Z.multiply(e,e);if(e instanceof Array||e instanceof t||e instanceof w)return Z.multiply(e,e);if(e.valueOf()!==e)return Z.square(e.valueOf());throw O("square",e)},Z.subtract=function(e,r){if(2!=arguments.length)throw x("subtract",arguments.length,2);if(v(e)){if(v(r))return e-r;if(r instanceof n)return new n(e-r.re,r.im)}else if(e instanceof n){if(v(r))return new n(e.re-r,e.im);if(r instanceof n)return new n(e.re-r.re,e.im-r.im)}else if(e instanceof E&&r instanceof E){if(!e.equalBase(r))throw Error("Units do not match");if(!e.hasValue)throw Error("Unit on left hand side of operator - has no value");if(!r.hasValue)throw Error("Unit on right hand side of operator - has no value");var i=e.clone();return i.value-=r.value,i.fixPrefix=!1,i}if(e instanceof Array||e instanceof t||e instanceof w||r instanceof Array||r instanceof t||r instanceof w)return K.map2(e,r,Z.subtract);if(e.valueOf()!==e||r.valueOf()!==r)return Z.subtract(e.valueOf(),r.valueOf());throw O("subtract",e,r)},Z.unaryminus=function(e){if(1!=arguments.length)throw x("unaryminus",arguments.length,1);if(v(e))return-e;if(e instanceof n)return new n(-e.re,-e.im);if(e instanceof E){var r=e.clone();return r.value=-e.value,r}if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.unaryminus);if(e.valueOf()!==e)return Z.unaryminus(e.valueOf());throw O("unaryminus",e)},Z.unequal=function(e,r){if(2!=arguments.length)throw x("unequal",arguments.length,2);if(v(e)){if(v(r))return e==r;if(r instanceof n)return e==r.re&&0==r.im}if(e instanceof n){if(v(r))return e.re==r&&0==e.im;if(r instanceof n)return e.re==r.re&&e.im==r.im}if(e instanceof E&&r instanceof E){if(!e.equalBase(r))throw Error("Cannot compare units with different base");return e.value==r.value}if(y(e)||y(r))return e==r;if(e instanceof Array||e instanceof t||e instanceof w||r instanceof Array||r instanceof t||r instanceof w)return K.map2(e,r,Z.unequal);if(e.valueOf()!==e||r.valueOf()!==r)return Z.unequal(e.valueOf(),r.valueOf());throw O("unequal",e,r)},Z.arg=function(e){if(1!=arguments.length)throw x("arg",arguments.length,1);if(v(e))return Math.atan2(0,e);if(e instanceof n)return Math.atan2(e.im,e.re);if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.arg);if(e.valueOf()!==e)return Z.arg(e.valueOf());throw O("arg",e)},Z.conj=function(e){if(1!=arguments.length)throw x("conj",arguments.length,1);if(v(e))return e;if(e instanceof n)return new n(e.re,-e.im);if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.conj); +if(e.valueOf()!==e)return Z.conj(e.valueOf());throw O("conj",e)},Z.im=function(e){if(1!=arguments.length)throw x("im",arguments.length,1);if(v(e))return 0;if(e instanceof n)return e.im;if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.im);if(e.valueOf()!==e)return Z.im(e.valueOf());throw O("im",e)},Z.re=function(e){if(1!=arguments.length)throw x("re",arguments.length,1);if(v(e))return e;if(e instanceof n)return e.re;if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.re);if(e.valueOf()!==e)return Z.re(e.valueOf());throw O("re",e)},Z.complex=function(){switch(arguments.length){case 0:return new n(0,0);case 1:var e=arguments[0];if(!y(e))throw new TypeError("Two numbers or a single string expected in function complex");var t=n.parse(e);if(t)return t;throw new SyntaxError('String "'+e+'" is no valid complex number');case 2:return new n(arguments[0],arguments[1]);default:throw x("complex",arguments.length,0,2)}},Z.matrix=function(e){if(arguments.length>1)throw x("matrix",arguments.length,0,1);return new t(e)},Z.parser=function(){return new Z.expr.Parser},Z.range=function(e){switch(arguments.length){case 1:if(!y(e))throw new TypeError("Two or three numbers or a single string expected in function range");var n=w.parse(e);if(n)return n;throw new SyntaxError('String "'+n+'" is no valid range');case 2:return new w(arguments[0],null,arguments[1]);case 3:return new w(arguments[0],arguments[1],arguments[2]);default:throw x("range",arguments.length,2,3)}},Z.unit=function(){switch(arguments.length){case 1:var e=arguments[0];if(!y(e))throw new TypeError("A string or a number and string expected in function unit");if(E.isPlainUnit(e))return new E(null,e);var n=E.parse(e);if(n)return n;throw new SyntaxError('String "'+e+'" is no valid unit');case 2:return new E(arguments[0],arguments[1]);default:throw x("unit",arguments.length,1,2)}},Z.workspace=function(){return new Z.expr.Workspace},Z.concat=function(){var e,n,r=arguments.length,i=-1,a=!1,o=[];for(e=0;r>e;e++){var s=arguments[e];if(s instanceof t&&(a=!0),e==r-1&&v(s)){if(n=i,i=s,!g(i)||1>i)throw new TypeError("Dimension number must be a positive integer (dim = "+i+")");if(e>0&&i>n)throw new RangeError("Dimension out of range ("+i+" > "+n+")")}else{if(!(s instanceof Array||s instanceof t))throw O("concat",s);var f=Z.clone(s.valueOf()),u=Z.size(s);if(o[e]=f,n=i,i=u.length,e>0&&i!=n)throw new RangeError("Dimension mismatch ("+n+" != "+i+")")}}if(0==o.length)throw new SyntaxError("At least one matrix expected");for(var c=o.shift();o.length;)c=P(c,o.shift(),i-1,0);return a?new t(c):c},Z.det=function(e){if(1!=arguments.length)throw x("det",arguments.length,1);var n=Z.size(e);switch(n.length){case 0:return Z.clone(e);case 1:if(1==n[0])return Z.clone(e.valueOf()[0]);throw new RangeError("Matrix must be square (size: "+Z.format(n)+")");case 2:var t=n[0],r=n[1];if(t==r)return C(e.valueOf(),t,r);throw new RangeError("Matrix must be square (size: "+Z.format(n)+")");default:throw new RangeError("Matrix must be two dimensional (size: "+Z.format(n)+")")}},Z.diag=function(e,n){var r,i,a,o;if(1!=arguments.length&&2!=arguments.length)throw x("diag",arguments.length,1,2);if(n){if(!v(n)||!g(n))throw new TypeError("Second parameter in function diag must be an integer")}else n=0;var s=n>0?n:0,f=0>n?-n:0;e instanceof t||e instanceof w||(e=new t(e));var u;switch(e.isVector()?(e=e.toVector(),u=[e.length]):u=e.size(),u.length){case 1:i=e.valueOf();var c=new t;for(c.resize([i.length+f,i.length+s]),r=c.valueOf(),o=i.length,a=0;o>a;a++)r[a+f][a+s]=Z.clone(i[a]);return c;case 2:for(i=[],r=e.valueOf(),o=Math.min(u[0]-f,u[1]-s),a=0;o>a;a++)i[a]=Z.clone(r[a+f][a+s]);return new t(i);default:throw new RangeError("Matrix for function diag must be 2 dimensional")}},Z.eye=function(){var e=K.argsToArray(arguments);if(0==e.length)e=[1,1];else if(1==e.length)e[1]=e[0];else if(e.length>2)throw x("eye",e.length,0,2);var n=e[0],r=e[1];if(!v(n)||!g(n)||1>n)throw Error("Parameters in function eye must be positive integers");if(r&&(!v(r)||!g(r)||1>r))throw Error("Parameters in function eye must be positive integers");var i=new t;i.resize(e);for(var a=Z.min(e),o=i.valueOf(),s=0;a>s;s++)o[s][s]=1;return i},Z.inv=function(e){if(1!=arguments.length)throw x("inv",arguments.length,1);var n=Z.size(e);switch(n.length){case 0:return Z.divide(1,e);case 1:if(1==n[0])return e instanceof t?new t([Z.divide(1,e.valueOf()[0])]):[Z.divide(1,e[0])];throw new RangeError("Matrix must be square (size: "+Z.format(n)+")");case 2:var r=n[0],i=n[1];if(r==i)return e instanceof t?new t(G(e.valueOf(),r,i)):G(e,r,i);throw new RangeError("Matrix must be square (size: "+Z.format(n)+")");default:throw new RangeError("Matrix must be two dimensional (size: "+Z.format(n)+")")}},Z.ones=function(){var e=K.argsToArray(arguments);0==e.length?e=[1,1]:1==e.length&&(e[1]=e[0]);var n=new t,r=1;return n.resize(e,r),n},Z.size=function(e){if(1!=arguments.length)throw x("size",arguments.length,1);if(v(e)||e instanceof n||e instanceof E||null==e)return[];if(y(e))return[e.length];if(e instanceof Array)return K.size(e);if(e instanceof t||e instanceof w)return e.size();if(e.valueOf()!==e)return Z.size(e.valueOf());throw O("size",e)},Z.squeeze=function(e){if(1!=arguments.length)throw x("squeeze",arguments.length,1);return e instanceof t||e instanceof w?V(e.toArray()):e instanceof Array?V(Z.clone(e)):Z.clone(e)},Z.transpose=function(e){if(1!=arguments.length)throw x("transpose",arguments.length,1);var n=Z.size(e);switch(n.length){case 0:return Z.clone(e);case 1:return Z.clone(e);case 2:for(var r,i=n[1],a=n[0],o=e instanceof t,s=e.valueOf(),f=[],u=Z.clone,c=0;i>c;c++){r=f[c]=[];for(var l=0;a>l;l++)r[l]=u(s[l][c])}return 0==a&&(f[0]=[]),o?new t(f):f;default:throw new RangeError("Matrix must be two dimensional (size: "+Z.format(n)+")")}},Z.zeros=function(){var e=K.argsToArray(arguments);0==e.length?e=[1,1]:1==e.length&&(e[1]=e[0]);var n=new t;return n.resize(e),n},Z.factorial=function(e){if(1!=arguments.length)throw x("factorial",arguments.length,1);if(v(e)){if(!g(e))throw new TypeError("Function factorial can only handle integer values");var n=e,r=n;for(n--;n>1;)r*=n,n--;return 0==r&&(r=1),r}if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.factorial);if(e.valueOf()!==e)return Z.factorial(e.valueOf());throw O("factorial",e)},Z.random=function(){if(0!=arguments.length)throw x("random",arguments.length,0);return Math.random()},Z.max=function(e){if(0==arguments.length)throw Error("Function max requires one or more parameters (0 provided)");if(e instanceof Array||e instanceof t||e instanceof w){if(arguments.length>1)throw Error("Wrong number of parameters (1 matrix or multiple scalars expected)");var n=Z.size(e);if(1==n.length){if(0==e.length)throw Error("Cannot calculate max of an empty vector");return D(e.valueOf())}if(2==n.length){if(0==n[0]||0==n[1])throw Error("Cannot calculate max of an empty matrix");if(e instanceof Array)return k(e,n[0],n[1]);if(e instanceof t||e instanceof w)return new t(k(e.valueOf(),n[0],n[1]));throw O("max",e)}throw new RangeError("Cannot calculate max for multi dimensional matrix")}return D(arguments)},Z.min=function(e){if(0==arguments.length)throw Error("Function min requires one or more parameters (0 provided)");if(e instanceof Array||e instanceof t||e instanceof w){if(arguments.length>1)throw Error("Wrong number of parameters (1 matrix or multiple scalars expected)");var n=Z.size(e);if(1==n.length){if(0==e.length)throw Error("Cannot calculate min of an empty vector");return F(e.valueOf())}if(2==n.length){if(0==n[0]||0==n[1])throw Error("Cannot calculate min of an empty matrix");if(e instanceof Array)return j(e,n[0],n[1]);if(e instanceof t||e instanceof w)return new t(j(e.valueOf(),n[0],n[1]));throw O("min",e)}throw new RangeError("Cannot calculate min for multi dimensional matrix")}return F(arguments)},Z.acos=function(e){if(1!=arguments.length)throw x("acos",arguments.length,1);if(v(e))return e>=-1&&1>=e?Math.acos(e):Z.acos(new n(e,0));if(e instanceof n){var r=new n(e.im*e.im-e.re*e.re+1,-2*e.re*e.im),i=Z.sqrt(r),a=new n(i.re-e.im,i.im+e.re),o=Z.log(a);return new n(1.5707963267948966-o.im,o.re)}if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.acos);if(e.valueOf()!==e)return Z.acos(e.valueOf());throw O("acos",e)},Z.asin=function(e){if(1!=arguments.length)throw x("asin",arguments.length,1);if(v(e))return e>=-1&&1>=e?Math.asin(e):Z.asin(new n(e,0));if(e instanceof n){var r=e.re,i=e.im,a=new n(i*i-r*r+1,-2*r*i),o=Z.sqrt(a),s=new n(o.re-i,o.im+r),f=Z.log(s);return new n(f.im,-f.re)}if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.asin);if(e.valueOf()!==e)return Z.asin(e.valueOf());throw O("asin",e)},Z.atan=function(e){if(1!=arguments.length)throw x("atan",arguments.length,1);if(v(e))return Math.atan(e);if(e instanceof n){var r=e.re,i=e.im,a=r*r+(1-i)*(1-i),o=new n((1-i*i-r*r)/a,-2*r/a),s=Z.log(o);return new n(-.5*s.im,.5*s.re)}if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.atan);if(e.valueOf()!==e)return Z.atan(e.valueOf());throw O("atan",e)},Z.atan2=function(e,r){if(2!=arguments.length)throw x("atan2",arguments.length,2);if(v(e)){if(v(r))return Math.atan2(e,r);if(r instanceof n)return Math.atan2(e,r.re)}else if(e instanceof n){if(v(r))return Math.atan2(e.re,r);if(r instanceof n)return Math.atan2(e.re,r.re)}if(e instanceof Array||e instanceof t||e instanceof w||r instanceof Array||r instanceof t||r instanceof w)return K.map2(e,r,Z.atan2);if(r.valueOf()!==r||e.valueOf()!==e)return Z.atan2(e.valueOf(),r.valueOf());throw O("atan2",e,r)},Z.cos=function(e){if(1!=arguments.length)throw x("cos",arguments.length,1);if(v(e))return Math.cos(e);if(e instanceof n)return new n(.5*Math.cos(e.re)*(Math.exp(-e.im)+Math.exp(e.im)),.5*Math.sin(e.re)*(Math.exp(-e.im)-Math.exp(e.im)));if(e instanceof E){if(!e.hasBase(E.BASE_UNITS.ANGLE))throw new TypeError("Unit in function cos is no angle");return Math.cos(e.value)}if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.cos);if(e.valueOf()!==e)return Z.cos(e.valueOf());throw O("cos",e)},Z.cot=function(e){if(1!=arguments.length)throw x("cot",arguments.length,1);if(v(e))return 1/Math.tan(e);if(e instanceof n){var r=Math.exp(-4*e.im)-2*Math.exp(-2*e.im)*Math.cos(2*e.re)+1;return new n(2*Math.exp(-2*e.im)*Math.sin(2*e.re)/r,(Math.exp(-4*e.im)-1)/r)}if(e instanceof E){if(!e.hasBase(E.BASE_UNITS.ANGLE))throw new TypeError("Unit in function cot is no angle");return 1/Math.tan(e.value)}if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.cot);if(e.valueOf()!==e)return Z.cot(e.valueOf());throw O("cot",e)},Z.csc=function(e){if(1!=arguments.length)throw x("csc",arguments.length,1);if(v(e))return 1/Math.sin(e);if(e instanceof n){var r=.25*(Math.exp(-2*e.im)+Math.exp(2*e.im))-.5*Math.cos(2*e.re);return new n(.5*Math.sin(e.re)*(Math.exp(-e.im)+Math.exp(e.im))/r,.5*Math.cos(e.re)*(Math.exp(-e.im)-Math.exp(e.im))/r)}if(e instanceof E){if(!e.hasBase(E.BASE_UNITS.ANGLE))throw new TypeError("Unit in function csc is no angle");return 1/Math.sin(e.value)}if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.csc);if(e.valueOf()!==e)return Z.csc(e.valueOf());throw O("csc",e)},Z.sec=function(e){if(1!=arguments.length)throw x("sec",arguments.length,1);if(v(e))return 1/Math.cos(e);if(e instanceof n){var r=.25*(Math.exp(-2*e.im)+Math.exp(2*e.im))+.5*Math.cos(2*e.re);return new n(.5*Math.cos(e.re)*(Math.exp(-e.im)+Math.exp(e.im))/r,.5*Math.sin(e.re)*(Math.exp(e.im)-Math.exp(-e.im))/r)}if(e instanceof E){if(!e.hasBase(E.BASE_UNITS.ANGLE))throw new TypeError("Unit in function sec is no angle");return 1/Math.cos(e.value)}if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.sec);if(e.valueOf()!==e)return Z.sec(e.valueOf());throw O("sec",e)},Z.sin=function(e){if(1!=arguments.length)throw x("sin",arguments.length,1);if(v(e))return Math.sin(e);if(e instanceof n)return new n(.5*Math.sin(e.re)*(Math.exp(-e.im)+Math.exp(e.im)),.5*Math.cos(e.re)*(Math.exp(e.im)-Math.exp(-e.im)));if(e instanceof E){if(!e.hasBase(E.BASE_UNITS.ANGLE))throw new TypeError("Unit in function cos is no angle");return Math.sin(e.value)}if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.sin);if(e.valueOf()!==e)return Z.sin(e.valueOf());throw O("sin",e)},Z.tan=function(e){if(1!=arguments.length)throw x("tan",arguments.length,1);if(v(e))return Math.tan(e);if(e instanceof n){var r=Math.exp(-4*e.im)+2*Math.exp(-2*e.im)*Math.cos(2*e.re)+1;return new n(2*Math.exp(-2*e.im)*Math.sin(2*e.re)/r,(1-Math.exp(-4*e.im))/r)}if(e instanceof E){if(!e.hasBase(E.BASE_UNITS.ANGLE))throw new TypeError("Unit in function tan is no angle");return Math.tan(e.value)}if(e instanceof Array||e instanceof t||e instanceof w)return K.map(e,Z.tan);if(e.valueOf()!==e)return Z.tan(e.valueOf());throw O("tan",e)},Z["in"]=function(e,n){if(2!=arguments.length)throw x("in",arguments.length,2);if(e instanceof E&&(n instanceof E||y(n)))return e.in(n);if(e instanceof Array||e instanceof t||e instanceof w||n instanceof Array||n instanceof t||n instanceof w)return K.map2(e,n,Z["in"]);if(e.valueOf()!==e)return Z["in"](e.valueOf());throw O("in",e,n)},Z.clone=function(n){if(1!=arguments.length)throw x("clone",arguments.length,1);if(null==n)return n;if("function"==typeof n.clone)return n.clone();if(v(n)||y(n)||e(n))return n;if(n instanceof Array){var t=Z.clone;return n.map(function(e){return t(e)})}if(n instanceof Object)return K.mapObject(n,Z.clone);throw O("clone",n)},Z.eval=function(e){if(1!=arguments.length)throw x("eval",arguments.length,1);if(!y(e))throw new TypeError("String expected");return en.eval(e)};var en=new Z.expr.Parser({readonly:!0});Z.format=function(e,n){var t=arguments.length;if(1!=t&&2!=t)throw x("format",t,1,2);if(1==t){var r=arguments[0];return v(r)?K.formatNumber(r):r instanceof Array?K.formatArray(r):y(r)?'"'+r+'"':r instanceof Object?""+r:r+""}if(!y(e))throw new TypeError("String expected as first parameter in function format");if(!(n instanceof Object))throw new TypeError("Object expected as first parameter in function format");return e.replace(/\$([\w\.]+)/g,function(e,t){for(var r=t.split("."),i=n[r.shift()];r.length&&void 0!=i;){var a=r.shift();i=a?i[a]:i+"."}return void 0!=i?i:e})},Z["import"]=function(e,n){var t;if(y(e)){if("undefined"==typeof require)throw Error("Cannot load file: require not available.");var r=require(e);Z["import"](r)}else if(Y(e)){if(t=e.name,!t)throw Error("Cannot import an unnamed function or object");(n||void 0===Z[t])&&H(t,e)}else if(e instanceof Object)for(t in e)if(e.hasOwnProperty(t)){var i=e[t];Y(i)?(n||void 0===Z[t])&&H(t,i):Z["import"](i)}},Z.select=function(e){return new Z.type.Selector(e)},Z["typeof"]=function(e){if(1!=arguments.length)throw x("typeof",arguments.length,1);var n,t=typeof e;if("object"==t){if(null==e)return"null";if(e.constructor){for(n in Z)if(Z.hasOwnProperty(n)&&e.constructor==Z[n])return n.toLowerCase();for(n in Z.type)if(Z.type.hasOwnProperty(n)&&e.constructor==Z.type[n])return n.toLowerCase();if(e.constructor.name)return e.constructor.name.toLowerCase()}}return t},Z.Complex=function(){W("new math.Complex()","math.complex()")},Z.Unit=function(){W("new math.Unit()","math.unit()")},Z.parser.Parser=function(){W("new math.parser.Parser()","math.parser()")},Z.parser.Workspace=function(){W("new math.parser.Workspace()","math.workspace()")};for(var nn in Z)Z.hasOwnProperty(nn)&&nn&&d(nn,Z[nn])})(); \ No newline at end of file diff --git a/src/expr/Parser.js b/src/expr/Parser.js index 4eab0978f..67e153f75 100644 --- a/src/expr/Parser.js +++ b/src/expr/Parser.js @@ -3,6 +3,9 @@ * @constructor math.expr.Parser * Parser parses math expressions and evaluates them or returns a node tree. * + * @param {Object} [options] Available options: + * {boolean} readonly (false by default). + * * Methods: * var result = parser.eval(expr); // evaluate an expression * var value = parser.get(name); // retrieve a variable from the parser @@ -43,13 +46,13 @@ * // clear defined functions and variables * parser.clear(); */ - math.expr.Parser = function Parser() { + math.expr.Parser = function Parser(options) { if (this.constructor != Parser) { throw new SyntaxError( 'Parser constructor must be called with the new operator'); } - this.scope = new math.expr.Scope(); + this.scope = new math.expr.Scope(null, options); }; /** @@ -430,16 +433,18 @@ function parse_ans (scope) { var expression = parse_function_assignment(scope); - // TODO: not so nice having to specify some special types here... - if (!(expression instanceof Assignment) - // !(expression instanceof FunctionAssignment) && // TODO - // !(expression instanceof plot) // TODO - ) { - // create a variable definition for ans - var name = 'ans'; - var params = undefined; - var link = scope.createDef(name); - return new Assignment(name, params, expression, link); + if (!scope.readonly) { + // TODO: not so nice having to specify some special types here... + if (!(expression instanceof Assignment) + // !(expression instanceof FunctionAssignment) && // TODO + // !(expression instanceof plot) // TODO + ) { + // create a variable definition for ans + var name = 'ans'; + var params = undefined; + var link = scope.createDef(name); + return new Assignment(name, params, expression, link); + } } return expression; diff --git a/src/expr/Scope.js b/src/expr/Scope.js index 1f34eacc8..44fd7d038 100644 --- a/src/expr/Scope.js +++ b/src/expr/Scope.js @@ -5,8 +5,15 @@ * * @constructor mathnotepad.Scope * @param {Scope} [parentScope] + * @param {Object} [options] Available options: + * {boolean} readonly (false by default). */ -math.expr.Scope = function Scope(parentScope) { +math.expr.Scope = function Scope(parentScope, options) { + this.readonly = false; + if (options && options.readonly != undefined) { + this.readonly = options.readonly; + } + this.parentScope = parentScope; this.nestedScopes = undefined; @@ -27,6 +34,10 @@ math.expr.Scope.prototype = { * @return {math.expr.Scope} nestedScope */ createNestedScope: function () { + if (this.readonly) { + throw new Error('Cannot create nested scope: Scope is read-only'); + } + var nestedScope = new math.expr.Scope(this); if (!this.nestedScopes) { this.nestedScopes = []; @@ -40,6 +51,10 @@ math.expr.Scope.prototype = { * (parent scope will not be cleared) */ clear: function () { + if (this.readonly) { + throw new Error('Cannot clear scope: Scope is read-only'); + } + this.symbols = {}; this.defs = {}; this.links = {}; @@ -146,6 +161,10 @@ math.expr.Scope.prototype = { * @return {function} symbol */ createDef: function (name, value) { + if (this.readonly) { + throw new Error('Cannot create variable: Scope is read-only'); + } + var symbol = this.defs[name]; if (!symbol) { symbol = this.createSymbol(name); @@ -164,6 +183,10 @@ math.expr.Scope.prototype = { * @return {function} symbol */ createUpdate: function (name) { + if (this.readonly) { + throw new Error('Cannot update variable: Scope is read-only'); + } + var symbol = this.updates[name]; if (!symbol) { symbol = this.createLink(name); diff --git a/src/function/utils/eval.js b/src/function/utils/eval.js new file mode 100644 index 000000000..cf8e739d5 --- /dev/null +++ b/src/function/utils/eval.js @@ -0,0 +1,22 @@ +/** + * Evaluate an expression. The expression will be evaluated using a read-only + * instance of a Parser (i.e. variable definitions are not supported). + * @param {String} expr + * @return {*} res + */ +math.eval = function eval(expr) { + if (arguments.length != 1) { + throw newArgumentsError('eval', arguments.length, 1); + } + + if (!isString(expr)) { + throw new TypeError('String expected'); + } + + return _readonlyParser.eval(expr); +}; + +/** @private */ +var _readonlyParser = new math.expr.Parser({ + readonly: true +}); diff --git a/test/expr/parser.js b/test/expr/parser.js index ff0d6e07e..f96869fc6 100644 --- a/test/expr/parser.js +++ b/test/expr/parser.js @@ -122,5 +122,12 @@ assert.throws(function () { assert.equal(parser.eval('q = 4/2'), 2); assert.equal(parser.eval('g(3)'), 9); +// test read-only parser +var readonlyParser = new math.expr.Parser({readonly: true}); +assert.equal(readonlyParser.get('pi'), Math.PI); +assert.throws(function () {readonlyParser.eval('b = 43');}); +assert.throws(function () {readonlyParser.eval('function f(x) = a * x');}); +assert.throws(function () {readonlyParser.eval('a([1,1])= [4]');}); +assert.throws(function () {readonlyParser.set('a', 3)}); // TODO: extensively test the Parser diff --git a/test/function/util.js b/test/function/util.js index e6343a7fc..870b54427 100644 --- a/test/function/util.js +++ b/test/function/util.js @@ -55,6 +55,16 @@ a.valueOf()[2].re = 5; assert.equal(b.valueOf()[2].re, 2); +// test eval +assert.equal(math.eval('pi'), Math.PI); +assert.equal(math.eval('(2+3)/4'), 1.25); +assert.equal(math.eval('sqrt(-4)').toString(), '2i'); +assert.throws(function () {math.eval('b = 43');}); +assert.throws(function () {math.eval('function f(x) = a * x');}); +assert.throws(function () {math.eval('a([1,1])= [4]');}); +assert.throws(function () {math.set('a', 3)}); + + // test format assert.equal(math.format(2/7), '0.2857142857'); assert.equal(math.format([[1,2],[3,4]]), '[[1, 2], [3, 4]]');