← Back to team overview

ubuntu-touch-coreapps-reviewers team mailing list archive

[Merge] lp:~gang65/ubuntu-calculator-app/ubuntu-calculator-app-mathjs-2-upgrade into lp:ubuntu-calculator-app

 

Bartosz Kosiorek has proposed merging lp:~gang65/ubuntu-calculator-app/ubuntu-calculator-app-mathjs-2-upgrade into lp:ubuntu-calculator-app.

Commit message:
Upgrade math.js to 2.1.1 to improve performance (LP: #1484851)

Requested reviews:
  Ubuntu Calculator Developers (ubuntu-calculator-dev)

For more details, see:
https://code.launchpad.net/~gang65/ubuntu-calculator-app/ubuntu-calculator-app-mathjs-2-upgrade/+merge/268046

Upgrade math.js to 2.1.1 to improve performance (LP: #1484851)
-- 
The attached diff has been truncated due to its size.
Your team Ubuntu Calculator Developers is requested to review the proposed merge of lp:~gang65/ubuntu-calculator-app/ubuntu-calculator-app-mathjs-2-upgrade into lp:ubuntu-calculator-app.
=== modified file 'app/engine/math.js'
--- app/engine/math.js	2015-04-29 19:37:47 +0000
+++ app/engine/math.js	2015-08-14 09:10:33 +0000
@@ -14,8 +14,8 @@
  * It features real and complex numbers, units, matrices, a large set of
  * mathematical functions, and a flexible expression parser.
  *
- * @version 1.5.2
- * @date    2015-04-09
+ * @version 2.1.1
+ * @date    2015-08-12
  *
  * @license
  * Copyright (C) 2013-2015 Jos de Jong <wjosdejong@xxxxxxxxx>
@@ -35,7 +35,8 @@
 
 (function webpackUniversalModuleDefinition(root, factory) {
     // UCA: we delete all exports, we don't need them, and we keep only our var
-    mathJs = factory();})(this, function() {
+    mathJs = factory();
+})(this, function() {
 return /******/ (function(modules) { // webpackBootstrap
 /******/ 	// The module cache
 /******/ 	var installedModules = {};
@@ -82,42 +83,117 @@
 /* 0 */
 /***/ function(module, exports, __webpack_require__) {
 
-	module.exports = __webpack_require__(1);
-
-
-/***/ },
-/* 1 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var object = __webpack_require__(2);
-	var digits = __webpack_require__(3).digits;
+	var core = __webpack_require__(1);
 
 	/**
-	 * math.js factory function.
+	 * math.js factory function. Creates a new instance of math.js
 	 *
 	 * @param {Object} [config] Available configuration options:
-	 *                            {String} matrix
+	 *                            {number} epsilon
+	 *                              Minimum relative difference between two
+	 *                              compared values, used by all comparison functions.
+	 *                            {string} matrix
 	 *                              A string 'matrix' (default) or 'array'.
-	 *                            {String} number
-	 *                              A string 'number' (default) or 'bignumber'
-	 *                            {Number} precision
+	 *                            {string} number
+	 *                              A string 'number' (default), 'bignumber', or
+	 *                              'fraction'
+	 *                            {number} precision
 	 *                              The number of significant digits for BigNumbers.
 	 *                              Not applicable for Numbers.
+	 *                            {boolean} predictable
+	 *                              Predictable output type of functions. When true,
+	 *                              output type depends only on the input types. When
+	 *                              false (default), output type can vary depending
+	 *                              on input values. For example `math.sqrt(-2)`
+	 *                              returns `NaN` when predictable is false, and
+	 *                              returns `complex('2i')` when true.
 	 */
 	function create (config) {
+	  // create a new math.js instance
+	  var math = core.create(config);
+	  math.create = create;
+
+	  // import data types, functions, constants, expression parser, etc.
+	  math.import(__webpack_require__(13));
+
+	  return math;
+	}
+
+	// return a new instance of math.js
+	module.exports = create();
+
+
+/***/ },
+/* 1 */
+/***/ function(module, exports, __webpack_require__) {
+
+	module.exports = __webpack_require__(2);
+
+/***/ },
+/* 2 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var isFactory = __webpack_require__(5).isFactory;
+	var deepExtend = __webpack_require__(5).deepExtend;
+	var typedFactory = __webpack_require__(6);
+	var emitter = __webpack_require__(3);
+
+	var importFactory = __webpack_require__(10);
+	var configFactory = __webpack_require__(12);
+
+	/**
+	 * Math.js core. Creates a new, empty math.js instance
+	 * @param {Object} [options] Available options:
+	 *                            {number} epsilon
+	 *                              Minimum relative difference between two
+	 *                              compared values, used by all comparison functions.
+	 *                            {string} matrix
+	 *                              A string 'matrix' (default) or 'array'.
+	 *                            {string} number
+	 *                              A string 'number' (default), 'bignumber', or 'fraction'
+	 *                            {number} precision
+	 *                              The number of significant digits for BigNumbers.
+	 *                              Not applicable for Numbers.
+	 *                            {boolean} predictable
+	 *                              Predictable output type of functions. When true,
+	 *                              output type depends only on the input types. When
+	 *                              false (default), output type can vary depending
+	 *                              on input values. For example `math.sqrt(-2)`
+	 *                              returns `NaN` when predictable is false, and
+	 *                              returns `complex('2i')` when true.
+	 * @returns {Object} Returns a bare-bone math.js instance containing
+	 *                   functions:
+	 *                   - `import` to add new functions
+	 *                   - `config` to change configuration
+	 *                   - `on`, `off`, `once`, `emit` for events
+	 */
+	exports.create = function create (options) {
 	  // simple test for ES5 support
 	  if (typeof Object.create !== 'function') {
 	    throw new Error('ES5 not supported by this JavaScript engine. ' +
-	        'Please load the es5-shim and es5-sham library for compatibility.');
+	    'Please load the es5-shim and es5-sham library for compatibility.');
 	  }
 
-	  // create namespace
-	  var math = {};
+	  // cached factories and instances
+	  var factories = [];
+	  var instances = [];
+
+	  // create a namespace for the mathjs instance, and attach emitter functions
+	  var math = emitter.mixin({});
+	  math.type = {};
+	  math.expression = {
+	    transform: Object.create(math)
+	  };
+
+	  // create a new typed instance
+	  math.typed = typedFactory.create(math.type);
 
 	  // create configuration options. These are private
 	  var _config = {
+	    // minimum relative difference between two compared values,
+	    // used by all comparison functions
+	    epsilon: 1e-14,
+
 	    // type of default matrix output. Choose 'matrix' (default) or 'array'
 	    matrix: 'matrix',
 
@@ -127,391 +203,161 @@
 	    // number of significant digits in BigNumbers
 	    precision: 64,
 
-	    // minimum relative difference between two compared values,
-	    // used by all comparison functions
-	    epsilon: 1e-14
+	    // predictable output type of functions. When true, output type depends only
+	    // on the input types. When false (default), output type can vary depending
+	    // on input values. For example `math.sqrt(-2)` returns `NaN` when
+	    // predictable is false, and returns `complex('2i')` when true.
+	    predictable: false
 	  };
 
+	  if (options) {
+	    // merge options
+	    deepExtend(_config, options);
+	  }
+
 	  /**
-	   * Set configuration options for math.js, and get current options
-	   * @param {Object} [options] Available options:
-	   *                            {String} matrix
-	   *                              A string 'matrix' (default) or 'array'.
-	   *                            {String} number
-	   *                              A string 'number' (default) or 'bignumber'
-	   *                            {Number} precision
-	   *                              The number of significant digits for BigNumbers.
-	   *                              Not applicable for Numbers.
-	   * @return {Object} Returns the current configuration
+	   * Load a function or data type from a factory.
+	   * If the function or data type already exists, the existing instance is
+	   * returned.
+	   * @param {{type: string, name: string, factory: Function}} factory
+	   * @returns {*}
 	   */
-	  math.config = function(options) {
-	    if (options) {
-	      // merge options
-	      object.deepExtend(_config, options);
-
-	      if (options.precision) {
-	        math.type.BigNumber.config({
-	          precision: options.precision
-	        });
-	      }
-
-	      // reload the constants (they depend on option number and precision)
-	      // this must be done after math.type.BigNumber.config is applied
-	      __webpack_require__(4)(math, _config);
-
-	      // TODO: remove deprecated setting some day (deprecated since version 0.17.0)
-	      if (options.number && options.number.defaultType) {
-	        throw new Error('setting `number.defaultType` is deprecated. Use `number` instead.');
-	      }
-
-	      // TODO: remove deprecated setting some day (deprecated since version 0.17.0)
-	      if (options.number && options.number.precision) {
-	        throw new Error('setting `number.precision` is deprecated. Use `precision` instead.');
-	      }
-
-	      // TODO: remove deprecated setting some day (deprecated since version 0.17.0)
-	      if (options.matrix && options.matrix.defaultType) {
-	        throw new Error('setting `matrix.defaultType` is deprecated. Use `matrix` instead.');
-	      }
-
-	      // TODO: remove deprecated setting some day (deprecated since version 0.15.0)
-	      if (options.matrix && options.matrix['default']) {
-	        throw new Error('setting `matrix.default` is deprecated. Use `matrix` instead.');
-	      }
-
-	      // TODO: remove deprecated setting some day (deprecated since version 0.20.0)
-	      if (options.decimals) {
-	        throw new Error('setting `decimals` is deprecated. Use `precision` instead.');
-	      }
+	  function load (factory) {
+	    if (!isFactory(factory)) {
+	      throw new Error('Factory object with properties `type`, `name`, and `factory` expected');
 	    }
 
-	    // return a clone of the settings
-	    return object.clone(_config);
-	  };
-
-	  /**
-	   * math.js factory function. Creates a new instance of math.js
-	   *
-	   * @param {Object} [config] Available configuration options:
-	   *                            {String} matrix
-	   *                              A string 'matrix' (default) or 'array'.
-	   *                            {String} number
-	   *                              A string 'number' (default) or 'bignumber'
-	   *                            {Number} precision
-	   *                              The number of significant digits for BigNumbers.
-	   *                              Not applicable for Numbers.
-	   */
-	  math.create = create;
-
-	  // create a new BigNumber factory for this instance of math.js
-	  var BigNumber = __webpack_require__(5).constructor();
-
-	  /**
-	   * Get a JSON representation of a BigNumber containing
-	   * type information
-	   * @returns {Object} Returns a JSON object structured as:
-	   *                   `{"mathjs": "BigNumber", "value": "0.2"}`
-	   */
-	  BigNumber.prototype.toJSON = function () {
-	    return {
-	      mathjs: 'BigNumber',
-	      value: this.toString()
-	    };
-	  };
-
-	  /**
-	   * Instantiate a BigNumber from a JSON object
-	   * @param {Object} json  a JSON object structured as:
-	   *                       `{"mathjs": "BigNumber", "value": "0.2"}`
-	   * @return {BigNumber}
-	   */
-	  BigNumber.fromJSON = function (json) {
-	    return new BigNumber(json.value);
-	  };
-
-	  // extend BigNumber with a function clone
-	  if (typeof BigNumber.prototype.clone !== 'function') {
-	    /**
-	     * Clone a bignumber
-	     * @return {BigNumber} clone
-	     */
-	    BigNumber.prototype.clone = function() {
-	      return this; // just return itself (a BigNumber is immutable)
-	    };
-	  }
-
-	  // extend BigNumber with a function convert
-	  if (typeof BigNumber.convert !== 'function') {
-	    /**
-	     * Try to convert a Number in to a BigNumber.
-	     * If the number has 15 or mor significant digits, the Number cannot be
-	     * converted to BigNumber and will return the original number.
-	     * @param {Number} number
-	     * @return {BigNumber | Number} bignumber
-	     */
-	    BigNumber.convert = function(number) {
-	      if (digits(number) > 15) {
-	        return number;
+	    var index = factories.indexOf(factory);
+	    var instance;
+	    if (index === -1) {
+	      // doesn't yet exist
+	      if (factory.math === true) {
+	        // pass with math namespace
+	        instance = factory.factory(math.type, _config, load, math.typed, math);
 	      }
 	      else {
-	        return new BigNumber(number);
+	        instance = factory.factory(math.type, _config, load, math.typed);
 	      }
-	    };
-	  }
-	  else {
-	    throw new Error('Cannot add function convert to BigNumber: function already exists');
-	  }
-
-	  // errors
-	  math.error = __webpack_require__(6);
-
-	  // types (Matrix, Complex, Unit, ...)
-	  math.type = {};
-	  math.type.Complex = __webpack_require__(7);
-	  math.type.Range = __webpack_require__(8);
-	  math.type.Index = __webpack_require__(9);
-	  math.type.Matrix = __webpack_require__(10)(_config);
-	  math.type.Unit = __webpack_require__(11);
-	  math.type.Help = __webpack_require__(12);
-	  math.type.ResultSet = __webpack_require__(13);
-	  math.type.BigNumber = BigNumber;
-
-	  math.collection = __webpack_require__(14)(math, _config);
-
-	  // matrix storage formats
-	  math.type.CcsMatrix = __webpack_require__(15)(math, _config);
-	  math.type.CrsMatrix = __webpack_require__(16)(math, _config);
-	  math.type.DenseMatrix = __webpack_require__(17)(math, _config);
-
-	  // matrix storage format registry
-	  math.type.Matrix._storage.ccs = math.type.CcsMatrix;
-	  math.type.Matrix._storage.crs = math.type.CrsMatrix;
-	  math.type.Matrix._storage.dense = math.type.DenseMatrix;
-	  math.type.Matrix._storage['default'] = math.type.DenseMatrix;
-
-	  // expression (parse, Parser, nodes, docs)
-	  math.expression = {};
-	  math.expression.node = __webpack_require__(18);
-	  math.expression.parse = __webpack_require__(19)(math, _config);
-	  math.expression.Parser = __webpack_require__(20)(math, _config);
-	  math.expression.docs = __webpack_require__(21);
-
-	  // serialization utilities
-	  math.json = {
-	    reviver: __webpack_require__(22)(math, _config)
-	  };
-	  
-	  // functions - construction (must be defined before the rest of functions)
-	  __webpack_require__(34)(math, _config);
-	  __webpack_require__(35)(math, _config);
-	  __webpack_require__(36)(math, _config);
-	  __webpack_require__(37)(math, _config);
-	  __webpack_require__(38)(math, _config);
-	  __webpack_require__(39)(math, _config);
-	  __webpack_require__(40)(math, _config);
-	  __webpack_require__(41)(math, _config);
-	  __webpack_require__(42)(math, _config);
-	  __webpack_require__(43)(math, _config);
-
-	  // expression parser
-	  __webpack_require__(44)(math, _config);
-	  __webpack_require__(45)(math, _config);
-	  __webpack_require__(46)(math, _config);
-	  __webpack_require__(47)(math, _config);
-
-	  // functions - arithmetic
-	  __webpack_require__(48)(math, _config);
-	  __webpack_require__(49)(math, _config);
-	  __webpack_require__(50)(math, _config);
-	  __webpack_require__(51)(math, _config);
-	  __webpack_require__(52)(math, _config);
-	  __webpack_require__(53)(math, _config);
-	  __webpack_require__(54)(math, _config);
-	  __webpack_require__(55)(math, _config);
-	  __webpack_require__(56)(math, _config);
-	  __webpack_require__(57)(math, _config);
-	  __webpack_require__(58)(math, _config);
-	  __webpack_require__(59)(math, _config);
-	  __webpack_require__(60)(math, _config);
-	  __webpack_require__(61)(math, _config);
-	  __webpack_require__(62)(math, _config);
-	  __webpack_require__(63)(math, _config);
-	  __webpack_require__(64)(math, _config);
-	  __webpack_require__(65)(math, _config);
-	  __webpack_require__(66)(math, _config);
-	  __webpack_require__(67)(math, _config);
-	  __webpack_require__(68)(math, _config);
-	  __webpack_require__(69)(math, _config);
-	  __webpack_require__(70)(math, _config);
-	  __webpack_require__(71)(math, _config);
-	  __webpack_require__(72)(math, _config);
-	  __webpack_require__(73)(math, _config);
-	  __webpack_require__(74)(math, _config);
-	  __webpack_require__(75)(math, _config);
-	  __webpack_require__(76)(math, _config);
-
-	  // functions - bitwise
-	  __webpack_require__(77)(math, _config);
-	  __webpack_require__(78)(math, _config);
-	  __webpack_require__(79)(math, _config);
-	  __webpack_require__(80)(math, _config);
-	  __webpack_require__(81)(math, _config);
-	  __webpack_require__(82)(math, _config);
-	  __webpack_require__(83)(math, _config);
-
-	  // functions - complex
-	  __webpack_require__(84)(math, _config);
-	  __webpack_require__(85)(math, _config);
-	  __webpack_require__(86)(math, _config);
-	  __webpack_require__(87)(math, _config);
-
-	  // functions - logical
-	  __webpack_require__(88)(math, _config);
-	  __webpack_require__(89)(math, _config);
-	  __webpack_require__(90)(math, _config);
-	  __webpack_require__(91)(math, _config);
-
-	  // functions - matrix
-	  __webpack_require__(92)(math, _config);
-	  __webpack_require__(93)(math, _config);
-	  __webpack_require__(94)(math, _config);
-	  __webpack_require__(95)(math, _config);
-	  __webpack_require__(96)(math, _config);
-	  __webpack_require__(97)(math, _config);
-	  __webpack_require__(98)(math, _config);
-	  __webpack_require__(99)(math, _config);
-	  __webpack_require__(100)(math, _config);
-	  __webpack_require__(101)(math, _config);
-	  __webpack_require__(102)(math, _config);
-	  __webpack_require__(103)(math, _config);
-	  __webpack_require__(104)(math, _config);
-	  __webpack_require__(105)(math, _config);
-	  __webpack_require__(106)(math, _config);
-	  __webpack_require__(107)(math, _config);
-	  __webpack_require__(108)(math, _config);
-
-	  // functions - probability
-	  //require('./function/probability/distribution')(math, _config); // TODO: rethink math.distribution
-	  __webpack_require__(109)(math, _config);
-	  __webpack_require__(110)(math, _config);
-	  __webpack_require__(111)(math, _config);
-	  __webpack_require__(112)(math, _config);
-	  __webpack_require__(113)(math, _config);
-	  __webpack_require__(114)(math, _config);
-	  __webpack_require__(115)(math, _config);
-
-	  // functions - relational
-	  __webpack_require__(116)(math, _config);
-	  __webpack_require__(117)(math, _config);
-	  __webpack_require__(118)(math, _config);
-	  __webpack_require__(119)(math, _config);
-	  __webpack_require__(120)(math, _config);
-	  __webpack_require__(121)(math, _config);
-	  __webpack_require__(122)(math, _config);
-	  __webpack_require__(123)(math, _config);
-
-	  // functions - statistics
-	  __webpack_require__(124)(math, _config);
-	  __webpack_require__(125)(math, _config);
-	  __webpack_require__(126)(math, _config);
-	  __webpack_require__(127)(math, _config);
-	  __webpack_require__(128)(math, _config);
-	  __webpack_require__(129)(math, _config);
-	  __webpack_require__(130)(math, _config);
-	  __webpack_require__(131)(math, _config);
-
-	  // functions - trigonometry
-	  __webpack_require__(132)(math, _config);
-	  __webpack_require__(133)(math, _config);
-	  __webpack_require__(134)(math, _config);
-	  __webpack_require__(135)(math, _config);
-	  __webpack_require__(136)(math, _config);
-	  __webpack_require__(137)(math, _config);
-	  __webpack_require__(138)(math, _config);
-	  __webpack_require__(139)(math, _config);
-	  __webpack_require__(140)(math, _config);
-	  __webpack_require__(141)(math, _config);
-	  __webpack_require__(142)(math, _config);
-	  __webpack_require__(143)(math, _config);
-	  __webpack_require__(144)(math, _config);
-	  __webpack_require__(145)(math, _config);
-	  __webpack_require__(146)(math, _config);
-	  __webpack_require__(147)(math, _config);
-	  __webpack_require__(148)(math, _config);
-	  __webpack_require__(149)(math, _config);
-	  __webpack_require__(150)(math, _config);
-	  __webpack_require__(151)(math, _config);
-	  __webpack_require__(152)(math, _config);
-	  __webpack_require__(153)(math, _config);
-	  __webpack_require__(154)(math, _config);
-	  __webpack_require__(155)(math, _config);
-	  __webpack_require__(156)(math, _config);
-
-	  // functions - units
-	  __webpack_require__(157)(math, _config);
-
-	  // functions - utils
-	  __webpack_require__(158)(math, _config);
-	  __webpack_require__(159)(math, _config);
-	  __webpack_require__(160)(math, _config);
-	  __webpack_require__(161)(math, _config);
-	  __webpack_require__(162)(math, _config);
-	  __webpack_require__(163)(math, _config);
-	  __webpack_require__(164)(math, _config);
-	  __webpack_require__(165)(math, _config);
-	  __webpack_require__(166)(math, _config);
-
-	  // TODO: deprecated since version 0.25.0, remove some day.
-	  math.ifElse = function () {
-	    throw new Error('Function ifElse is deprecated. Use the conditional operator instead.');
-	  };
-
-	  // constants
-	  __webpack_require__(4)(math, _config);
-
-	  // attach transform functions (for converting one-based indices to zero-based)
-	  math.expression.transform = {
-	    concat: __webpack_require__(23)(math, _config),
-	    filter: __webpack_require__(24)(math, _config),
-	    forEach:__webpack_require__(25)(math, _config),
-	    index:  __webpack_require__(26)(math, _config),
-	    map:    __webpack_require__(27)(math, _config),
-	    max:    __webpack_require__(28)(math, _config),
-	    mean:   __webpack_require__(29)(math, _config),
-	    min:    __webpack_require__(30)(math, _config),
-	    range:  __webpack_require__(31)(math, _config),
-	    subset: __webpack_require__(32)(math, _config)
-	  };
-
-	  // selector (we initialize after all functions are loaded)
-	  math.chaining = {};
-	  math.chaining.Chain = __webpack_require__(33)(math, _config);
-	  math.chaining.Selector = math.chaining.Chain; // TODO: deprecate in v2.0
-
-	  // apply provided configuration options
-	  math.config(_config); // apply the default options
-	  math.config(config);  // apply custom options
-
-	  // return the new instance
+
+	      // append to the cache
+	      factories.push(factory);
+	      instances.push(instance);
+	    }
+	    else {
+	      // already existing function, return the cached instance
+	      instance = instances[index];
+	    }
+
+	    return instance;
+	  }
+
+	  // load the import and config functions
+	  math['import'] = load(importFactory);
+	  math['config'] = load(configFactory);
+
 	  return math;
-	}
-
-	// create a default instance of math.js
-	var math = create();
-
-	if (typeof window !== 'undefined') {
-	  window.mathjs = math; // TODO: deprecate the mathjs namespace some day (replaced with 'math' since version 0.25.0)
-	}
-
-	// export the default instance
-	module.exports = math;
-
+	};
 
 
 /***/ },
-/* 2 */
+/* 3 */
 /***/ function(module, exports, __webpack_require__) {
 
+	var Emitter = __webpack_require__(4);
+
+	/**
+	 * Extend given object with emitter functions `on`, `off`, `once`, `emit`
+	 * @param {Object} obj
+	 * @return {Object} obj
+	 */
+	exports.mixin = function (obj) {
+	  // create event emitter
+	  var emitter = new Emitter();
+
+	  // bind methods to obj (we don't want to expose the emitter.e Array...)
+	  obj.on   = emitter.on.bind(emitter);
+	  obj.off  = emitter.off.bind(emitter);
+	  obj.once = emitter.once.bind(emitter);
+	  obj.emit = emitter.emit.bind(emitter);
+
+	  return obj;
+	};
+
+
+/***/ },
+/* 4 */
+/***/ function(module, exports) {
+
+	function E () {
+		// Keep this empty so it's easier to inherit from
+	  // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)
+	}
+
+	E.prototype = {
+		on: function (name, callback, ctx) {
+	    var e = this.e || (this.e = {});
+	    
+	    (e[name] || (e[name] = [])).push({
+	      fn: callback,
+	      ctx: ctx
+	    });
+	    
+	    return this;
+	  },
+
+	  once: function (name, callback, ctx) {
+	    var self = this;
+	    var fn = function () {
+	      self.off(name, fn);
+	      callback.apply(ctx, arguments);
+	    };
+	    
+	    return this.on(name, fn, ctx);
+	  },
+
+	  emit: function (name) {
+	    var data = [].slice.call(arguments, 1);
+	    var evtArr = ((this.e || (this.e = {}))[name] || []).slice();
+	    var i = 0;
+	    var len = evtArr.length;
+	    
+	    for (i; i < len; i++) {
+	      evtArr[i].fn.apply(evtArr[i].ctx, data);
+	    }
+	    
+	    return this;
+	  },
+
+	  off: function (name, callback) {
+	    var e = this.e || (this.e = {});
+	    var evts = e[name];
+	    var liveEvents = [];
+	    
+	    if (evts && callback) {
+	      for (var i = 0, len = evts.length; i < len; i++) {
+	        if (evts[i].fn !== callback) liveEvents.push(evts[i]);
+	      }
+	    }
+	    
+	    // Remove event from queue to prevent memory leak
+	    // Suggested by https://github.com/lazd
+	    // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910
+
+	    (liveEvents.length) 
+	      ? e[name] = liveEvents
+	      : delete e[name];
+	    
+	    return this;
+	  }
+	};
+
+	module.exports = E;
+
+
+/***/ },
+/* 5 */
+/***/ function(module, exports) {
+
 	'use strict';
 
 	/**
@@ -546,10 +392,11 @@
 	    });
 	  }
 
-	  if (x instanceof Number)  return new Number(x.valueOf());
-	  if (x instanceof String)  return new String(x.valueOf());
-	  if (x instanceof Boolean) return new Boolean(x.valueOf());
-	  if (x instanceof Date)    return new Date(x.valueOf());
+	  if (x instanceof Number)    return new Number(x.valueOf());
+	  if (x instanceof String)    return new String(x.valueOf());
+	  if (x instanceof Boolean)   return new Boolean(x.valueOf());
+	  if (x instanceof Date)      return new Date(x.valueOf());
+	  if (x && x.isBigNumber === true) return x; // bignumbers are immutable
 	  if (x instanceof RegExp)  throw new TypeError('Cannot clone ' + x);  // TODO: clone a RegExp
 
 	  // object
@@ -682,7 +529,7 @@
 	 * of the properties value.
 	 * @param {Object} object   Object where to add the property
 	 * @param {string} prop     Property name
-	 * @param {function} fn     Function returning the property value. Called
+	 * @param {Function} fn     Function returning the property value. Called
 	 *                          without arguments.
 	 */
 	exports.lazy = function (object, prop, fn) {
@@ -701,7 +548,10 @@
 	      set: function (value) {
 	        _value = value;
 	        _uninitialized = false;
-	      }
+	      },
+
+	      configurable: true,
+	      enumerable: true
 	    });
 	  }
 	  else {
@@ -710,37 +560,1553 @@
 	  }
 	};
 
-
-/***/ },
-/* 3 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var NumberFormatter = __webpack_require__(167);
-
-	/**
-	 * Test whether value is a Number
+	/**
+	 * Traverse a path into an object.
+	 * When a namespace is missing, it will be created
+	 * @param {Object} object
+	 * @param {string} path   A dot separated string like 'name.space'
+	 * @return {Object} Returns the object at the end of the path
+	 */
+	exports.traverse = function(object, path) {
+	  var obj = object;
+
+	  if (path) {
+	    var names = path.split('.');
+	    for (var i = 0; i < names.length; i++) {
+	      var name = names[i];
+	      if (!(name in obj)) {
+	        obj[name] = {};
+	      }
+	      obj = obj[name];
+	    }
+	  }
+
+	  return obj;
+	};
+
+	/**
+	 * Test whether an object is a factory. a factory has fields:
+	 *
+	 * - factory: function (type: Object, config: Object, load: function, typed: function [, math: Object])   (required)
+	 * - name: string (optional)
+	 * - path: string    A dot separated path (optional)
+	 * - math: boolean   If true (false by default), the math namespace is passed
+	 *                   as fifth argument of the factory function
+	 *
+	 * @param {*} object
+	 * @returns {boolean}
+	 */
+	exports.isFactory = function (object) {
+	  return object && typeof object.factory === 'function';
+	};
+
+
+/***/ },
+/* 6 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var typedFunction = __webpack_require__(7);
+	var digits = __webpack_require__(8).digits;
+
+	// returns a new instance of typed-function
+	var createTyped = function () {
+	  // initially, return the original instance of typed-function
+	  // consecutively, return a new instance from typed.create.
+	  createTyped = typedFunction.create;
+	  return typedFunction;
+	};
+
+	/**
+	 * Factory function for creating a new typed instance
+	 * @param {Object} type   Object with data types like Complex and BigNumber
+	 * @returns {Function}
+	 */
+	exports.create = function create(type) {
+	  // TODO: typed-function must be able to silently ignore signatures with unknown data types
+
+	  // get a new instance of typed-function
+	  var typed = createTyped();
+
+	  // define all types. The order of the types determines in which order function
+	  // arguments are type-checked (so for performance it's important to put the
+	  // most used types first).
+	  typed.types = [
+	    { name: 'number',               test: function (x) { return typeof x === 'number'; } },
+	    { name: 'Complex',              test: function (x) { return x && x.isComplex; } },
+	    { name: 'BigNumber',            test: function (x) { return x && x.isBigNumber; } },
+	    { name: 'Fraction',             test: function (x) { return x && x.isFraction; } },
+	    { name: 'Unit',                 test: function (x) { return x && x.isUnit; } },
+	    { name: 'string',               test: function (x) { return typeof x === 'string'; } },
+	    { name: 'Array',                test: Array.isArray },
+	    { name: 'Matrix',               test: function (x) { return x && x.isMatrix; } },
+	    { name: 'DenseMatrix',          test: function (x) { return x && x.isDenseMatrix; } },
+	    { name: 'SparseMatrix',         test: function (x) { return x && x.isSparseMatrix; } },
+	    { name: 'ImmutableDenseMatrix', test: function (x) { return x && x.isImmutableDenseMatrix; } },
+	    { name: 'Range',                test: function (x) { return x && x.isRange; } },
+	    { name: 'Index',                test: function (x) { return x && x.isIndex; } },
+	    { name: 'boolean',              test: function (x) { return typeof x === 'boolean'; } },
+	    { name: 'ResultSet',            test: function (x) { return x && x.isResultSet; } },
+	    { name: 'Help',                 test: function (x) { return x && x.isHelp; } },
+	    { name: 'function',             test: function (x) { return typeof x === 'function';} },
+	    { name: 'Date',                 test: function (x) { return x instanceof Date; } },
+	    { name: 'RegExp',               test: function (x) { return x instanceof RegExp; } },
+	    { name: 'Object',               test: function (x) { return typeof x === 'object'; } },
+	    { name: 'null',                 test: function (x) { return x === null; } },
+	    { name: 'undefined',            test: function (x) { return x === undefined; } }
+	  ];
+
+	  // TODO: add conversion from BigNumber to number?
+	  typed.conversions = [
+	    {
+	      from: 'number',
+	      to: 'BigNumber',
+	      convert: function (x) {
+	        // note: conversion from number to BigNumber can fail if x has >15 digits
+	        if (digits(x) > 15) {
+	          throw new TypeError('Cannot implicitly convert a number with >15 significant digits to BigNumber ' +
+	          '(value: ' + x + '). ' +
+	          'Use function bignumber(x) to convert to BigNumber.');
+	        }
+	        return new type.BigNumber(x);
+	      }
+	    }, {
+	      from: 'number',
+	      to: 'Complex',
+	      convert: function (x) {
+	        return new type.Complex(x, 0);
+	      }
+	    }, {
+	      from: 'number',
+	      to: 'string',
+	      convert: function (x) {
+	        return x + '';
+	      }
+	    }, {
+	      from: 'BigNumber',
+	      to: 'Complex',
+	      convert: function (x) {
+	        return new type.Complex(x.toNumber(), 0);
+	      }
+	    }, {
+	      from: 'number',
+	      to: 'Fraction',
+	      convert: function (x) {
+	        if (digits(x) > 15) {
+	          throw new TypeError('Cannot implicitly convert a number with >15 significant digits to Fraction ' +
+	              '(value: ' + x + '). ' +
+	              'Use function fraction(x) to convert to Fraction.');
+	        }
+	        return new type.Fraction(x);
+	      }
+	    }, {
+	      from: 'string',
+	      to: 'number',
+	      convert: function (x) {
+	        var n = Number(x);
+	        if (isNaN(n)) {
+	          throw new Error('Cannot convert "' + x + '" to a number');
+	        }
+	        return n;
+	      }
+	    }, {
+	      from: 'boolean',
+	      to: 'number',
+	      convert: function (x) {
+	        return +x;
+	      }
+	    }, {
+	      from: 'boolean',
+	      to: 'BigNumber',
+	      convert: function (x) {
+	        return new type.BigNumber(+x);
+	      }
+	    }, {
+	      from: 'boolean',
+	      to: 'string',
+	      convert: function (x) {
+	        return +x;
+	      }
+	    }, {
+	      from: 'null',
+	      to: 'number',
+	      convert: function () {
+	        return 0;
+	      }
+	    }, {
+	      from: 'null',
+	      to: 'string',
+	      convert: function () {
+	        return 'null';
+	      }
+	    }, {
+	      from: 'null',
+	      to: 'BigNumber',
+	      convert: function () {
+	        return new type.BigNumber(0);
+	      }
+	    }, {
+	      from: 'Array',
+	      to: 'Matrix',
+	      convert: function (array) {
+	        // TODO: how to decide on the right type of matrix to create?
+	        return new type.DenseMatrix(array);
+	      }
+	    }, {
+	      from: 'Matrix',
+	      to: 'Array',
+	      convert: function (matrix) {
+	        return matrix.valueOf();
+	      }
+	    }
+	  ];
+
+	  return typed;
+	};
+
+
+/***/ },
+/* 7 */
+/***/ function(module, exports, __webpack_require__) {
+
+	var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/**
+	 * typed-function
+	 *
+	 * Type checking for JavaScript functions
+	 *
+	 * https://github.com/josdejong/typed-function
+	 */
+	'use strict';
+
+	(function (factory) {
+	  if (true) {
+	    // AMD. Register as an anonymous module.
+	    !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+	  } else if (typeof exports === 'object') {
+	    // OldNode. Does not work with strict CommonJS, but
+	    // only CommonJS-like environments that support module.exports,
+	    // like OldNode.
+	    module.exports = factory();
+	  } else {
+	    // Browser globals (root is window)
+	    window.typed = factory();
+	  }
+	}(function () {
+	  // factory function to create a new instance of typed-function
+	  // TODO: allow passing configuration, types, tests via the factory function
+	  function create() {
+	    /**
+	     * Get a type test function for a specific data type
+	     * @param {string} name                   Name of a data type like 'number' or 'string'
+	     * @returns {Function(obj: *) : boolean}  Returns a type testing function.
+	     *                                        Throws an error for an unknown type.
+	     */
+	    function getTypeTest(name) {
+	      var test;
+	      for (var i = 0; i < typed.types.length; i++) {
+	        var entry = typed.types[i];
+	        if (entry.name === name) {
+	          test = entry.test;
+	          break;
+	        }
+	      }
+
+	      if (!test) {
+	        var hint;
+	        for (i = 0; i < typed.types.length; i++) {
+	          entry = typed.types[i];
+	          if (entry.name.toLowerCase() == name.toLowerCase()) {
+	            hint = entry.name;
+	            break;
+	          }
+	        }
+
+	        throw new Error('Unknown type "' + name + '"' +
+	            (hint ? ('. Did you mean "' + hint + '"?') : ''));
+	      }
+	      return test;
+	    }
+
+	    /**
+	     * Retrieve the function name from a set of functions, and check
+	     * whether the name of all functions match (if given)
+	     * @param {Array.<function>} fns
+	     */
+	    function getName (fns) {
+	      var name = '';
+
+	      for (var i = 0; i < fns.length; i++) {
+	        var fn = fns[i];
+
+	        // merge function name
+	        if (fn.name != '') {
+	          if (name == '') {
+	            name = fn.name;
+	          }
+	          else if (name != fn.name) {
+	            var err = new Error('Function names do not match (expected: ' + name + ', actual: ' + fn.name + ')');
+	            err.data = {
+	              actual: fn.name,
+	              expected: name
+	            };
+	            throw err;
+	          }
+	        }
+	      }
+
+	      return name;
+	    }
+
+	    /**
+	     * Create an ArgumentsError. Creates messages like:
+	     *
+	     *   Unexpected type of argument (expected: ..., actual: ..., index: ...)
+	     *   Too few arguments (expected: ..., index: ...)
+	     *   Too many arguments (expected: ..., actual: ...)
+	     *
+	     * @param {String} fn         Function name
+	     * @param {number} argCount   Number of arguments
+	     * @param {Number} index      Current argument index
+	     * @param {*} actual          Current argument
+	     * @param {string} [expected] An optional, comma separated string with
+	     *                            expected types on given index
+	     * @extends Error
+	     */
+	    function createError(fn, argCount, index, actual, expected) {
+	      var actualType = getTypeOf(actual);
+	      var _expected = expected ? expected.split(',') : null;
+	      var _fn = (fn || 'unnamed');
+	      var anyType = _expected && contains(_expected, 'any');
+	      var message;
+	      var data = {
+	        fn: fn,
+	        index: index,
+	        actual: actual,
+	        expected: _expected
+	      };
+
+	      if (_expected) {
+	        if (argCount > index && !anyType) {
+	          // unexpected type
+	          message = 'Unexpected type of argument in function ' + _fn +
+	              ' (expected: ' + _expected.join(' or ') + ', actual: ' + actualType + ', index: ' + index + ')';
+	        }
+	        else {
+	          // too few arguments
+	          message = 'Too few arguments in function ' + _fn +
+	              ' (expected: ' + _expected.join(' or ') + ', index: ' + index + ')';
+	        }
+	      }
+	      else {
+	        // too many arguments
+	        message = 'Too many arguments in function ' + _fn +
+	            ' (expected: ' + index + ', actual: ' + argCount + ')'
+	      }
+
+	      var err = new TypeError(message);
+	      err.data = data;
+	      return err;
+	    }
+
+	    /**
+	     * Collection with function references (local shortcuts to functions)
+	     * @constructor
+	     * @param {string} [name='refs']  Optional name for the refs, used to generate
+	     *                                JavaScript code
+	     */
+	    function Refs(name) {
+	      this.name = name || 'refs';
+	      this.categories = {};
+	    }
+
+	    /**
+	     * Add a function reference.
+	     * @param {Function} fn
+	     * @param {string} [category='fn']    A function category, like 'fn' or 'signature'
+	     * @returns {string} Returns the function name, for example 'fn0' or 'signature2'
+	     */
+	    Refs.prototype.add = function (fn, category) {
+	      var cat = category || 'fn';
+	      if (!this.categories[cat]) this.categories[cat] = [];
+
+	      var index = this.categories[cat].indexOf(fn);
+	      if (index == -1) {
+	        index = this.categories[cat].length;
+	        this.categories[cat].push(fn);
+	      }
+
+	      return cat + index;
+	    };
+
+	    /**
+	     * Create code lines for all function references
+	     * @returns {string} Returns the code containing all function references
+	     */
+	    Refs.prototype.toCode = function () {
+	      var code = [];
+	      var path = this.name + '.categories';
+	      var categories = this.categories;
+
+	      for (var cat in categories) {
+	        if (categories.hasOwnProperty(cat)) {
+	          var category = categories[cat];
+
+	          for (var i = 0; i < category.length; i++) {
+	            code.push('var ' + cat + i + ' = ' + path + '[\'' + cat + '\'][' + i + '];');
+	          }
+	        }
+	      }
+
+	      return code.join('\n');
+	    };
+
+	    /**
+	     * A function parameter
+	     * @param {string | string[] | Param} types    A parameter type like 'string',
+	     *                                             'number | boolean'
+	     * @param {boolean} [varArgs=false]            Variable arguments if true
+	     * @constructor
+	     */
+	    function Param(types, varArgs) {
+	      // parse the types, can be a string with types separated by pipe characters |
+	      if (typeof types === 'string') {
+	        // parse variable arguments operator (ellipses '...number')
+	        var _types = types.trim();
+	        var _varArgs = _types.substr(0, 3) === '...';
+	        if (_varArgs) {
+	          _types = _types.substr(3);
+	        }
+	        if (_types === '') {
+	          this.types = ['any'];
+	        }
+	        else {
+	          this.types = _types.split('|');
+	          for (var i = 0; i < this.types.length; i++) {
+	            this.types[i] = this.types[i].trim();
+	          }
+	        }
+	      }
+	      else if (Array.isArray(types)) {
+	        this.types = types;
+	      }
+	      else if (types instanceof Param) {
+	        return types.clone();
+	      }
+	      else {
+	        throw new Error('String or Array expected');
+	      }
+
+	      // can hold a type to which to convert when handling this parameter
+	      this.conversions = [];
+	      // TODO: implement better API for conversions, be able to add conversions via constructor (support a new type Object?)
+
+	      // variable arguments
+	      this.varArgs = _varArgs || varArgs || false;
+
+	      // check for any type arguments
+	      this.anyType = this.types.indexOf('any') !== -1;
+	    }
+
+	    /**
+	     * Order Params
+	     * any type ('any') will be ordered last, and object as second last (as other
+	     * types may be an object as well, like Array).
+	     *
+	     * @param {Param} a
+	     * @param {Param} b
+	     * @returns {number} Returns 1 if a > b, -1 if a < b, and else 0.
+	     */
+	    Param.compare = function (a, b) {
+	      // TODO: simplify parameter comparison, it's a mess
+	      if (a.anyType) return 1;
+	      if (b.anyType) return -1;
+
+	      if (contains(a.types, 'Object')) return 1;
+	      if (contains(b.types, 'Object')) return -1;
+
+	      if (a.hasConversions()) {
+	        if (b.hasConversions()) {
+	          var i, ac, bc;
+
+	          for (i = 0; i < a.conversions.length; i++) {
+	            if (a.conversions[i] !== undefined) {
+	              ac = a.conversions[i];
+	              break;
+	            }
+	          }
+
+	          for (i = 0; i < b.conversions.length; i++) {
+	            if (b.conversions[i] !== undefined) {
+	              bc = b.conversions[i];
+	              break;
+	            }
+	          }
+
+	          return typed.conversions.indexOf(ac) - typed.conversions.indexOf(bc);
+	        }
+	        else {
+	          return 1;
+	        }
+	      }
+	      else {
+	        if (b.hasConversions()) {
+	          return -1;
+	        }
+	        else {
+	          // both params have no conversions
+	          var ai, bi;
+
+	          for (i = 0; i < typed.types.length; i++) {
+	            if (typed.types[i].name === a.types[0]) {
+	              ai = i;
+	              break;
+	            }
+	          }
+
+	          for (i = 0; i < typed.types.length; i++) {
+	            if (typed.types[i].name === b.types[0]) {
+	              bi = i;
+	              break;
+	            }
+	          }
+
+	          return ai - bi;
+	        }
+	      }
+	    };
+
+	    /**
+	     * Test whether this parameters types overlap an other parameters types.
+	     * @param {Param} other
+	     * @return {boolean} Returns true when there are conflicting types
+	     */
+	    Param.prototype.overlapping = function (other) {
+	      for (var i = 0; i < this.types.length; i++) {
+	        if (contains(other.types, this.types[i])) {
+	          return true;
+	        }
+	      }
+	      return false;
+	    };
+
+	    /**
+	     * Create a clone of this param
+	     * @returns {Param} Returns a cloned version of this param
+	     */
+	    Param.prototype.clone = function () {
+	      var param = new Param(this.types.slice(), this.varArgs);
+	      param.conversions = this.conversions.slice();
+	      return param;
+	    };
+
+	    /**
+	     * Test whether this parameter contains conversions
+	     * @returns {boolean} Returns true if the parameter contains one or
+	     *                    multiple conversions.
+	     */
+	    Param.prototype.hasConversions = function () {
+	      return this.conversions.length > 0;
+	    };
+
+	    /**
+	     * Tests whether this parameters contains any of the provided types
+	     * @param {Object} types  A Map with types, like {'number': true}
+	     * @returns {boolean}     Returns true when the parameter contains any
+	     *                        of the provided types
+	     */
+	    Param.prototype.contains = function (types) {
+	      for (var i = 0; i < this.types.length; i++) {
+	        if (types[this.types[i]]) {
+	          return true;
+	        }
+	      }
+	      return false;
+	    };
+
+	    /**
+	     * Return a string representation of this params types, like 'string' or
+	     * 'number | boolean' or '...number'
+	     * @param {boolean} [toConversion]   If true, the returned types string
+	     *                                   contains the types where the parameter
+	     *                                   will convert to. If false (default)
+	     *                                   the "from" types are returned
+	     * @returns {string}
+	     */
+	    Param.prototype.toString = function (toConversion) {
+	      var types = [];
+	      var keys = {};
+
+	      for (var i = 0; i < this.types.length; i++) {
+	        var conversion = this.conversions[i];
+	        var type = toConversion && conversion ? conversion.to : this.types[i];
+	        if (!(type in keys)) {
+	          keys[type] = true;
+	          types.push(type);
+	        }
+	      }
+
+	      return (this.varArgs ? '...' : '') + types.join('|');
+	    };
+
+	    /**
+	     * A function signature
+	     * @param {string | string[] | Param[]} params
+	     *                         Array with the type(s) of each parameter,
+	     *                         or a comma separated string with types
+	     * @param {Function} fn    The actual function
+	     * @constructor
+	     */
+	    function Signature(params, fn) {
+	      var _params;
+	      if (typeof params === 'string') {
+	        _params = (params !== '') ? params.split(',') : [];
+	      }
+	      else if (Array.isArray(params)) {
+	        _params = params;
+	      }
+	      else {
+	        throw new Error('string or Array expected');
+	      }
+
+	      this.params = new Array(_params.length);
+	      for (var i = 0; i < _params.length; i++) {
+	        var param = new Param(_params[i]);
+	        this.params[i] = param;
+	        if (i === _params.length - 1) {
+	          // the last argument
+	          this.varArgs = param.varArgs;
+	        }
+	        else {
+	          // non-last argument
+	          if (param.varArgs) {
+	            throw new SyntaxError('Unexpected variable arguments operator "..."');
+	          }
+	        }
+	      }
+
+	      this.fn = fn;
+	    }
+
+	    /**
+	     * Create a clone of this signature
+	     * @returns {Signature} Returns a cloned version of this signature
+	     */
+	    Signature.prototype.clone = function () {
+	      return new Signature(this.params.slice(), this.fn);
+	    };
+
+	    /**
+	     * Expand a signature: split params with union types in separate signatures
+	     * For example split a Signature "string | number" into two signatures.
+	     * @return {Signature[]} Returns an array with signatures (at least one)
+	     */
+	    Signature.prototype.expand = function () {
+	      var signatures = [];
+
+	      function recurse(signature, path) {
+	        if (path.length < signature.params.length) {
+	          var i, newParam, conversion;
+
+	          var param = signature.params[path.length];
+	          if (param.varArgs) {
+	            // a variable argument. do not split the types in the parameter
+	            newParam = param.clone();
+
+	            // add conversions to the parameter
+	            // recurse for all conversions
+	            for (i = 0; i < typed.conversions.length; i++) {
+	              conversion = typed.conversions[i];
+	              if (!contains(param.types, conversion.from) && contains(param.types, conversion.to)) {
+	                var j = newParam.types.length;
+	                newParam.types[j] = conversion.from;
+	                newParam.conversions[j] = conversion;
+	              }
+	            }
+
+	            recurse(signature, path.concat(newParam));
+	          }
+	          else {
+	            // split each type in the parameter
+	            for (i = 0; i < param.types.length; i++) {
+	              recurse(signature, path.concat(new Param(param.types[i])));
+	            }
+
+	            // recurse for all conversions
+	            for (i = 0; i < typed.conversions.length; i++) {
+	              conversion = typed.conversions[i];
+	              if (!contains(param.types, conversion.from) && contains(param.types, conversion.to)) {
+	                newParam = new Param(conversion.from);
+	                newParam.conversions[0] = conversion;
+	                recurse(signature, path.concat(newParam));
+	              }
+	            }
+	          }
+	        }
+	        else {
+	          signatures.push(new Signature(path, signature.fn));
+	        }
+	      }
+
+	      recurse(this, []);
+
+	      return signatures;
+	    };
+
+	    /**
+	     * Compare two signatures.
+	     *
+	     * When two params are equal and contain conversions, they will be sorted
+	     * by lowest index of the first conversions.
+	     *
+	     * @param {Signature} a
+	     * @param {Signature} b
+	     * @returns {number} Returns 1 if a > b, -1 if a < b, and else 0.
+	     */
+	    Signature.compare = function (a, b) {
+	      if (a.params.length > b.params.length) return 1;
+	      if (a.params.length < b.params.length) return -1;
+
+	      // count the number of conversions
+	      var i;
+	      var len = a.params.length; // a and b have equal amount of params
+	      var ac = 0;
+	      var bc = 0;
+	      for (i = 0; i < len; i++) {
+	        if (a.params[i].hasConversions()) ac++;
+	        if (b.params[i].hasConversions()) bc++;
+	      }
+
+	      if (ac > bc) return 1;
+	      if (ac < bc) return -1;
+
+	      // compare the order per parameter
+	      for (i = 0; i < a.params.length; i++) {
+	        var cmp = Param.compare(a.params[i], b.params[i]);
+	        if (cmp !== 0) {
+	          return cmp;
+	        }
+	      }
+
+	      return 0;
+	    };
+
+	    /**
+	     * Test whether any of the signatures parameters has conversions
+	     * @return {boolean} Returns true when any of the parameters contains
+	     *                   conversions.
+	     */
+	    Signature.prototype.hasConversions = function () {
+	      for (var i = 0; i < this.params.length; i++) {
+	        if (this.params[i].hasConversions()) {
+	          return true;
+	        }
+	      }
+	      return false;
+	    };
+
+	    /**
+	     * Test whether this signature should be ignored.
+	     * Checks whether any of the parameters contains a type listed in
+	     * typed.ignore
+	     * @return {boolean} Returns true when the signature should be ignored
+	     */
+	    Signature.prototype.ignore = function () {
+	      // create a map with ignored types
+	      var types = {};
+	      for (var i = 0; i < typed.ignore.length; i++) {
+	        types[typed.ignore[i]] = true;
+	      }
+
+	      // test whether any of the parameters contains this type
+	      for (i = 0; i < this.params.length; i++) {
+	        if (this.params[i].contains(types)) {
+	          return true;
+	        }
+	      }
+
+	      return false;
+	    };
+
+	    /**
+	     * Generate the code to invoke this signature
+	     * @param {Refs} refs
+	     * @param {string} prefix
+	     * @returns {string} Returns code
+	     */
+	    Signature.prototype.toCode = function (refs, prefix) {
+	      var code = [];
+
+	      var args = new Array(this.params.length);
+	      for (var i = 0; i < this.params.length; i++) {
+	        var param = this.params[i];
+	        var conversion = param.conversions[0];
+	        if (param.varArgs) {
+	          args[i] = 'varArgs';
+	        }
+	        else if (conversion) {
+	          args[i] = refs.add(conversion.convert, 'convert') + '(arg' + i + ')';
+	        }
+	        else {
+	          args[i] = 'arg' + i;
+	        }
+	      }
+
+	      var ref = this.fn ? refs.add(this.fn, 'signature') : undefined;
+	      if (ref) {
+	        return prefix + 'return ' + ref + '(' + args.join(', ') + '); // signature: ' + this.params.join(', ');
+	      }
+
+	      return code.join('\n');
+	    };
+
+	    /**
+	     * Return a string representation of the signature
+	     * @returns {string}
+	     */
+	    Signature.prototype.toString = function () {
+	      return this.params.join(', ');
+	    };
+
+	    /**
+	     * A group of signatures with the same parameter on given index
+	     * @param {Param[]} path
+	     * @param {Signature} [signature]
+	     * @param {Node[]} childs
+	     * @constructor
+	     */
+	    function Node(path, signature, childs) {
+	      this.path = path || [];
+	      this.param = path[path.length - 1] || null;
+	      this.signature = signature || null;
+	      this.childs = childs || [];
+	    }
+
+	    /**
+	     * Generate code for this group of signatures
+	     * @param {Refs} refs
+	     * @param {string} prefix
+	     * @param {Node | undefined} [anyType]  Sibling of this node with any type parameter
+	     * @returns {string} Returns the code as string
+	     */
+	    Node.prototype.toCode = function (refs, prefix, anyType) {
+	      // TODO: split this function in multiple functions, it's too large
+	      var code = [];
+
+	      if (this.param) {
+	        var index = this.path.length - 1;
+	        var conversion = this.param.conversions[0];
+	        var comment = '// type: ' + (conversion ?
+	                (conversion.from + ' (convert to ' + conversion.to + ')') :
+	                this.param);
+
+	        // non-root node (path is non-empty)
+	        if (this.param.varArgs) {
+	          if (this.param.anyType) {
+	            // variable arguments with any type
+	            code.push(prefix + 'if (arguments.length > ' + index + ') {');
+	            code.push(prefix + '  var varArgs = [];');
+	            code.push(prefix + '  for (var i = ' + index + '; i < arguments.length; i++) {');
+	            code.push(prefix + '    varArgs.push(arguments[i]);');
+	            code.push(prefix + '  }');
+	            code.push(this.signature.toCode(refs, prefix + '  '));
+	            code.push(prefix + '}');
+	          }
+	          else {
+	            // variable arguments with a fixed type
+	            var getTests = function (types, arg) {
+	              var tests = [];
+	              for (var i = 0; i < types.length; i++) {
+	                tests[i] = refs.add(getTypeTest(types[i]), 'test') + '(' + arg + ')';
+	              }
+	              return tests.join(' || ');
+	            }.bind(this);
+
+	            var allTypes = this.param.types;
+	            var exactTypes = [];
+	            for (var i = 0; i < allTypes.length; i++) {
+	              if (this.param.conversions[i] === undefined) {
+	                exactTypes.push(allTypes[i]);
+	              }
+	            }
+
+	            code.push(prefix + 'if (' + getTests(allTypes, 'arg' + index) + ') { ' + comment);
+	            code.push(prefix + '  var varArgs = [arg' + index + '];');
+	            code.push(prefix + '  for (var i = ' + (index + 1) + '; i < arguments.length; i++) {');
+	            code.push(prefix + '    if (' + getTests(exactTypes, 'arguments[i]') + ') {');
+	            code.push(prefix + '      varArgs.push(arguments[i]);');
+
+	            for (var i = 0; i < allTypes.length; i++) {
+	              var conversion_i = this.param.conversions[i];
+	              if (conversion_i) {
+	                var test = refs.add(getTypeTest(allTypes[i]), 'test');
+	                var convert = refs.add(conversion_i.convert, 'convert');
+	                code.push(prefix + '    }');
+	                code.push(prefix + '    else if (' + test + '(arguments[i])) {');
+	                code.push(prefix + '      varArgs.push(' + convert + '(arguments[i]));');
+	              }
+	            }
+	            code.push(prefix + '    } else {');
+	            code.push(prefix + '      throw createError(name, arguments.length, i, arguments[i], \'' + exactTypes.join(',') + '\');');
+	            code.push(prefix + '    }');
+	            code.push(prefix + '  }');
+	            code.push(this.signature.toCode(refs, prefix + '  '));
+	            code.push(prefix + '}');
+	          }
+	        }
+	        else {
+	          if (this.param.anyType) {
+	            // any type
+	            code.push(prefix + '// type: any');
+	            code.push(this._innerCode(refs, prefix, anyType));
+	          }
+	          else {
+	            // regular type
+	            var type = this.param.types[0];
+	            var test = type !== 'any' ? refs.add(getTypeTest(type), 'test') : null;
+
+	            code.push(prefix + 'if (' + test + '(arg' + index + ')) { ' + comment);
+	            code.push(this._innerCode(refs, prefix + '  ', anyType));
+	            code.push(prefix + '}');
+	          }
+	        }
+	      }
+	      else {
+	        // root node (path is empty)
+	        code.push(this._innerCode(refs, prefix, anyType));
+	      }
+
+	      return code.join('\n');
+	    };
+
+	    /**
+	     * Generate inner code for this group of signatures.
+	     * This is a helper function of Node.prototype.toCode
+	     * @param {Refs} refs
+	     * @param {string} prefix
+	     * @param {Node | undefined} [anyType]  Sibling of this node with any type parameter
+	     * @returns {string} Returns the inner code as string
+	     * @private
+	     */
+	    Node.prototype._innerCode = function (refs, prefix, anyType) {
+	      var code = [];
+	      var i;
+
+	      if (this.signature) {
+	        code.push(prefix + 'if (arguments.length === ' + this.path.length + ') {');
+	        code.push(this.signature.toCode(refs, prefix + '  '));
+	        code.push(prefix + '}');
+	      }
+
+	      var nextAnyType;
+	      for (i = 0; i < this.childs.length; i++) {
+	        if (this.childs[i].param.anyType) {
+	          nextAnyType = this.childs[i];
+	          break;
+	        }
+	      }
+
+	      for (i = 0; i < this.childs.length; i++) {
+	        code.push(this.childs[i].toCode(refs, prefix, nextAnyType));
+	      }
+
+	      if (anyType && !this.param.anyType) {
+	        code.push(anyType.toCode(refs, prefix, nextAnyType));
+	      }
+
+	      var exceptions = this._exceptions(refs, prefix);
+	      if (exceptions) {
+	        code.push(exceptions);
+	      }
+
+	      return code.join('\n');
+	    };
+
+	    /**
+	     * Generate code to throw exceptions
+	     * @param {Refs} refs
+	     * @param {string} prefix
+	     * @returns {string} Returns the inner code as string
+	     * @private
+	     */
+	    Node.prototype._exceptions = function (refs, prefix) {
+	      var index = this.path.length;
+
+	      if (this.childs.length === 0) {
+	        // TODO: can this condition be simplified? (we have a fall-through here)
+	        return [
+	          prefix + 'if (arguments.length > ' + index + ') {',
+	          prefix + '  throw createError(name, arguments.length, ' + index + ', arguments[' + index + ']);',
+	          prefix + '}'
+	        ].join('\n');
+	      }
+	      else {
+	        var keys = {};
+	        var types = [];
+
+	        for (var i = 0; i < this.childs.length; i++) {
+	          var node = this.childs[i];
+	          if (node.param) {
+	            for (var j = 0; j < node.param.types.length; j++) {
+	              var type = node.param.types[j];
+	              if (!(type in keys) && !node.param.conversions[j]) {
+	                keys[type] = true;
+	                types.push(type);
+	              }
+	            }
+	          }
+	        }
+
+	        return prefix + 'throw createError(name, arguments.length, ' + index + ', arguments[' + index + '], \'' + types.join(',') + '\');';
+	      }
+	    };
+
+	    /**
+	     * Split all raw signatures into an array with expanded Signatures
+	     * @param {Object.<string, Function>} rawSignatures
+	     * @return {Signature[]} Returns an array with expanded signatures
+	     */
+	    function parseSignatures(rawSignatures) {
+	      // FIXME: need to have deterministic ordering of signatures, do not create via object
+	      var signature;
+	      var keys = {};
+	      var signatures = [];
+	      var i;
+
+	      for (var types in rawSignatures) {
+	        if (rawSignatures.hasOwnProperty(types)) {
+	          var fn = rawSignatures[types];
+	          signature = new Signature(types, fn);
+
+	          if (signature.ignore()) {
+	            continue;
+	          }
+
+	          var expanded = signature.expand();
+
+	          for (i = 0; i < expanded.length; i++) {
+	            var signature_i = expanded[i];
+	            var key = signature_i.toString();
+	            var existing = keys[key];
+	            if (!existing) {
+	              keys[key] = signature_i;
+	            }
+	            else {
+	              var cmp = Signature.compare(signature_i, existing);
+	              if (cmp < 0) {
+	                // override if sorted first
+	                keys[key] = signature_i;
+	              }
+	              else if (cmp === 0) {
+	                throw new Error('Signature "' + key + '" is defined twice');
+	              }
+	              // else: just ignore
+	            }
+	          }
+	        }
+	      }
+
+	      // convert from map to array
+	      for (key in keys) {
+	        if (keys.hasOwnProperty(key)) {
+	          signatures.push(keys[key]);
+	        }
+	      }
+
+	      // order the signatures
+	      signatures.sort(function (a, b) {
+	        return Signature.compare(a, b);
+	      });
+
+	      // filter redundant conversions from signatures with varArgs
+	      // TODO: simplify this loop or move it to a separate function
+	      for (i = 0; i < signatures.length; i++) {
+	        signature = signatures[i];
+
+	        if (signature.varArgs) {
+	          var index = signature.params.length - 1;
+	          var param = signature.params[index];
+
+	          var t = 0;
+	          while (t < param.types.length) {
+	            if (param.conversions[t]) {
+	              var type = param.types[t];
+
+	              for (var j = 0; j < signatures.length; j++) {
+	                var other = signatures[j];
+	                var p = other.params[index];
+
+	                if (other !== signature &&
+	                    p &&
+	                    contains(p.types, type) && !p.conversions[index]) {
+	                  // this (conversion) type already exists, remove it
+	                  param.types.splice(t, 1);
+	                  param.conversions.splice(t, 1);
+	                  t--;
+	                  break;
+	                }
+	              }
+	            }
+	            t++;
+	          }
+	        }
+	      }
+
+	      return signatures;
+	    }
+
+	    /**
+	     * create a map with normalized signatures as key and the function as value
+	     * @param {Signature[]} signatures   An array with split signatures
+	     * @return {Object.<string, Function>} Returns a map with normalized
+	     *                                     signatures as key, and the function
+	     *                                     as value.
+	     */
+	    function mapSignatures(signatures) {
+	      var normalized = {};
+
+	      for (var i = 0; i < signatures.length; i++) {
+	        var signature = signatures[i];
+	        if (signature.fn && !signature.hasConversions()) {
+	          var params = signature.params.join(',');
+	          normalized[params] = signature.fn;
+	        }
+	      }
+
+	      return normalized;
+	    }
+
+	    /**
+	     * Parse signatures recursively in a node tree.
+	     * @param {Signature[]} signatures  Array with expanded signatures
+	     * @param {Param[]} path            Traversed path of parameter types
+	     * @return {Node}                   Returns a node tree
+	     */
+	    function parseTree(signatures, path) {
+	      var i, signature;
+	      var index = path.length;
+	      var nodeSignature;
+
+	      var filtered = [];
+	      for (i = 0; i < signatures.length; i++) {
+	        signature = signatures[i];
+
+	        // filter the first signature with the correct number of params
+	        if (signature.params.length === index && !nodeSignature) {
+	          nodeSignature = signature;
+	        }
+
+	        if (signature.params[index] != undefined) {
+	          filtered.push(signature);
+	        }
+	      }
+
+	      // sort the filtered signatures by param
+	      filtered.sort(function (a, b) {
+	        return Param.compare(a.params[index], b.params[index]);
+	      });
+
+	      // recurse over the signatures
+	      var entries = [];
+	      for (i = 0; i < filtered.length; i++) {
+	        signature = filtered[i];
+	        // group signatures with the same param at current index
+	        var param = signature.params[index];
+
+	        // TODO: replace the next filter loop
+	        var existing = entries.filter(function (entry) {
+	          return entry.param.overlapping(param);
+	        })[0];
+
+	        //var existing;
+	        //for (var j = 0; j < entries.length; j++) {
+	        //  if (entries[j].param.overlapping(param)) {
+	        //    existing = entries[j];
+	        //    break;
+	        //  }
+	        //}
+
+	        if (existing) {
+	          if (existing.param.varArgs) {
+	            throw new Error('Conflicting types "' + existing.param + '" and "' + param + '"');
+	          }
+	          existing.signatures.push(signature);
+	        }
+	        else {
+	          entries.push({
+	            param: param,
+	            signatures: [signature]
+	          });
+	        }
+	      }
+
+	      // parse the childs
+	      var childs = new Array(entries.length);
+	      for (i = 0; i < entries.length; i++) {
+	        var entry = entries[i];
+	        childs[i] = parseTree(entry.signatures, path.concat(entry.param))
+	      }
+
+	      return new Node(path, nodeSignature, childs);
+	    }
+
+	    /**
+	     * Generate an array like ['arg0', 'arg1', 'arg2']
+	     * @param {number} count Number of arguments to generate
+	     * @returns {Array} Returns an array with argument names
+	     */
+	    function getArgs(count) {
+	      // create an array with all argument names
+	      var args = [];
+	      for (var i = 0; i < count; i++) {
+	        args[i] = 'arg' + i;
+	      }
+
+	      return args;
+	    }
+
+	    /**
+	     * Compose a function from sub-functions each handling a single type signature.
+	     * Signatures:
+	     *   typed(signature: string, fn: function)
+	     *   typed(name: string, signature: string, fn: function)
+	     *   typed(signatures: Object.<string, function>)
+	     *   typed(name: string, signatures: Object.<string, function>)
+	     *
+	     * @param {string | null} name
+	     * @param {Object.<string, Function>} signatures
+	     * @return {Function} Returns the typed function
+	     * @private
+	     */
+	    function _typed(name, signatures) {
+	      var refs = new Refs();
+
+	      // parse signatures, expand them
+	      var _signatures = parseSignatures(signatures);
+	      if (_signatures.length == 0) {
+	        throw new Error('No signatures provided');
+	      }
+
+	      // parse signatures into a node tree
+	      var node = parseTree(_signatures, []);
+
+	      //var util = require('util');
+	      //console.log('ROOT');
+	      //console.log(util.inspect(node, { depth: null }));
+
+	      // generate code for the typed function
+	      var code = [];
+	      var _name = name || '';
+	      var _args = getArgs(maxParams(_signatures));
+	      code.push('function ' + _name + '(' + _args.join(', ') + ') {');
+	      code.push('  "use strict";');
+	      code.push('  var name = \'' + _name + '\';');
+	      code.push(node.toCode(refs, '  '));
+	      code.push('}');
+
+	      // generate body for the factory function
+	      var body = [
+	        refs.toCode(),
+	        'return ' + code.join('\n')
+	      ].join('\n');
+
+	      // evaluate the JavaScript code and attach function references
+	      var factory = (new Function(refs.name, 'createError', body));
+	      var fn = factory(refs, createError);
+
+	      //console.log('FN\n' + fn.toString()); // TODO: cleanup
+
+	      // attach the signatures with sub-functions to the constructed function
+	      fn.signatures = mapSignatures(_signatures);
+
+	      return fn;
+	    }
+
+	    /**
+	     * Calculate the maximum number of parameters in givens signatures
+	     * @param {Signature[]} signatures
+	     * @returns {number} The maximum number of parameters
+	     */
+	    function maxParams(signatures) {
+	      var max = 0;
+
+	      for (var i = 0; i < signatures.length; i++) {
+	        var len = signatures[i].params.length;
+	        if (len > max) {
+	          max = len;
+	        }
+	      }
+
+	      return max;
+	    }
+
+	    /**
+	     * Get the type of a value
+	     * @param {*} x
+	     * @returns {string} Returns a string with the type of value
+	     */
+	    function getTypeOf(x) {
+	      var obj;
+
+	      for (var i = 0; i < typed.types.length; i++) {
+	        var entry = typed.types[i];
+
+	        if (entry.name === 'Object') {
+	          // Array and Date are also Object, so test for Object afterwards
+	          obj = entry;
+	        }
+	        else {
+	          if (entry.test(x)) return entry.name;
+	        }
+	      }
+
+	      // at last, test whether an object
+	      if (obj && obj.test(x)) return obj.name;
+
+	      return 'unknown';
+	    }
+
+	    /**
+	     * Test whether an array contains some entry
+	     * @param {Array} array
+	     * @param {*} entry
+	     * @return {boolean} Returns true if array contains entry, false if not.
+	     */
+	    function contains(array, entry) {
+	      return array.indexOf(entry) !== -1;
+	    }
+
+	    // data type tests
+	    var types = [
+	      { name: 'number',    test: function (x) { return typeof x === 'number' } },
+	      { name: 'string',    test: function (x) { return typeof x === 'string' } },
+	      { name: 'boolean',   test: function (x) { return typeof x === 'boolean' } },
+	      { name: 'Function',  test: function (x) { return typeof x === 'function'} },
+	      { name: 'Array',     test: Array.isArray },
+	      { name: 'Date',      test: function (x) { return x instanceof Date } },
+	      { name: 'RegExp',    test: function (x) { return x instanceof RegExp } },
+	      { name: 'Object',    test: function (x) { return typeof x === 'object' } },
+	      { name: 'null',      test: function (x) { return x === null } },
+	      { name: 'undefined', test: function (x) { return x === undefined } }
+	    ];
+
+	    // configuration
+	    var config = {};
+
+	    // type conversions. Order is important
+	    var conversions = [];
+
+	    // types to be ignored
+	    var ignore = [];
+
+	    // temporary object for holding types and conversions, for constructing
+	    // the `typed` function itself
+	    // TODO: find a more elegant solution for this
+	    var typed = {
+	      config: config,
+	      types: types,
+	      conversions: conversions,
+	      ignore: ignore
+	    };
+
+	    /**
+	     * Construct the typed function itself with various signatures
+	     *
+	     * Signatures:
+	     *
+	     *   typed(signatures: Object.<string, function>)
+	     *   typed(name: string, signatures: Object.<string, function>)
+	     */
+	    typed = _typed('typed', {
+	      'Object': function (signatures) {
+	        var fns = [];
+	        for (var signature in signatures) {
+	          if (signatures.hasOwnProperty(signature)) {
+	            fns.push(signatures[signature]);
+	          }
+	        }
+	        var name = getName(fns);
+
+	        return _typed(name, signatures);
+	      },
+	      'string, Object': _typed,
+	      // TODO: add a signature 'Array.<function>'
+	      '...Function': function (fns) {
+	        var err;
+	        var name = getName(fns);
+	        var signatures = {};
+
+	        for (var i = 0; i < fns.length; i++) {
+	          var fn = fns[i];
+
+	          // test whether this is a typed-function
+	          if (!(typeof fn.signatures === 'object')) {
+	            err = new TypeError('Function is no typed-function (index: ' + i + ')');
+	            err.data = {index: i};
+	            throw err;
+	          }
+
+	          // merge the signatures
+	          for (var signature in fn.signatures) {
+	            if (fn.signatures.hasOwnProperty(signature)) {
+	              if (signatures.hasOwnProperty(signature)) {
+	                if (fn.signatures[signature] !== signatures[signature]) {
+	                  err = new Error('Signature "' + signature + '" is defined twice');
+	                  err.data = {signature: signature};
+	                  throw err;
+	                }
+	                // else: both signatures point to the same function, that's fine
+	              }
+	              else {
+	                signatures[signature] = fn.signatures[signature];
+	              }
+	            }
+	          }
+	        }
+
+	        return _typed(name, signatures);
+	      }
+	    });
+
+	    /**
+	     * Find a specific signature from a (composed) typed function, for
+	     * example:
+	     *
+	     *   typed.find(fn, ['number', 'string'])
+	     *   typed.find(fn, 'number, string')
+	     *
+	     * Function find only only works for exact matches.
+	     *
+	     * @param {Function} fn                   A typed-function
+	     * @param {string | string[]} signature   Signature to be found, can be
+	     *                                        an array or a comma separated string.
+	     * @return {Function}                     Returns the matching signature, or
+	     *                                        throws an errror when no signature
+	     *                                        is found.
+	     */
+	    function find (fn, signature) {
+	      if (!fn.signatures) {
+	        throw new TypeError('Function is no typed-function');
+	      }
+
+	      // normalize input
+	      var arr;
+	      if (typeof signature === 'string') {
+	        arr = signature.split(',');
+	        for (var i = 0; i < arr.length; i++) {
+	          arr[i] = arr[i].trim();
+	        }
+	      }
+	      else if (Array.isArray(signature)) {
+	        arr = signature;
+	      }
+	      else {
+	        throw new TypeError('String array or a comma separated string expected');
+	      }
+
+	      var str = arr.join(',');
+
+	      // find an exact match
+	      var match = fn.signatures[str];
+	      if (match) {
+	        return match;
+	      }
+
+	      // TODO: extend find to match non-exact signatures
+
+	      throw new TypeError('Signature not found (signature: ' + (fn.name || 'unnamed') + '(' + arr.join(', ') + '))');
+	    }
+
+	    /**
+	     * Convert a given value to another data type.
+	     * @param {*} value
+	     * @param {string} type
+	     */
+	    function convert (value, type) {
+	      var from = getTypeOf(value);
+	      
+	      // check conversion is needed
+	      if (type === from) {
+	        return value;
+	      }
+
+	      for (var i = 0; i < typed.conversions.length; i++) {
+	        var conversion = typed.conversions[i];
+	        if (conversion.from === from && conversion.to === type) {
+	          return conversion.convert(value);
+	        }
+	      }
+
+	      throw new Error('Cannot convert from ' + from + ' to ' + type);
+	    }
+
+	    // attach types and conversions to the final `typed` function
+	    typed.config = config;
+	    typed.types = types;
+	    typed.conversions = conversions;
+	    typed.ignore = ignore;
+	    typed.create = create;
+	    typed.find = find;
+	    typed.convert = convert;
+
+	    // add a type
+	    typed.addType = function (type) {
+	      if (!type || typeof type.name !== 'string' || typeof type.test !== 'function') {
+	        throw new TypeError('Object with properties {name: string, test: function} expected');
+	      }
+
+	      typed.types.push(type);
+	    };
+
+	    // add a conversion
+	    typed.addConversion = function (conversion) {
+	      if (!conversion
+	          || typeof conversion.from !== 'string'
+	          || typeof conversion.to !== 'string'
+	          || typeof conversion.convert !== 'function') {
+	        throw new TypeError('Object with properties {from: string, to: string, convert: function} expected');
+	      }
+
+	      typed.conversions.push(conversion);
+	    };
+
+	    return typed;
+	  }
+
+	  return create();
+	}));
+
+
+/***/ },
+/* 8 */
+/***/ function(module, exports, __webpack_require__) {
+
+	'use strict';
+
+	var NumberFormatter = __webpack_require__(9);
+
+	/**
+	 * Test whether value is a number
 	 * @param {*} value
-	 * @return {Boolean} isNumber
+	 * @return {boolean} isNumber
 	 */
 	exports.isNumber = function(value) {
-	  return (value instanceof Number) || (typeof value == 'number');
+	  return typeof value === 'number';
 	};
 
 	/**
 	 * Check if a number is integer
-	 * @param {Number | Boolean} value
-	 * @return {Boolean} isInteger
+	 * @param {number | boolean} value
+	 * @return {boolean} isInteger
 	 */
 	exports.isInteger = function(value) {
-	  return (value == Math.round(value));
+	  return isFinite(value)
+	      ? (value == Math.round(value))
+	      : false;
 	  // Note: we use ==, not ===, as we can have Booleans as well
 	};
 
 	/**
 	 * Calculate the sign of a number
-	 * @param {Number} x
+	 * @param {number} x
 	 * @returns {*}
 	 */
 	exports.sign = function(x) {
@@ -767,9 +2133,9 @@
 	 *
 	 * Where:
 	 *
-	 *    {Number} value   The value to be formatted
+	 *    {number} value   The value to be formatted
 	 *    {Object} options An object with formatting options. Available options:
-	 *                     {String} notation
+	 *                     {string} notation
 	 *                         Number notation. Choose from:
 	 *                         'fixed'          Always use regular number notation.
 	 *                                          For example '123.40' and '14000000'
@@ -782,7 +2148,7 @@
 	 *                                          Lower bound is included, upper bound
 	 *                                          is excluded.
 	 *                                          For example '123.4' and '1.4e7'.
-	 *                     {Number} precision   A number between 0 and 16 to round
+	 *                     {number} precision   A number between 0 and 16 to round
 	 *                                          the digits of the number.
 	 *                                          In case of notations 'exponential' and
 	 *                                          'auto', `precision` defines the total
@@ -793,7 +2159,7 @@
 	 *                                          significant digits after the decimal
 	 *                                          point, and is 0 by default.
 	 *                     {Object} exponential An object containing two parameters,
-	 *                                          {Number} lower and {Number} upper,
+	 *                                          {number} lower and {number} upper,
 	 *                                          used by notation 'auto' to determine
 	 *                                          when to return exponential notation.
 	 *                                          Default values are `lower=1e-3` and
@@ -815,9 +2181,9 @@
 	 *    format(2.3,    {notation: 'fixed', precision: 2});  // '2.30'
 	 *    format(52.8,   {notation: 'exponential'});          // '5.28e+1'
 	 *
-	 * @param {Number} value
-	 * @param {Object | Function | Number} [options]
-	 * @return {String} str The formatted value
+	 * @param {number} value
+	 * @param {Object | Function | number} [options]
+	 * @return {string} str The formatted value
 	 */
 	exports.format = function(value, options) {
 	  if (typeof options === 'function') {
@@ -882,8 +2248,8 @@
 
 	/**
 	 * Format a number in exponential notation. Like '1.23e+5', '2.3e+0', '3.500e-3'
-	 * @param {Number} value
-	 * @param {Number} [precision]  Number of digits in formatted output.
+	 * @param {number} value
+	 * @param {number} [precision]  Number of digits in formatted output.
 	 *                              If not provided, the maximum available digits
 	 *                              is used.
 	 * @returns {string} str
@@ -894,8 +2260,8 @@
 
 	/**
 	 * Format a number with fixed notation.
-	 * @param {Number} value
-	 * @param {Number} [precision=0]        Optional number of decimals after the
+	 * @param {number} value
+	 * @param {number} [precision=0]        Optional number of decimals after the
 	 *                                      decimal point. Zero by default.
 	 */
 	exports.toFixed = function(value, precision) {
@@ -904,8 +2270,8 @@
 
 	/**
 	 * Format a number with a certain precision
-	 * @param {Number} value
-	 * @param {Number} [precision=undefined] Optional number of digits.
+	 * @param {number} value
+	 * @param {number} [precision=undefined] Optional number of digits.
 	 * @param {{lower: number, upper: number}} [options]  By default:
 	 *                                                    lower = 1e-3 (excl)
 	 *                                                    upper = 1e+5 (incl)
@@ -923,8 +2289,8 @@
 	 *   0.0034 returns 2
 	 *   120.5e+30 returns 4
 	 *
-	 * @param {Number} value
-	 * @return {Number} digits   Number of significant digits
+	 * @param {number} value
+	 * @return {number} digits   Number of significant digits
 	 */
 	exports.digits = function(value) {
 	  return value
@@ -941,9 +2307,9 @@
 
 	/**
 	 * Compares two floating point numbers.
-	 * @param {Number} x          First value to compare
-	 * @param {Number} y          Second value to compare
-	 * @param {Number} [epsilon]  The maximum relative difference between x and y
+	 * @param {number} x          First value to compare
+	 * @param {number} y          Second value to compare
+	 * @param {number} [epsilon]  The maximum relative difference between x and y
 	 *                            If epsilon is undefined or null, the function will
 	 *                            test whether x and y are exactly equal.
 	 * @return {boolean} whether the two numbers are equal
@@ -977,1167 +2343,216 @@
 
 
 /***/ },
-/* 4 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math, config) {
-	  var object = __webpack_require__(2);
-	  var bignumber = __webpack_require__(168);
-	  var Complex = __webpack_require__(7);
-	  var BigNumber = math.type.BigNumber;
-
-	  math['true']     = true;
-	  math['false']    = false;
-	  math['null']     = null;
-	  math['uninitialized'] = __webpack_require__(169).UNINITIALIZED;
-
-	  if (config.number === 'bignumber') {
-	    math['Infinity'] = new BigNumber(Infinity);
-	    math['NaN']      = new BigNumber(NaN);
-
-	    object.lazy(math, 'pi',  function () {return bignumber.pi(config.precision)});
-	    object.lazy(math, 'tau', function () {return bignumber.tau(config.precision)});
-	    object.lazy(math, 'e',   function () {return bignumber.e(config.precision)});
-	    object.lazy(math, 'phi', function () {return bignumber.phi(config.precision)}); // golden ratio, (1+sqrt(5))/2
-
-	    // uppercase constants (for compatibility with built-in Math)
-	    object.lazy(math, 'E',       function () {return math.e;});
-	    object.lazy(math, 'LN2',     function () {return new BigNumber(2).ln();});
-	    object.lazy(math, 'LN10',    function () {return new BigNumber(10).ln()});
-	    object.lazy(math, 'LOG2E',   function () {return new BigNumber(1).div(new BigNumber(2).ln());});
-	    object.lazy(math, 'LOG10E',  function () {return new BigNumber(1).div(new BigNumber(10).ln())});
-	    object.lazy(math, 'PI',      function () {return math.pi});
-	    object.lazy(math, 'SQRT1_2', function () {return new BigNumber('0.5').sqrt()});
-	    object.lazy(math, 'SQRT2',   function () {return new BigNumber(2).sqrt()});
-	  }
-	  else {
-	    math['Infinity'] = Infinity;
-	    math['NaN']      = NaN;
-
-	    math.pi  = Math.PI;
-	    math.tau = Math.PI * 2;
-	    math.e   = Math.E;
-	    math.phi = 1.61803398874989484820458683436563811772030917980576286213545; // golden ratio, (1+sqrt(5))/2
-
-	    // uppercase constants (for compatibility with built-in Math)
-	    math.E           = math.e;
-	    math.LN2         = Math.LN2;
-	    math.LN10        = Math.LN10;
-	    math.LOG2E       = Math.LOG2E;
-	    math.LOG10E      = Math.LOG10E;
-	    math.PI          = math.pi;
-	    math.SQRT1_2     = Math.SQRT1_2;
-	    math.SQRT2       = Math.SQRT2;
-	  }
-
-	  // complex i
-	  math.i = new Complex(0, 1);
-
-	  // meta information
-	  math.version = __webpack_require__(170);
-	};
-
-
-/***/ },
-/* 5 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var BigNumber = __webpack_require__(340);
-
-	// FIXME: replace all require('decimal.js') with require('./BigNumber').
-
-	module.exports = BigNumber;
-
-
-/***/ },
-/* 6 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	exports.ArgumentsError = __webpack_require__(171);
-	exports.DimensionError = __webpack_require__(172);
-	exports.IndexError = __webpack_require__(173);
-	exports.UnsupportedTypeError = __webpack_require__(174);
-
-	// TODO: implement an InvalidValueError?
-
-
-/***/ },
-/* 7 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var util = __webpack_require__(175),
-	    Unit = __webpack_require__(11),
-	    number = util.number,
-
-	    isNumber = util.number.isNumber,
-	    isUnit = Unit.isUnit,
-	    isString = util.string.isString;
-
-	/**
-	 * @constructor Complex
-	 *
-	 * A complex value can be constructed in the following ways:
-	 *     var a = new Complex();
-	 *     var b = new Complex(re, im);
-	 *     var c = Complex.parse(str);
-	 *
-	 * Example usage:
-	 *     var a = new Complex(3, -4);      // 3 - 4i
-	 *     a.re = 5;                        // a = 5 - 4i
-	 *     var i = a.im;                    // -4;
-	 *     var b = Complex.parse('2 + 6i'); // 2 + 6i
-	 *     var c = new Complex();           // 0 + 0i
-	 *     var d = math.add(a, b);          // 5 + 2i
-	 *
-	 * @param {Number} re       The real part of the complex value
-	 * @param {Number} [im]     The imaginary part of the complex value
-	 */
-	function Complex(re, im) {
-	  if (!(this instanceof Complex)) {
-	    throw new SyntaxError('Constructor must be called with the new operator');
-	  }
-
-	  switch (arguments.length) {
-	    case 0:
-	      this.re = 0;
-	      this.im = 0;
-	      break;
-
-	    case 1:
-	      var arg = arguments[0];
-	      if (typeof arg === 'object') {
-	        if('re' in arg && 'im' in arg) {
-	          var construct = new Complex(arg.re, arg.im); // pass on input validation
-	          this.re = construct.re;
-	          this.im = construct.im;
-	          break;
-	        } else if ('r' in arg && 'phi' in arg) {
-	          var construct = Complex.fromPolar(arg.r, arg.phi);
-	          this.re = construct.re;
-	          this.im = construct.im;
-	          break;
-	        }
-	      }
-	      throw new SyntaxError('Object with the re and im or r and phi properties expected.');
-
-	    case 2:
-	      if (!isNumber(re) || !isNumber(im)) {
-	        throw new TypeError('Two numbers expected in Complex constructor');
-	      }
-	      this.re = re;
-	      this.im = im;
-	      break;
-
-	    default:
-	      throw new SyntaxError('One, two or three arguments expected in Complex constructor');
-	  }
-	}
-
-	/**
-	 * Test whether value is a Complex value
-	 * @param {*} value
-	 * @return {Boolean} isComplex
-	 */
-	Complex.isComplex = function (value) {
-	  return (value instanceof Complex);
-	};
-
-	// private variables and functions for the parser
-	var text, index, c;
-
-	function skipWhitespace() {
-	  while (c == ' ' || c == '\t') {
-	    next();
-	  }
-	}
-
-	function isDigitDot (c) {
-	  return ((c >= '0' && c <= '9') || c == '.');
-	}
-
-	function isDigit (c) {
-	  return ((c >= '0' && c <= '9'));
-	}
-
-	function next() {
-	  index++;
-	  c = text.charAt(index);
-	}
-
-	function revert(oldIndex) {
-	  index = oldIndex;
-	  c = text.charAt(index);
-	}
-
-	function parseNumber () {
-	  var number = '';
-	  var oldIndex;
-	  oldIndex = index;
-
-	  if (c == '+') {
-	    next();
-	  }
-	  else if (c == '-') {
-	    number += c;
-	    next();
-	  }
-
-	  if (!isDigitDot(c)) {
-	    // a + or - must be followed by a digit
-	    revert(oldIndex);
-	    return null;
-	  }
-
-	  // get number, can have a single dot
-	  if (c == '.') {
-	    number += c;
-	    next();
-	    if (!isDigit(c)) {
-	      // this is no legal number, it is just a dot
-	      revert(oldIndex);
-	      return null;
-	    }
-	  }
-	  else {
-	    while (isDigit(c)) {
-	      number += c;
-	      next();
-	    }
-	    if (c == '.') {
-	      number += c;
-	      next();
-	    }
-	  }
-	  while (isDigit(c)) {
-	    number += c;
-	    next();
-	  }
-
-	  // check for exponential notation like "2.3e-4" or "1.23e50"
-	  if (c == 'E' || c == 'e') {
-	    number += c;
-	    next();
-
-	    if (c == '+' || c == '-') {
-	      number += c;
-	      next();
-	    }
-
-	    // Scientific notation MUST be followed by an exponent
-	    if (!isDigit(c)) {
-	      // this is no legal number, exponent is missing.
-	      revert(oldIndex);
-	      return null;
-	    }
-
-	    while (isDigit(c)) {
-	      number += c;
-	      next();
-	    }
-	  }
-
-	  return number;
-	}
-
-	function parseComplex () {
-	  // check for 'i', '-i', '+i'
-	  var cnext = text.charAt(index + 1);
-	  if (c == 'I' || c == 'i') {
-	    next();
-	    return '1';
-	  }
-	  else if ((c == '+' || c == '-') && (cnext == 'I' || cnext == 'i')) {
-	    var number = (c == '+') ? '1' : '-1';
-	    next();
-	    next();
-	    return number;
-	  }
-
-	  return null;
-	}
-
-	/**
-	 * Parse a complex number from a string. For example Complex.parse("2 + 3i")
-	 * will return a Complex value where re = 2, im = 3.
-	 * Returns null if provided string does not contain a valid complex number.
-	 * @param {String} str
-	 * @returns {Complex | null} complex
-	 */
-	Complex.parse = function (str) {
-	  text = str;
-	  index = -1;
-	  c = '';
-
-	  if (!isString(text)) {
-	    return null;
-	  }
-
-	  next();
-	  skipWhitespace();
-	  var first = parseNumber();
-	  if (first) {
-	    if (c == 'I' || c == 'i') {
-	      // pure imaginary number
-	      next();
-	      skipWhitespace();
-	      if (c) {
-	        // garbage at the end. not good.
-	        return null;
-	      }
-
-	      return new Complex(0, Number(first));
-	    }
-	    else {
-	      // complex and real part
-	      skipWhitespace();
-	      var separator = c;
-	      if (separator != '+' && separator != '-') {
-	        // pure real number
-	        skipWhitespace();
-	        if (c) {
-	          // garbage at the end. not good.
-	          return null;
-	        }
-
-	        return new Complex(Number(first), 0);
-	      }
-	      else {
-	        // complex and real part
-	        next();
-	        skipWhitespace();
-	        var second = parseNumber();
-	        if (second) {
-	          if (c != 'I' && c != 'i') {
-	            // 'i' missing at the end of the complex number
-	            return null;
-	          }
-	          next();
-	        }
-	        else {
-	          second = parseComplex();
-	          if (!second) {
-	            // imaginary number missing after separator
-	            return null;
-	          }
-	        }
-
-	        if (separator == '-') {
-	          if (second[0] == '-') {
-	            second =  '+' + second.substring(1);
-	          }
-	          else {
-	            second = '-' + second;
-	          }
-	        }
-
-	        next();
-	        skipWhitespace();
-	        if (c) {
-	          // garbage at the end. not good.
-	          return null;
-	        }
-
-	        return new Complex(Number(first), Number(second));
-	      }
-	    }
-	  }
-	  else {
-	    // check for 'i', '-i', '+i'
-	    first = parseComplex();
-	    if (first) {
-	      skipWhitespace();
-	      if (c) {
-	        // garbage at the end. not good.
-	        return null;
-	      }
-
-	      return new Complex(0, Number(first));
-	    }
-	  }
-
-	  return null;
-	};
-
-	/**
-	 * Create a complex number from polar coordinates
-	 *
-	 * Usage:
-	 *
-	 *     Complex.fromPolar(r: Number, phi: Number) : Complex
-	 *     Complex.fromPolar({r: Number, phi: Number}) : Complex
-	 *
-	 * @param {*} args...
-	 * @return {Complex}
-	 */
-	Complex.fromPolar = function (args) {
-	  switch (arguments.length) {
-	    case 1:
-	      var arg = arguments[0];
-	      if(typeof arg === 'object') {
-	        return Complex.fromPolar(arg.r, arg.phi);
-	      }
-	      throw new TypeError('Input has to be an object with r and phi keys.');
-
-	    case 2:
-	      var r = arguments[0],
-	        phi = arguments[1];
-	      if(isNumber(r)) {
-	        if (isUnit(phi) && phi.hasBase(Unit.BASE_UNITS.ANGLE)) {
-	          // convert unit to a number in radians
-	          phi = phi.toNumber('rad');
-	        }
-
-	        if(isNumber(phi)) {
-	          return new Complex(r * Math.cos(phi), r * Math.sin(phi));
-	        }
-
-	        throw new TypeError('Phi is not a number nor an angle unit.');
-	      } else {
-	        throw new TypeError('Radius r is not a number.');
-	      }
-
-	    default:
-	      throw new SyntaxError('Wrong number of arguments in function fromPolar');
-	  }
-	};
-
-	/*
-	 * Return the value of the complex number in polar notation
-	 * The angle phi will be set in the interval of [-pi, pi].
-	 * @return {{r: number, phi: number}} Returns and object with properties r and phi.
-	 */
-	Complex.prototype.toPolar = function() {
-	  return {
-	    r: Math.sqrt(this.re * this.re + this.im * this.im),
-	    phi: Math.atan2(this.im, this.re)
-	  };
-	};
-
-	/**
-	 * Create a copy of the complex value
-	 * @return {Complex} clone
-	 */
-	Complex.prototype.clone = function () {
-	  return new Complex(this.re, this.im);
-	};
-
-	/**
-	 * Test whether this complex number equals an other complex value.
-	 * Two complex numbers are equal when both their real and imaginary parts
-	 * are equal.
-	 * @param {Complex} other
-	 * @return {boolean} isEqual
-	 */
-	Complex.prototype.equals = function (other) {
-	  return (this.re === other.re) && (this.im === other.im);
-	};
-
-	/**
-	 * Get a string representation of the complex number,
-	 * with optional formatting options.
-	 * @param {Object | Number | Function} [options]  Formatting options. See
-	 *                                                lib/util/number:format for a
-	 *                                                description of the available
-	 *                                                options.
-	 * @return {String} str
-	 */
-	Complex.prototype.format = function (options) {
-	  var str = '';
-	  var im = this.im;
-	  var re = this.re;
-	  var strRe = number.format(this.re, options);
-	  var strIm = number.format(this.im, options);
-
-	  // round either re or im when smaller than the configured precision
-	  var precision = isNumber(options) ? options : options ? options.precision : null;
-	  if (precision !== null) {
-	    var epsilon = Math.pow(10, -precision);
-	    if (Math.abs(re / im) < epsilon) {re = 0;}
-	    if (Math.abs(im / re) < epsilon) {im = 0;}
-	  }
-
-	  if (im == 0) {
-	    // real value
-	    str = strRe;
-	  }
-	  else if (re == 0) {
-	    // purely complex value
-	    if (im == 1) {
-	      str = 'i';
-	    }
-	    else if (im == -1) {
-	      str = '-i';
-	    }
-	    else {
-	      str = strIm + 'i';
-	    }
-	  }
-	  else {
-	    // complex value
-	    if (im > 0) {
-	      if (im == 1) {
-	        str = strRe + ' + i';
-	      }
-	      else {
-	        str = strRe + ' + ' + strIm + 'i';
-	      }
-	    }
-	    else {
-	      if (im == -1) {
-	        str = strRe + ' - i';
-	      }
-	      else {
-	        str = strRe + ' - ' + strIm.substring(1) + 'i';
-	      }
-	    }
-	  }
-
-	  return str;
-	};
-
-	/**
-	 * Get a string representation of the complex number.
-	 * @return {String} str
-	 */
-	Complex.prototype.toString = function () {
-	  return this.format();
-	};
-
-	/**
-	 * Get a JSON representation of the complex number
-	 * @returns {Object} Returns a JSON object structured as:
-	 *                   `{"mathjs": "Complex", "re": 2, "im": 3}`
-	 */
-	Complex.prototype.toJSON = function () {
-	  return {
-	    mathjs: 'Complex',
-	    re: this.re,
-	    im: this.im
-	  };
-	};
-
-	/**
-	 * Create a Complex number from a JSON object
-	 * @param {Object} json  A JSON Object structured as
-	 *                       {"mathjs": "Complex", "re": 2, "im": 3}
-	 *                       All properties are optional, default values
-	 *                       for `re` and `im` are 0.
-	 * @return {Complex} Returns a new Complex number
-	 */
-	Complex.fromJSON = function (json) {
-	  return new Complex(json);
-	};
-
-	/**
-	 * Returns a string representation of the complex number.
-	 * @return {String} str
-	 */
-	Complex.prototype.valueOf = Complex.prototype.toString;
-
-	// exports
-	module.exports = Complex;
-
-
-/***/ },
-/* 8 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var util = __webpack_require__(175);
-
-	var number = util.number;
-	var string = util.string;
-	var array = util.array;
-
-	/**
-	 * @constructor Range
-	 * Create a range. A range has a start, step, and end, and contains functions
-	 * to iterate over the range.
-	 *
-	 * A range can be constructed as:
-	 *     var range = new Range(start, end);
-	 *     var range = new Range(start, end, step);
-	 *
-	 * To get the result of the range:
-	 *     range.forEach(function (x) {
-	 *         console.log(x);
-	 *     });
-	 *     range.map(function (x) {
-	 *         return math.sin(x);
-	 *     });
-	 *     range.toArray();
-	 *
-	 * Example usage:
-	 *     var c = new Range(2, 6);         // 2:1:5
-	 *     c.toArray();                     // [2, 3, 4, 5]
-	 *     var d = new Range(2, -3, -1);    // 2:-1:-2
-	 *     d.toArray();                     // [2, 1, 0, -1, -2]
-	 *
-	 * @param {Number} start  included lower bound
-	 * @param {Number} end    excluded upper bound
-	 * @param {Number} [step] step size, default value is 1
-	 */
-	function Range(start, end, step) {
-	  if (!(this instanceof Range)) {
-	    throw new SyntaxError('Constructor must be called with the new operator');
-	  }
-
-	  if (start != null && !number.isNumber(start)) {
-	    throw new TypeError('Parameter start must be a number');
-	  }
-	  if (end != null && !number.isNumber(end)) {
-	    throw new TypeError('Parameter end must be a number');
-	  }
-	  if (step != null && !number.isNumber(step)) {
-	    throw new TypeError('Parameter step must be a number');
-	  }
-
-	  this.start = (start != null) ? parseFloat(start) : 0;
-	  this.end   = (end != null) ? parseFloat(end) : 0;
-	  this.step  = (step != null) ? parseFloat(step) : 1;
-	}
-
-	/**
-	 * Parse a string into a range,
-	 * The string contains the start, optional step, and end, separated by a colon.
-	 * If the string does not contain a valid range, null is returned.
-	 * For example str='0:2:11'.
-	 * @param {String} str
-	 * @return {Range | null} range
-	 */
-	Range.parse = function (str) {
-	  if (!string.isString(str)) {
-	    return null;
-	  }
-
-	  var args = str.split(':');
-	  var nums = args.map(function (arg) {
-	    return parseFloat(arg);
-	  });
-
-	  var invalid = nums.some(function (num) {
-	    return isNaN(num);
-	  });
-	  if(invalid) {
-	    return null;
-	  }
-
-	  switch (nums.length) {
-	    case 2: return new Range(nums[0], nums[1]);
-	    case 3: return new Range(nums[0], nums[2], nums[1]);
-	    default: return null;
-	  }
-	};
-
-	/**
-	 * Create a clone of the range
-	 * @return {Range} clone
-	 */
-	Range.prototype.clone = function () {
-	  return new Range(this.start, this.end, this.step);
-	};
-
-	/**
-	 * Test whether an object is a Range
-	 * @param {*} object
-	 * @return {Boolean} isRange
-	 */
-	Range.isRange = function (object) {
-	  return (object instanceof Range);
-	};
-
-	/**
-	 * Retrieve the size of the range.
-	 * Returns an array containing one number, the number of elements in the range.
-	 * @returns {Number[]} size
-	 */
-	Range.prototype.size = function () {
-	  var len = 0,
-	      start = this.start,
-	      step = this.step,
-	      end = this.end,
-	      diff = end - start;
-
-	  if (number.sign(step) == number.sign(diff)) {
-	    len = Math.ceil((diff) / step);
-	  }
-	  else if (diff == 0) {
-	    len = 0;
-	  }
-
-	  if (isNaN(len)) {
-	    len = 0;
-	  }
-	  return [len];
-	};
-
-	/**
-	 * Calculate the minimum value in the range
-	 * @return {Number | undefined} min
-	 */
-	Range.prototype.min = function () {
-	  var size = this.size()[0];
-
-	  if (size > 0) {
-	    if (this.step > 0) {
-	      // positive step
-	      return this.start;
-	    }
-	    else {
-	      // negative step
-	      return this.start + (size - 1) * this.step;
-	    }
-	  }
-	  else {
-	    return undefined;
-	  }
-	};
-
-	/**
-	 * Calculate the maximum value in the range
-	 * @return {Number | undefined} max
-	 */
-	Range.prototype.max = function () {
-	  var size = this.size()[0];
-
-	  if (size > 0) {
-	    if (this.step > 0) {
-	      // positive step
-	      return this.start + (size - 1) * this.step;
-	    }
-	    else {
-	      // negative step
-	      return this.start;
-	    }
-	  }
-	  else {
-	    return undefined;
-	  }
-	};
-
-
-	/**
-	 * Execute a callback function for each value in the range.
-	 * @param {function} callback   The callback method is invoked with three
-	 *                              parameters: the value of the element, the index
-	 *                              of the element, and the Matrix being traversed.
-	 */
-	Range.prototype.forEach = function (callback) {
-	  var x = this.start;
-	  var step = this.step;
-	  var end = this.end;
-	  var i = 0;
-
-	  if (step > 0) {
-	    while (x < end) {
-	      callback(x, i, this);
-	      x += step;
-	      i++;
-	    }
-	  }
-	  else if (step < 0) {
-	    while (x > end) {
-	      callback(x, i, this);
-	      x += step;
-	      i++;
-	    }
-	  }
-	};
-
-	/**
-	 * Execute a callback function for each value in the Range, and return the
-	 * results as an array
-	 * @param {function} callback   The callback method is invoked with three
-	 *                              parameters: the value of the element, the index
-	 *                              of the element, and the Matrix being traversed.
-	 * @returns {Array} array
-	 */
-	Range.prototype.map = function (callback) {
-	  var array = [];
-	  this.forEach(function (value, index, obj) {
-	    array[index] = callback(value, index, obj);
-	  });
-	  return array;
-	};
-
-	/**
-	 * Create an Array with a copy of the Ranges data
-	 * @returns {Array} array
-	 */
-	Range.prototype.toArray = function () {
-	  var array = [];
-	  this.forEach(function (value, index) {
-	    array[index] = value;
-	  });
-	  return array;
-	};
-
-	/**
-	 * Get the primitive value of the Range, a one dimensional array
-	 * @returns {Array} array
-	 */
-	Range.prototype.valueOf = function () {
-	  // TODO: implement a caching mechanism for range.valueOf()
-	  return this.toArray();
-	};
-
-	/**
-	 * Get a string representation of the range, with optional formatting options.
-	 * Output is formatted as 'start:step:end', for example '2:6' or '0:0.2:11'
-	 * @param {Object | Number | Function} [options]  Formatting options. See
-	 *                                                lib/util/number:format for a
-	 *                                                description of the available
-	 *                                                options.
-	 * @returns {String} str
-	 */
-	Range.prototype.format = function (options) {
-	  var str = number.format(this.start, options);
-
-	  if (this.step != 1) {
-	    str += ':' + number.format(this.step, options);
-	  }
-	  str += ':' + number.format(this.end, options);
-	  return str;
-	};
-
-	/**
-	 * Get a string representation of the range.
-	 * @returns {String}
-	 */
-	Range.prototype.toString = function () {
-	  return this.format();
-	};
-
-	/**
-	 * Get a JSON representation of the range
-	 * @returns {Object} Returns a JSON object structured as:
-	 *                   `{"mathjs": "Range", "start": 2, "end": 4, "step": 1}`
-	 */
-	Range.prototype.toJSON = function () {
-	  return {
-	    mathjs: 'Range',
-	    start: this.start,
-	    end: this.end,
-	    step: this.step
-	  };
-	};
-
-	/**
-	 * Instantiate a Range from a JSON object
-	 * @param {Object} json A JSON object structured as:
-	 *                      `{"mathjs": "Range", "start": 2, "end": 4, "step": 1}`
-	 * @return {Range}
-	 */
-	Range.fromJSON = function (json) {
-	  return new Range(json.start, json.end, json.step);
-	};
-
-	// exports
-	module.exports = Range;
-
-
-/***/ },
 /* 9 */
-/***/ function(module, exports, __webpack_require__) {
+/***/ function(module, exports) {
 
 	'use strict';
 
-	var util = __webpack_require__(175),
-
-	    Range = __webpack_require__(8),
-
-	    number = util.number,
-
-	    isNumber = number.isNumber,
-	    isInteger = number.isInteger,
-	    isArray = Array.isArray;
-
-	/**
-	 * @Constructor Index
-	 * Create an index. An Index can store ranges having start, step, and end
-	 * for multiple dimensions.
-	 * Matrix.get, Matrix.set, and math.subset accept an Index as input.
-	 *
-	 * Usage:
-	 *     var index = new Index(range1, range2, ...);
-	 *
-	 * Where each range can be any of:
-	 *     An array [start, end]
-	 *     An array [start, end, step]
-	 *     A number
-	 *     An instance of Range
-	 *
-	 * The parameters start, end, and step must be integer numbers.
-	 *
-	 * @param {...*} ranges
-	 */
-	function Index(ranges) {
-	  if (!(this instanceof Index)) {
-	    throw new SyntaxError('Constructor must be called with the new operator');
-	  }
-
-	  this._ranges = [];
-	  this._isScalar = true;
-
-	  for (var i = 0, ii = arguments.length; i < ii; i++) {
-	    var arg = arguments[i];
-
-	    if (arg instanceof Range) {
-	      this._ranges.push(arg);
-	      this._isScalar = false;
-	    }
-	    else if (isArray(arg)) {
-	      this._ranges.push(_createRange(arg));
-	      this._isScalar = false;
-	    }
-	    else if (isNumber(arg)) {
-	      this._ranges.push(_createRange([arg, arg + 1]));
-	    }
-	    // TODO: implement support for wildcard '*'
-	    else {
-	      var primitive = arg.valueOf(); // for example turn a Matrix into an Array
-	      if (isArray(primitive)) {
-	        this._ranges.push(_createRange(primitive));
-	        this._isScalar = false;
-	      }
-	      else {
-	        throw new TypeError('Ranges must be an Array, Number, or Range');
-	      }
-	    }
-	  }
-	}
-
-	/**
-	 * Parse an argument into a range and validate the range
-	 * @param {Array} arg  An array with [start: Number, end: Number] and
-	 *                     optional a third element step:Number
-	 * @return {Range} range
-	 * @private
-	 */
-	function _createRange(arg) {
-	  // TODO: make function _createRange simpler/faster
-
-	  // test whether all arguments are integers
-	  var num = arg.length;
-	  for (var i = 0; i < num; i++) {
-	    if (!isNumber(arg[i]) || !isInteger(arg[i])) {
-	      throw new TypeError('Index parameters must be integer numbers');
-	    }
-	  }
-
-	  switch (arg.length) {
-	    case 2:
-	      return new Range(arg[0], arg[1]); // start, end
-	    case 3:
-	      return new Range(arg[0], arg[1], arg[2]); // start, end, step
-	    default:
-	      // TODO: improve error message
-	      throw new SyntaxError('Wrong number of arguments in Index (2 or 3 expected)');
-	  }
-	}
-
-	/**
-	 * Create a clone of the index
-	 * @return {Index} clone
-	 */
-	Index.prototype.clone = function () {
-	  var index = new Index();
-	  index._ranges = util.object.clone(this._ranges);
-	  index._isScalar = this._isScalar;
-	  return index;
-	};
-
-	/**
-	 * Test whether an object is an Index
-	 * @param {*} object
-	 * @return {Boolean} isIndex
-	 */
-	Index.isIndex = function (object) {
-	  return (object instanceof Index);
-	};
-
-	/**
-	 * Create an index from an array with ranges/numbers
-	 * @param {Array.<Array | Number>} ranges
-	 * @return {Index} index
-	 * @private
-	 */
-	Index.create = function (ranges) {
-	  var index = new Index();
-	  Index.apply(index, ranges);
-	  return index;
-	};
-
-	/**
-	 * Retrieve the size of the index, the number of elements for each dimension.
-	 * @returns {Number[]} size
-	 */
-	Index.prototype.size = function () {
-	  var size = [];
-
-	  for (var i = 0, ii = this._ranges.length; i < ii; i++) {
-	    var range = this._ranges[i];
-
-	    size[i] = range.size()[0];
-	  }
-
-	  return size;
-	};
-
-	/**
-	 * Get the maximum value for each of the indexes ranges.
-	 * @returns {Number[]} max
-	 */
-	Index.prototype.max = function () {
-	  var values = [];
-
-	  for (var i = 0, ii = this._ranges.length; i < ii; i++) {
-	    var range = this._ranges[i];
-	    values[i] = range.max();
-	  }
-
-	  return values;
-	};
-
-	/**
-	 * Get the minimum value for each of the indexes ranges.
-	 * @returns {Number[]} min
-	 */
-	Index.prototype.min = function () {
-	  var values = [];
-
-	  for (var i = 0, ii = this._ranges.length; i < ii; i++) {
-	    var range = this._ranges[i];
-
-	    values[i] = range.min();
-	  }
-
-	  return values;
-	};
-
-	/**
-	 * Loop over each of the ranges of the index
-	 * @param {function} callback   Called for each range with a Range as first
-	 *                              argument, the dimension as second, and the
-	 *                              index object as third.
-	 */
-	Index.prototype.forEach = function (callback) {
-	  for (var i = 0, ii = this._ranges.length; i < ii; i++) {
-	    callback(this._ranges[i], i, this);
-	  }
-	};
-
-	/**
-	 * Retrieve the range for a given dimension number from the index
-	 * @param {Number} dim                  Number of the dimension
-	 * @returns {Range | null} range
-	 */
-	Index.prototype.range = function(dim) {
-	  return this._ranges[dim] || null;
-	};
-
-	/**
-	 * Test whether this index contains only a single value.
-	 *
-	 * This is the case when the index is created with only scalar values as ranges,
-	 * not for ranges resolving into a single value.
-	 * @return {boolean} isScalar
-	 */
-	Index.prototype.isScalar = function () {
-	  return this._isScalar;
-	};
-
-	/**
-	 * Expand the Index into an array.
-	 * For example new Index([0,3], [2,7]) returns [[0,1,2], [2,3,4,5,6]]
-	 * @returns {Array} array
-	 */
-	Index.prototype.toArray = function () {
-	  var array = [];
-	  for (var i = 0, ii = this._ranges.length; i < ii; i++) {
-	    var range = this._ranges[i],
-	        row = [],
-	        x = range.start,
-	        end = range.end,
-	        step = range.step;
-
-	    if (step > 0) {
-	      while (x < end) {
-	        row.push(x);
-	        x += step;
-	      }
-	    }
-	    else if (step < 0) {
-	      while (x > end) {
-	        row.push(x);
-	        x += step;
-	      }
-	    }
-
-	    array.push(row);
-	  }
-
-	  return array;
-	};
-
-	/**
-	 * Get the primitive value of the Index, a two dimensional array.
-	 * Equivalent to Index.toArray().
-	 * @returns {Array} array
-	 */
-	Index.prototype.valueOf = Index.prototype.toArray;
-
-	/**
-	 * Get the string representation of the index, for example '[2:6]' or '[0:2:10, 4:7]'
-	 * @returns {String} str
-	 */
-	Index.prototype.toString = function () {
-	  var strings = [];
-
-	  for (var i = 0, ii = this._ranges.length; i < ii; i++) {
-	    var range = this._ranges[i];
-	    var str = number.format(range.start);
-	    if (range.step != 1) {
-	      str += ':' + number.format(range.step);
-	    }
-	    str += ':' + number.format(range.end);
-	    strings.push(str);
-	  }
-
-	  return '[' + strings.join(', ') + ']';
-	};
-
-	/**
-	 * Get a JSON representation of the Index
-	 * @returns {Object} Returns a JSON object structured as:
-	 *                   `{"mathjs": "Index", "ranges": [{"mathjs": "Range", start: 0, end: 10, step:1}, ...]}`
-	 */
-	Index.prototype.toJSON = function () {
-	  return {
-	    mathjs: 'Index',
-	    ranges: this._ranges
-	  };
-	};
-
-	/**
-	 * Instantiate an Index from a JSON object
-	 * @param {Object} json A JSON object structured as:
-	 *                     `{"mathjs": "Index", "ranges": [{"mathjs": "Range", start: 0, end: 10, step:1}, ...]}`
-	 * @return {Index}
-	 */
-	Index.fromJSON = function (json) {
-	  return Index.create(json.ranges);
-	};
-
-	// exports
-	module.exports = Index;
+	/**
+	 * Format a number using methods toPrecision, toFixed, toExponential.
+	 * @param {number | string} value
+	 * @constructor
+	 */
+	function NumberFormatter (value) {
+	  // parse the input value
+	  var match = String(value).toLowerCase().match(/^0*?(-?)(\d+\.?\d*)(e([+-]?\d+))?$/);
+	  if (!match) {
+	    throw new SyntaxError('Invalid number');
+	  }
+
+	  var sign         = match[1];
+	  var coefficients = match[2];
+	  var exponent     = parseFloat(match[4] || '0');
+
+	  var dot = coefficients.indexOf('.');
+	  exponent += (dot !== -1) ? (dot - 1) : (coefficients.length - 1);
+
+	  this.sign = sign;
+	  this.coefficients = coefficients
+	      .replace('.', '')  // remove the dot (must be removed before removing leading zeros)
+	      .replace(/^0*/, function (zeros) {
+	        // remove leading zeros, add their count to the exponent
+	        exponent -= zeros.length;
+	        return '';
+	      })
+	      .replace(/0*$/, '') // remove trailing zeros
+	      .split('')
+	      .map(function (d) {
+	        return parseInt(d);
+	      });
+
+	  if (this.coefficients.length === 0) {
+	    this.coefficients.push(0);
+	    exponent++;
+	  }
+
+	  this.exponent = exponent;
+	}
+
+	/**
+	 * Format a number with fixed notation.
+	 * @param {number} [precision=0]        Optional number of decimals after the
+	 *                                      decimal point. Zero by default.
+	 */
+	NumberFormatter.prototype.toFixed = function (precision) {
+	  var rounded = this.roundDigits(this.exponent + 1 + (precision || 0));
+	  var c = rounded.coefficients;
+	  var p = rounded.exponent + 1; // exponent may have changed
+
+	  // append zeros if needed
+	  var pp = p + (precision || 0);
+	  if (c.length < pp) {
+	    c = c.concat(zeros(pp - c.length));
+	  }
+
+	  // prepend zeros if needed
+	  if (p < 0) {
+	    c = zeros(-p + 1).concat(c);
+	    p = 1;
+	  }
+
+	  // insert a dot if needed
+	  if (precision) {
+	    c.splice(p, 0, (p === 0) ? '0.' : '.');
+	  }
+
+	  return this.sign + c.join('');
+	};
+
+	/**
+	 * Format a number in exponential notation. Like '1.23e+5', '2.3e+0', '3.500e-3'
+	 * @param {number} [precision]  Number of digits in formatted output.
+	 *                              If not provided, the maximum available digits
+	 *                              is used.
+	 */
+	NumberFormatter.prototype.toExponential = function (precision) {
+	  // round if needed, else create a clone
+	  var rounded = precision ? this.roundDigits(precision) : this.clone();
+	  var c = rounded.coefficients;
+	  var e = rounded.exponent;
+
+	  // append zeros if needed
+	  if (c.length < precision) {
+	    c = c.concat(zeros(precision - c.length));
+	  }
+
+	  // format as `C.CCCe+EEE` or `C.CCCe-EEE`
+	  var first = c.shift();
+	  return this.sign + first + (c.length > 0 ? ('.' + c.join('')) : '') +
+	      'e' + (e >= 0 ? '+' : '') + e;
+	};
+
+	/**
+	 * Format a number with a certain precision
+	 * @param {number} [precision=undefined] Optional number of digits.
+	 * @param {{lower: number | undefined, upper: number | undefined}} [options]
+	 *                                       By default:
+	 *                                         lower = 1e-3 (excl)
+	 *                                         upper = 1e+5 (incl)
+	 * @return {string}
+	 */
+	NumberFormatter.prototype.toPrecision = function(precision, options) {
+	  // determine lower and upper bound for exponential notation.
+	  var lower = (options && options.lower !== undefined) ? options.lower : 1e-3;
+	  var upper = (options && options.upper !== undefined) ? options.upper : 1e+5;
+
+	  var abs = Math.abs(Math.pow(10, this.exponent));
+	  if (abs < lower || abs >= upper) {
+	    // exponential notation
+	    return this.toExponential(precision);
+	  }
+	  else {
+	    var rounded = precision ? this.roundDigits(precision) : this.clone();
+	    var c = rounded.coefficients;
+	    var e = rounded.exponent;
+
+	    // append trailing zeros
+	    if (c.length < precision) {
+	      c = c.concat(zeros(precision - c.length));
+	    }
+
+	    // append trailing zeros
+	    // TODO: simplify the next statement
+	    c = c.concat(zeros(e - c.length + 1 +
+	        (c.length < precision ? precision - c.length : 0)));
+
+	    // prepend zeros
+	    c = zeros(-e).concat(c);
+
+	    var dot = e > 0 ? e : 0;
+	    if (dot < c.length - 1) {
+	      c.splice(dot + 1, 0, '.');
+	    }
+
+	    return this.sign + c.join('');
+	  }
+	};
+
+	/**
+	 * Crete a clone of the NumberFormatter
+	 * @return {NumberFormatter} Returns a clone of the NumberFormatter
+	 */
+	NumberFormatter.prototype.clone = function () {
+	  var clone = new NumberFormatter('0');
+	  clone.sign = this.sign;
+	  clone.coefficients = this.coefficients.slice(0);
+	  clone.exponent = this.exponent;
+	  return clone;
+	};
+
+	/**
+	 * Round the number of digits of a number *
+	 * @param {number} precision  A positive integer
+	 * @return {NumberFormatter}  Returns a new NumberFormatter with the rounded
+	 *                            digits
+	 */
+	NumberFormatter.prototype.roundDigits = function (precision) {
+	  var rounded = this.clone();
+	  var c = rounded.coefficients;
+
+	  // prepend zeros if needed
+	  while (precision <= 0) {
+	    c.unshift(0);
+	    rounded.exponent++;
+	    precision++;
+	  }
+
+	  if (c.length > precision) {
+	    var removed = c.splice(precision);
+
+	    if (removed[0] >= 5) {
+	      var i = precision - 1;
+	      c[i]++;
+	      while (c[i] === 10) {
+	        c.pop();
+	        if (i === 0) {
+	          c.unshift(0);
+	          rounded.exponent++;
+	          i++;
+	        }
+	        i--;
+	        c[i]++;
+	      }
+	    }
+	  }
+
+	  return rounded;
+	};
+
+	/**
+	 * Create an array filled with zeros.
+	 * @param {number} length
+	 * @return {Array}
+	 */
+	function zeros(length) {
+	  var arr = [];
+	  for (var i = 0; i < length; i++) {
+	    arr.push(0);
+	  }
+	  return arr;
+	}
+
+	module.exports = NumberFormatter;
 
 
 /***/ },
@@ -2146,1166 +2561,300 @@
 
 	'use strict';
 
-	var string = __webpack_require__(176),
-
-	    isString = string.isString;
-
-	module.exports = function (config) {
-
+	var lazy = __webpack_require__(5).lazy;
+	var isFactory = __webpack_require__(5).isFactory;
+	var traverse = __webpack_require__(5).traverse;
+	var extend = __webpack_require__(5).extend;
+	var ArgumentsError = __webpack_require__(11);
+
+	function factory (type, config, load, typed, math) {
 	  /**
-	   * @constructor Matrix
-	   *
-	   * A Matrix is a wrapper around an Array. A matrix can hold a multi dimensional
-	   * array. A matrix can be constructed as:
-	   *     var matrix = math.matrix(data)
-	   *
-	   * Matrix contains the functions to resize, get and set values, get the size,
-	   * clone the matrix and to convert the matrix to a vector, array, or scalar.
-	   * Furthermore, one can iterate over the matrix using map and forEach.
-	   * The internal Array of the Matrix can be accessed using the function valueOf.
-	   *
-	   * Example usage:
-	   *     var matrix = math.matrix([[1, 2], [3, 4]]);
-	   *     matix.size();              // [2, 2]
-	   *     matrix.resize([3, 2], 5);
-	   *     matrix.valueOf();          // [[1, 2], [3, 4], [5, 5]]
-	   *     matrix.subset([1,2])       // 3 (indexes are zero-based)
-	   *
+	   * Import functions from an object or a module
+	   *
+	   * Syntax:
+	   *
+	   *    math.import(object)
+	   *    math.import(object, options)
+	   *
+	   * Where:
+	   *
+	   * - `object: Object`
+	   *   An object with functions to be imported.
+	   * - `options: Object` An object with import options. Available options:
+	   *   - `override: boolean`
+	   *     If true, existing functions will be overwritten. False by default.
+	   *   - `silent: boolean`
+	   *     If true, the function will not throw errors on duplicates or invalid
+	   *     types. False by default.
+	   *   - `wrap: boolean`
+	   *     If true, the functions will be wrapped in a wrapper function
+	   *     which converts data types like Matrix to primitive data types like Array.
+	   *     The wrapper is needed when extending math.js with libraries which do not
+	   *     support these data type. False by default.
+	   *
+	   * Examples:
+	   *
+	   *    // define new functions and variables
+	   *    math.import({
+	   *      myvalue: 42,
+	   *      hello: function (name) {
+	   *        return 'hello, ' + name + '!';
+	   *      }
+	   *    });
+	   *
+	   *    // use the imported function and variable
+	   *    math.myvalue * 2;               // 84
+	   *    math.hello('user');             // 'hello, user!'
+	   *
+	   *    // import the npm module 'numbers'
+	   *    // (must be installed first with `npm install numbers`)
+	   *    math.import(require('numbers'), {wrap: true});
+	   *
+	   *    math.fibonacci(7); // returns 13
+	   *
+	   * @param {Object | Array} object   Object with functions to be imported.
+	   * @param {Object} [options]        Import options.
 	   */
-	  function Matrix() {
-	    if (!(this instanceof Matrix)) {
-	      throw new SyntaxError('Constructor must be called with the new operator');
+	  function math_import(object, options) {
+	    var num = arguments.length;
+	    if (num != 1 && num != 2) {
+	      throw new ArgumentsError('import', num, 1, 2);
+	    }
+
+	    if (!options) {
+	      options = {};
+	    }
+
+	    if (isFactory(object)) {
+	      _importFactory(object, options);
+	    }
+	    else if (Array.isArray(object)) {
+	      object.forEach(function (entry) {
+	        math_import(entry, options);
+	      });
+	    }
+	    else if (typeof object === 'object') {
+	      // a map with functions
+	      for (var name in object) {
+	        if (object.hasOwnProperty(name)) {
+	          var value = object[name];
+	          if (isSupportedType(value)) {
+	            _import(name, value, options);
+	          }
+	          else if (isFactory(object)) {
+	            _importFactory(object, options);
+	          }
+	          else {
+	            math_import(value, options);
+	          }
+	        }
+	      }
+	    }
+	    else {
+	      if (!options.silent) {
+	        throw new TypeError('Factory, Object, or Array expected');
+	      }
 	    }
 	  }
 
 	  /**
-	   * Test whether an object is a Matrix
-	   * @param {*} object
-	   * @return {Boolean} isMatrix
-	   */
-	  Matrix.isMatrix = function (object) {
-	    return (object instanceof Matrix);
-	  };
-
-	  /**
-	   * Get the Matrix storage constructor for the given format.
-	   *
-	   * @param {string} format       The Matrix storage format.
-	   *
-	   * @return {Function}           The Matrix storage constructor.
-	   */
-	  Matrix.storage = function (format) {
-	    // check storage format is a string
-	    if (!isString(format)) {
-	      throw new TypeError('format must be a string value');
-	    }
-
-	    // get storage format constructor
-	    var constructor = Matrix._storage[format];
-	    if (!constructor) {
-	      throw new SyntaxError('Unsupported matrix storage format: ' + format);
-	    }
-
-	    // return storage constructor
-	    return constructor;
-	  };
-
-	  // a map with all constructors for all storage types
-	  Matrix._storage = {};
-
-	  /**
-	   * Get the storage format used by the matrix.
-	   *
-	   * Usage:
-	   *     var format = matrix.storage()                   // retrieve storage format
-	   *
-	   * @return {string}           The storage format.
-	   */
-	  Matrix.prototype.storage = function () {
-	    // must be implemented by each of the Matrix implementations
-	    throw new Error('Cannot invoke storage on a Matrix interface');
-	  };
-	  
-	  /**
-	   * Get a subset of the matrix, or replace a subset of the matrix.
-	   *
-	   * Usage:
-	   *     var subset = matrix.subset(index)               // retrieve subset
-	   *     var value = matrix.subset(index, replacement)   // replace subset
-	   *
-	   * @param {Index} index
-	   * @param {Array | Matrix | *} [replacement]
-	   * @param {*} [defaultValue=0]      Default value, filled in on new entries when
-	   *                                  the matrix is resized. If not provided,
-	   *                                  new matrix elements will be filled with zeros.
-	   */
-	  Matrix.prototype.subset = function (index, replacement, defaultValue) {
-	    // must be implemented by each of the Matrix implementations
-	    throw new Error('Cannot invoke subset on a Matrix interface');
-	  };
-
-	  /**
-	   * Get a single element from the matrix.
-	   * @param {Number[]} index   Zero-based index
-	   * @return {*} value
-	   */
-	  Matrix.prototype.get = function (index) {
-	    // must be implemented by each of the Matrix implementations
-	    throw new Error('Cannot invoke get on a Matrix interface');
-	  };
-
-	  /**
-	   * Replace a single element in the matrix.
-	   * @param {Number[]} index   Zero-based index
+	   * Add a property to the math namespace and create a chain proxy for it.
+	   * @param {string} name
 	   * @param {*} value
-	   * @param {*} [defaultValue]        Default value, filled in on new entries when
-	   *                                  the matrix is resized. If not provided,
-	   *                                  new matrix elements will be left undefined.
-	   * @return {Matrix} self
-	   */
-	  Matrix.prototype.set = function (index, value, defaultValue) {
-	    // must be implemented by each of the Matrix implementations
-	    throw new Error('Cannot invoke set on a Matrix interface');
-	  };
-
-	  /**
-	   * Resize the matrix to the given size. Returns a copy of the matrix when 
-	   * `copy=true`, otherwise return the matrix itself (resize in place).
-	   *
-	   * @param {Number[]} size           The new size the matrix should have.
-	   * @param {*} [defaultValue=0]      Default value, filled in on new entries.
-	   *                                  If not provided, the matrix elements will
-	   *                                  be filled with zeros.
-	   * @param {boolean} [copy]          Return a resized copy of the matrix
-	   *
-	   * @return {Matrix}                 The resized matrix
-	   */
-	  Matrix.prototype.resize = function (size, defaultValue) {
-	    // must be implemented by each of the Matrix implementations
-	    throw new Error('Cannot invoke resize on a Matrix interface');
-	  };
-
-	  /**
-	   * Create a clone of the matrix
-	   * @return {Matrix} clone
-	   */
-	  Matrix.prototype.clone = function () {
-	    // must be implemented by each of the Matrix implementations
-	    throw new Error('Cannot invoke clone on a Matrix interface');
-	  };
-
-	  /**
-	   * Retrieve the size of the matrix.
-	   * @returns {Number[]} size
-	   */
-	  Matrix.prototype.size = function() {
-	    // must be implemented by each of the Matrix implementations
-	    throw new Error('Cannot invoke size on a Matrix interface');
-	  };
-
-	  /**
-	   * Create a new matrix with the results of the callback function executed on
-	   * each entry of the matrix.
-	   * @param {function} callback   The callback function is invoked with three
-	   *                              parameters: the value of the element, the index
-	   *                              of the element, and the Matrix being traversed.
-	   * @param {boolean} [skipZeros] Invoke callback function for non-zero values only.
-	   *
-	   * @return {Matrix} matrix
-	   */
-	  Matrix.prototype.map = function (callback, skipZeros) {
-	    // must be implemented by each of the Matrix implementations
-	    throw new Error('Cannot invoke map on a Matrix interface');
-	  };
-
-	  /**
-	   * Execute a callback function on each entry of the matrix.
-	   * @param {function} callback   The callback function is invoked with three
-	   *                              parameters: the value of the element, the index
-	   *                              of the element, and the Matrix being traversed.
-	   */
-	  Matrix.prototype.forEach = function (callback) {
-	    // must be implemented by each of the Matrix implementations
-	    throw new Error('Cannot invoke forEach on a Matrix interface');
-	  };
-
-	  /**
-	   * Create an Array with a copy of the data of the Matrix
-	   * @returns {Array} array
-	   */
-	  Matrix.prototype.toArray = function () {
-	    // must be implemented by each of the Matrix implementations
-	    throw new Error('Cannot invoke toArray on a Matrix interface');
-	  };
-
-	  /**
-	   * Get the primitive value of the Matrix: a multidimensional array
-	   * @returns {Array} array
-	   */
-	  Matrix.prototype.valueOf = function () {
-	    // must be implemented by each of the Matrix implementations
-	    throw new Error('Cannot invoke valueOf on a Matrix interface');
-	  };
-
-	  /**
-	   * Get a string representation of the matrix, with optional formatting options.
-	   * @param {Object | Number | Function} [options]  Formatting options. See
-	   *                                                lib/util/number:format for a
-	   *                                                description of the available
-	   *                                                options.
-	   * @returns {String} str
-	   */
-	  Matrix.prototype.format = function (options) {
-	    // must be implemented by each of the Matrix implementations
-	    throw new Error('Cannot invoke format on a Matrix interface');
-	  };
-
-	  /**
-	   * Get a string representation of the matrix
-	   * @returns {String} str
-	   */
-	  Matrix.prototype.toString = function () {
-	    // must be implemented by each of the Matrix implementations
-	    throw new Error('Cannot invoke toString on a Matrix interface');
-	  };
-
-	  /**
-	   * Calculates the transpose of the matrix
-	   * @returns {Matrix}
-	   */
-	  Matrix.prototype.transpose = function () {
-	    // must be implemented by each of the Matrix implementations
-	    throw new Error('Cannot invoke transpose on a Matrix interface');
-	  };
-
-	  /**
-	   * Calculate the trace of a matrix: the sum of the elements on the main
-	   * diagonal of a square matrix.
-	   *
-	   * See also:
-	   *
-	   *    diagonal
-	   *
-	   * @returns {Number}       The matrix trace
-	   */
-	  Matrix.prototype.trace = function () {
-	    // must be implemented by each of the Matrix implementations
-	    throw new Error('Cannot invoke transpose on a Matrix interface');
-	  };
-
-	  /**
-	   * Multiply the matrix values times the argument.
-	   *
-	   * @param  {Number | BigNumber | Boolean | Complex | Unit | Array | Matrix | null} Value to multiply.
-	   *
-	   * @return {Number | BigNumber | Complex | Unit | Matrix}
-	   */
-	  Matrix.prototype.multiply = function (value) {
-	    // must be implemented by each of the Matrix implementations
-	    throw new Error('Cannot invoke multiply on a Matrix interface');
-	  };
-	  
-	  // exports
-	  return Matrix;
-	};
+	   * @param {Object} options  See import for a description of the options
+	   * @private
+	   */
+	  function _import(name, value, options) {
+	    if (options.wrap && typeof value === 'function') {
+	      // create a wrapper around the function
+	      value = _wrap(value);
+	    }
+
+	    if (isTypedFunction(math[name]) && isTypedFunction(value)) {
+	      // merge two typed functions
+	      if (options.override) {
+	        value = typed(extend({}, math[name].signatures, value.signatures));
+	      }
+	      else {
+	        value = typed(math[name], value);
+	      }
+
+	      math[name] = value;
+	      _importTransform(name, value);
+	      math.emit('import', name, function resolver() {
+	        return value;
+	      });
+	      return;
+	    }
+
+	    if (math[name] === undefined || options.override) {
+	      math[name] = value;
+	      _importTransform(name, value);
+	      math.emit('import', name, function resolver() {
+	        return value;
+	      });
+	      return;
+	    }
+
+	    if (!options.silent) {
+	      throw new Error('Cannot import "' + name + '": already exists');
+	    }
+	  }
+
+	  function _importTransform (name, value) {
+	    if (value && typeof value.transform === 'function') {
+	      math.expression.transform[name] = value.transform;
+	    }
+	  }
+
+	  /**
+	   * Create a wrapper a round an function which converts the arguments
+	   * to their primitive values (like convert a Matrix to Array)
+	   * @param {Function} fn
+	   * @return {Function} Returns the wrapped function
+	   * @private
+	   */
+	  function _wrap (fn) {
+	    var wrapper = function wrapper () {
+	      var args = [];
+	      for (var i = 0, len = arguments.length; i < len; i++) {
+	        var arg = arguments[i];
+	        args[i] = arg && arg.valueOf();
+	      }
+	      return fn.apply(math, args);
+	    };
+
+	    if (fn.transform) {
+	      wrapper.transform = fn.transform;
+	    }
+
+	    return wrapper;
+	  }
+
+	  /**
+	   * Import an instance of a factory into math.js
+	   * @param {{factory: Function, name: string, path: string, math: boolean}} factory
+	   * @param {Object} options  See import for a description of the options
+	   * @private
+	   */
+	  function _importFactory(factory, options) {
+	    if (typeof factory.name === 'string') {
+	      var name = factory.name;
+	      var namespace = factory.path ? traverse(math, factory.path) : math;
+	      var existing = namespace.hasOwnProperty(name) ? namespace[name] : undefined;
+
+	      var resolver = function () {
+	        var instance = load(factory);
+
+	        if (isTypedFunction(existing) && isTypedFunction(instance)) {
+	          // merge two typed functions
+	          if (options.override) {
+	            instance = typed(extend({}, existing.signatures, instance.signatures));
+	          }
+	          else {
+	            instance = typed(existing, instance);
+	          }
+
+	          return instance;
+	        }
+
+	        if (existing === undefined || options.override) {
+	          return instance;
+	        }
+
+	        if (!options.silent) {
+	          throw new Error('Cannot import "' + name + '": already exists');
+	        }
+	      };
+
+	      if (factory.lazy !== false) {
+	        lazy(namespace, name, resolver);
+	      }
+	      else {
+	        namespace[name] = resolver();
+	      }
+
+	      math.emit('import', name, resolver, factory.path);
+	    }
+	    else {
+	      // unnamed factory.
+	      // no lazy loading
+	      load(factory);
+	    }
+	  }
+
+	  /**
+	   * Check whether given object is a type which can be imported
+	   * @param {Function | number | string | boolean | null | Unit | Complex} object
+	   * @return {boolean}
+	   * @private
+	   */
+	  function isSupportedType(object) {
+	    return typeof object == 'function'
+	        || typeof object === 'number'
+	        || typeof object === 'string'
+	        || typeof object === 'boolean'
+	        || object === null
+	        || (object && object.isUnit === true)
+	        || (object && object.isComplex === true)
+	  }
+
+	  /**
+	   * Test whether a given thing is a typed-function
+	   * @param {*} fn
+	   * @return {boolean} Returns true when `fn` is a typed-function
+	   */
+	  function isTypedFunction (fn) {
+	    return typeof fn === 'function' && typeof fn.signatures === 'object';
+	  }
+
+	  return math_import;
+	}
+
+	exports.math = true; // request access to the math namespace as 5th argument of the factory function
+	exports.name = 'import';
+	exports.factory = factory;
+	exports.lazy = true;
+
 
 /***/ },
 /* 11 */
-/***/ function(module, exports, __webpack_require__) {
+/***/ function(module, exports) {
 
 	'use strict';
 
-	var util = __webpack_require__(175),
-
-	    number = util.number,
-	    string = util.string,
-	    isNumber = util.number.isNumber,
-	    isString = util.string.isString;
-
-	/**
-	 * @constructor Unit
-	 *
-	 * A unit can be constructed in the following ways:
-	 *     var a = new Unit(value, name);
-	 *     var b = new Unit(null, name);
-	 *     var c = Unit.parse(str);
-	 *
-	 * Example usage:
-	 *     var a = new Unit(5, 'cm');               // 50 mm
-	 *     var b = Unit.parse('23 kg');             // 23 kg
-	 *     var c = math.in(a, new Unit(null, 'm');  // 0.05 m
-	 *
-	 * @param {Number} [value]  A value like 5.2
-	 * @param {String} [name]   A unit name like "cm" or "inch". Can include a prefix
-	 */
-	function Unit(value, name) {
-	  if (!(this instanceof Unit)) {
-	    throw new Error('Constructor must be called with the new operator');
-	  }
-
-	  if (value != undefined && !isNumber(value)) {
-	    throw new TypeError('First parameter in Unit constructor must be a number');
-	  }
-	  if (name != undefined && (!isString(name) || name == '')) {
-	    throw new TypeError('Second parameter in Unit constructor must be a string');
-	  }
-
-	  if (name != undefined) {
-	    // find the unit and prefix from the string
-	    var res = _findUnit(name);
-	    if (!res) {
-	      throw new SyntaxError('Unknown unit "' + name + '"');
-	    }
-	    this.unit = res.unit;
-	    this.prefix = res.prefix;
-	  }
-	  else {
-	    this.unit = UNIT_NONE;
-	    this.prefix = PREFIX_NONE;  // link to a list with supported prefixes
-	  }
-
-	  this.value = (value != undefined) ? this._normalize(value) : null;
-	  this.fixPrefix = false; // if true, function format will not search for the
-	                          // best prefix but leave it as initially provided.
-	                          // fixPrefix is set true by the method Unit.to
-	}
-
-	// private variables and functions for the Unit parser
-	var text, index, c;
-
-	function skipWhitespace() {
-	  while (c == ' ' || c == '\t') {
-	    next();
-	  }
-	}
-
-	function isDigitDot (c) {
-	  return ((c >= '0' && c <= '9') || c == '.');
-	}
-
-	function isDigit (c) {
-	  return ((c >= '0' && c <= '9'));
-	}
-
-	function next() {
-	  index++;
-	  c = text.charAt(index);
-	}
-
-	function revert(oldIndex) {
-	  index = oldIndex;
-	  c = text.charAt(index);
-	}
-
-	function parseNumber () {
-	  var number = '';
-	  var oldIndex;
-	  oldIndex = index;
-
-	  if (c == '+') {
-	    next();
-	  }
-	  else if (c == '-') {
-	    number += c;
-	    next();
-	  }
-
-	  if (!isDigitDot(c)) {
-	    // a + or - must be followed by a digit
-	    revert(oldIndex);
-	    return null;
-	  }
-
-	  // get number, can have a single dot
-	  if (c == '.') {
-	    number += c;
-	    next();
-	    if (!isDigit(c)) {
-	      // this is no legal number, it is just a dot
-	      revert(oldIndex);
-	      return null;
-	    }
-	  }
-	  else {
-	    while (isDigit(c)) {
-	      number += c;
-	      next();
-	    }
-	    if (c == '.') {
-	      number += c;
-	      next();
-	    }
-	  }
-	  while (isDigit(c)) {
-	    number += c;
-	    next();
-	  }
-
-	  // check for exponential notation like "2.3e-4" or "1.23e50"
-	  if (c == 'E' || c == 'e') {
-	    number += c;
-	    next();
-
-	    if (c == '+' || c == '-') {
-	      number += c;
-	      next();
-	    }
-
-	    // Scientific notation MUST be followed by an exponent
-	    if (!isDigit(c)) {
-	      // this is no legal number, exponent is missing.
-	      revert(oldIndex);
-	      return null;
-	    }
-
-	    while (isDigit(c)) {
-	      number += c;
-	      next();
-	    }
-	  }
-
-	  return number;
-	}
-
-	function parseUnit() {
-	  var unitName = '';
-
-	  skipWhitespace();
-	  while (c && c != ' ' && c != '\t') {
-	    unitName += c;
-	    next();
-	  }
-
-	  return unitName || null;
-	}
-
-	/**
-	 * Parse a string into a unit. Returns null if the provided string does not
-	 * contain a valid unit.
-	 * @param {String} str        A string like "5.2 inch", "4e2 kg"
-	 * @return {Unit | null} unit
-	 */
-	Unit.parse = function(str) {
-	  text = str;
-	  index = -1;
-	  c = '';
-
-	  if (!isString(text)) {
-	    return null;
-	  }
-
-	  next();
-	  skipWhitespace();
-	  var value = parseNumber();
-	  var name;
-	  if (value) {
-	    name = parseUnit();
-
-	    next();
-	    skipWhitespace();
-	    if (c) {
-	      // garbage at the end. not good.
-	      return null;
-	    }
-
-	    if (value && name) {
-	      try {
-	        // constructor will throw an error when unit is not found
-	        return new Unit(Number(value), name);
-	      }
-	      catch (err) {}
-	    }
-	  }
-	  else {
-	    name = parseUnit();
-
-	    next();
-	    skipWhitespace();
-	    if (c) {
-	      // garbage at the end. not good.
-	      return null;
-	    }
-
-	    if (name) {
-	      try {
-	        // constructor will throw an error when unit is not found
-	        return new Unit(null, name);
-	      }
-	      catch (err) {}
-	    }
-	  }
-
-	  return null;
-	};
-
-	/**
-	 * Test whether value is of type Unit
-	 * @param {*} value
-	 * @return {Boolean} isUnit
-	 */
-	Unit.isUnit = function(value) {
-	  return (value instanceof Unit);
-	};
-
-	/**
-	 * create a copy of this unit
-	 * @return {Unit} clone
-	 */
-	Unit.prototype.clone = function () {
-	  var clone = new Unit();
-
-	  for (var p in this) {
-	    if (this.hasOwnProperty(p)) {
-	      clone[p] = this[p];
-	    }
-	  }
-
-	  return clone;
-	};
-
-	/**
-	 * Normalize a value, based on its currently set unit
-	 * @param {Number} value
-	 * @return {Number} normalized value
-	 * @private
-	 */
-	Unit.prototype._normalize = function(value) {
-	  return (value + this.unit.offset) * this.unit.value * this.prefix.value;
-	};
-
-	/**
-	 * Denormalize a value, based on its currently set unit
-	 * @param {Number} value
-	 * @param {Number} [prefixValue]    Optional prefix value to be used
-	 * @return {Number} denormalized value
-	 * @private
-	 */
-	Unit.prototype._denormalize = function (value, prefixValue) {
-	  if (prefixValue == undefined) {
-	    return value / this.unit.value / this.prefix.value - this.unit.offset;
-	  }
-	  else {
-	    return value / this.unit.value / prefixValue - this.unit.offset;
-	  }
-	};
-
-	/**
-	 * Find a unit from a string
-	 * @param {String} str              A string like 'cm' or 'inch'
-	 * @returns {Object | null} result  When found, an object with fields unit and
-	 *                                  prefix is returned. Else, null is returned.
-	 * @private
-	 */
-	function _findUnit(str) {
-	  for (var name in UNITS) {
-	    if (UNITS.hasOwnProperty(name)) {
-	      if (string.endsWith(str, name) ) {
-	        var unit = UNITS[name];
-	        var prefixLen = (str.length - name.length);
-	        var prefixName = str.substring(0, prefixLen);
-	        var prefix = unit.prefixes[prefixName];
-	        if (prefix !== undefined) {
-	          // store unit, prefix, and value
-	          return {
-	            unit: unit,
-	            prefix: prefix
-	          };
-	        }
-	      }
-	    }
-	  }
-
-	  return null;
-	}
-
-	/**
-	 * Test if the given expression is a unit.
-	 * The unit can have a prefix but cannot have a value.
-	 * @param {String} name   A string to be tested whether it is a value less unit.
-	 *                        The unit can have prefix, like "cm"
-	 * @return {Boolean}      true if the given string is a unit
-	 */
-	Unit.isValuelessUnit = function (name) {
-	  return (_findUnit(name) != null);
-	};
-
-	/**
-	 * check if this unit has given base unit
-	 * @param {BASE_UNITS | undefined} base
-	 */
-	Unit.prototype.hasBase = function(base) {
-	  return (this.unit.base === base);
-	};
-
-	/**
-	 * Check if this unit has a base equal to another base
-	 * @param {Unit} other
-	 * @return {Boolean} true if equal base
-	 */
-	Unit.prototype.equalBase = function(other) {
-	  return (this.unit.base === other.unit.base);
-	};
-
-	/**
-	 * Check if this unit equals another unit
-	 * @param {Unit} other
-	 * @return {Boolean} true if both units are equal
-	 */
-	Unit.prototype.equals = function(other) {
-	  return (this.equalBase(other) && this.value == other.value);
-	};
-
-	/**
-	 * Create a clone of this unit with a representation
-	 * @param {String | Unit} valuelessUnit   A unit without value. Can have prefix, like "cm"
-	 * @returns {Unit} unit having fixed, specified unit
-	 */
-	Unit.prototype.to = function (valuelessUnit) {
-	  var other;
-	  var value = this.value == null ? this._normalize(1) : this.value;
-	  if (isString(valuelessUnit)) {
-	    other = new Unit(null, valuelessUnit);
-
-	    if (!this.equalBase(other)) {
-	      throw new Error('Units do not match');
-	    }
-
-	    other.value = value;
-	    other.fixPrefix = true;
-	    return other;
-	  }
-	  else if (valuelessUnit instanceof Unit) {
-	    if (!this.equalBase(valuelessUnit)) {
-	      throw new Error('Units do not match');
-	    }
-	    if (valuelessUnit.value !== null) {
-	      throw new Error('Cannot convert to a unit with a value');
-	    }
-
-	    other = valuelessUnit.clone();
-	    other.value = value;
-	    other.fixPrefix = true;
-	    return other;
-	  }
-	  else {
-	    throw new Error('String or Unit expected as parameter');
-	  }
-	};
-
-	/**
-	 * Return the value of the unit when represented with given valueless unit
-	 * @param {String | Unit} valuelessUnit    For example 'cm' or 'inch'
-	 * @return {Number} value
-	 */
-	Unit.prototype.toNumber = function (valuelessUnit) {
-	  var other = this.to(valuelessUnit);
-	  return other._denormalize(other.value, other.prefix.value);
-	};
-
-
-	/**
-	 * Get a string representation of the unit.
-	 * @return {String}
-	 */
-	Unit.prototype.toString = function() {
-	  return this.format();
-	};
-
-	/**
-	 * Get a JSON representation of the unit
-	 * @returns {Object} Returns a JSON object structured as:
-	 *                   `{"mathjs": "Unit", "value": 2, "unit": "cm", "fixPrefix": false}`
-	 */
-	Unit.prototype.toJSON = function () {
-	  return {
-	    mathjs: 'Unit',
-	    value: this._denormalize(this.value),
-	    unit: this.prefix.name + this.unit.name,
-	    fixPrefix: this.fixPrefix
-	  };
-	};
-
-	/**
-	 * Instantiate a Unit from a JSON object
-	 * @param {Object} json  A JSON object structured as:
-	 *                       `{"mathjs": "Unit", "value": 2, "unit": "cm", "fixPrefix": false}`
-	 * @return {Unit}
-	 */
-	Unit.fromJSON = function (json) {
-	  var unit = new Unit(json.value, json.unit);
-	  unit.fixPrefix = json.fixPrefix || false;
-	  return unit;
-	};
-
-	/**
-	 * Returns the string representation of the unit.
-	 * @return {String}
-	 */
-	Unit.prototype.valueOf = Unit.prototype.toString;
-
-	/**
-	 * Get a string representation of the Unit, with optional formatting options.
-	 * @param {Object | Number | Function} [options]  Formatting options. See
-	 *                                                lib/util/number:format for a
-	 *                                                description of the available
-	 *                                                options.
-	 * @return {String}
-	 */
-	Unit.prototype.format = function(options) {
-	  var value,
-	      str;
-
-	  if (this.value !== null && !this.fixPrefix) {
-	    var bestPrefix = this._bestPrefix();
-	    value = this._denormalize(this.value, bestPrefix.value);
-	    str = number.format(value, options) + ' ';
-	    str += bestPrefix.name + this.unit.name;
-	  }
-	  else {
-	    value = this._denormalize(this.value);
-	    str = (this.value !== null) ? (number.format(value, options) + ' ') : '';
-	    str += this.prefix.name + this.unit.name;
-	  }
-
-	  return str;
-	};
-
-	/**
-	 * Calculate the best prefix using current value.
-	 * @returns {Object} prefix
-	 * @private
-	 */
-	Unit.prototype._bestPrefix = function () {
-	  // find the best prefix value (resulting in the value of which
-	  // the absolute value of the log10 is closest to zero,
-	  // though with a little offset of 1.2 for nicer values: you get a
-	  // sequence 1mm 100mm 500mm 0.6m 1m 10m 100m 500m 0.6km 1km ...
-	  var absValue = Math.abs(this.value / this.unit.value);
-	  var bestPrefix = PREFIX_NONE;
-	  var bestDiff = Math.abs(
-	      Math.log(absValue / bestPrefix.value) / Math.LN10 - 1.2);
-
-	  var prefixes = this.unit.prefixes;
-	  for (var p in prefixes) {
-	    if (prefixes.hasOwnProperty(p)) {
-	      var prefix = prefixes[p];
-	      if (prefix.scientific) {
-	        var diff = Math.abs(
-	            Math.log(absValue / prefix.value) / Math.LN10 - 1.2);
-
-	        if (diff < bestDiff) {
-	          bestPrefix = prefix;
-	          bestDiff = diff;
-	        }
-	      }
-	    }
-	  }
-
-	  return bestPrefix;
-	};
-
-	var PREFIXES = {
-	  NONE: {
-	    '': {name: '', value: 1, scientific: true}
-	  },
-	  SHORT: {
-	    '': {name: '', value: 1, scientific: true},
-
-	    'da': {name: 'da', value: 1e1, scientific: false},
-	    'h': {name: 'h', value: 1e2, scientific: false},
-	    'k': {name: 'k', value: 1e3, scientific: true},
-	    'M': {name: 'M', value: 1e6, scientific: true},
-	    'G': {name: 'G', value: 1e9, scientific: true},
-	    'T': {name: 'T', value: 1e12, scientific: true},
-	    'P': {name: 'P', value: 1e15, scientific: true},
-	    'E': {name: 'E', value: 1e18, scientific: true},
-	    'Z': {name: 'Z', value: 1e21, scientific: true},
-	    'Y': {name: 'Y', value: 1e24, scientific: true},
-
-	    'd': {name: 'd', value: 1e-1, scientific: false},
-	    'c': {name: 'c', value: 1e-2, scientific: false},
-	    'm': {name: 'm', value: 1e-3, scientific: true},
-	    'u': {name: 'u', value: 1e-6, scientific: true},
-	    'n': {name: 'n', value: 1e-9, scientific: true},
-	    'p': {name: 'p', value: 1e-12, scientific: true},
-	    'f': {name: 'f', value: 1e-15, scientific: true},
-	    'a': {name: 'a', value: 1e-18, scientific: true},
-	    'z': {name: 'z', value: 1e-21, scientific: true},
-	    'y': {name: 'y', value: 1e-24, scientific: true}
-	  },
-	  LONG: {
-	    '': {name: '', value: 1, scientific: true},
-
-	    'deca': {name: 'deca', value: 1e1, scientific: false},
-	    'hecto': {name: 'hecto', value: 1e2, scientific: false},
-	    'kilo': {name: 'kilo', value: 1e3, scientific: true},
-	    'mega': {name: 'mega', value: 1e6, scientific: true},
-	    'giga': {name: 'giga', value: 1e9, scientific: true},
-	    'tera': {name: 'tera', value: 1e12, scientific: true},
-	    'peta': {name: 'peta', value: 1e15, scientific: true},
-	    'exa': {name: 'exa', value: 1e18, scientific: true},
-	    'zetta': {name: 'zetta', value: 1e21, scientific: true},
-	    'yotta': {name: 'yotta', value: 1e24, scientific: true},
-
-	    'deci': {name: 'deci', value: 1e-1, scientific: false},
-	    'centi': {name: 'centi', value: 1e-2, scientific: false},
-	    'milli': {name: 'milli', value: 1e-3, scientific: true},
-	    'micro': {name: 'micro', value: 1e-6, scientific: true},
-	    'nano': {name: 'nano', value: 1e-9, scientific: true},
-	    'pico': {name: 'pico', value: 1e-12, scientific: true},
-	    'femto': {name: 'femto', value: 1e-15, scientific: true},
-	    'atto': {name: 'atto', value: 1e-18, scientific: true},
-	    'zepto': {name: 'zepto', value: 1e-21, scientific: true},
-	    'yocto': {name: 'yocto', value: 1e-24, scientific: true}
-	  },
-	  SQUARED: {
-	    '': {name: '', value: 1, scientific: true},
-
-	    'da': {name: 'da', value: 1e2, scientific: false},
-	    'h': {name: 'h', value: 1e4, scientific: false},
-	    'k': {name: 'k', value: 1e6, scientific: true},
-	    'M': {name: 'M', value: 1e12, scientific: true},
-	    'G': {name: 'G', value: 1e18, scientific: true},
-	    'T': {name: 'T', value: 1e24, scientific: true},
-	    'P': {name: 'P', value: 1e30, scientific: true},
-	    'E': {name: 'E', value: 1e36, scientific: true},
-	    'Z': {name: 'Z', value: 1e42, scientific: true},
-	    'Y': {name: 'Y', value: 1e48, scientific: true},
-
-	    'd': {name: 'd', value: 1e-2, scientific: false},
-	    'c': {name: 'c', value: 1e-4, scientific: false},
-	    'm': {name: 'm', value: 1e-6, scientific: true},
-	    'u': {name: 'u', value: 1e-12, scientific: true},
-	    'n': {name: 'n', value: 1e-18, scientific: true},
-	    'p': {name: 'p', value: 1e-24, scientific: true},
-	    'f': {name: 'f', value: 1e-30, scientific: true},
-	    'a': {name: 'a', value: 1e-36, scientific: true},
-	    'z': {name: 'z', value: 1e-42, scientific: true},
-	    'y': {name: 'y', value: 1e-42, scientific: true}
-	  },
-	  CUBIC: {
-	    '': {name: '', value: 1, scientific: true},
-
-	    'da': {name: 'da', value: 1e3, scientific: false},
-	    'h': {name: 'h', value: 1e6, scientific: false},
-	    'k': {name: 'k', value: 1e9, scientific: true},
-	    'M': {name: 'M', value: 1e18, scientific: true},
-	    'G': {name: 'G', value: 1e27, scientific: true},
-	    'T': {name: 'T', value: 1e36, scientific: true},
-	    'P': {name: 'P', value: 1e45, scientific: true},
-	    'E': {name: 'E', value: 1e54, scientific: true},
-	    'Z': {name: 'Z', value: 1e63, scientific: true},
-	    'Y': {name: 'Y', value: 1e72, scientific: true},
-
-	    'd': {name: 'd', value: 1e-3, scientific: false},
-	    'c': {name: 'c', value: 1e-6, scientific: false},
-	    'm': {name: 'm', value: 1e-9, scientific: true},
-	    'u': {name: 'u', value: 1e-18, scientific: true},
-	    'n': {name: 'n', value: 1e-27, scientific: true},
-	    'p': {name: 'p', value: 1e-36, scientific: true},
-	    'f': {name: 'f', value: 1e-45, scientific: true},
-	    'a': {name: 'a', value: 1e-54, scientific: true},
-	    'z': {name: 'z', value: 1e-63, scientific: true},
-	    'y': {name: 'y', value: 1e-72, scientific: true}
-	  },
-	  BINARY_SHORT: {
-	    '': {name: '', value: 1, scientific: true},
-	    'k': {name: 'k', value: 1e3, scientific: true},
-	    'M': {name: 'M', value: 1e6, scientific: true},
-	    'G': {name: 'G', value: 1e9, scientific: true},
-	    'T': {name: 'T', value: 1e12, scientific: true},
-	    'P': {name: 'P', value: 1e15, scientific: true},
-	    'E': {name: 'E', value: 1e18, scientific: true},
-	    'Z': {name: 'Z', value: 1e21, scientific: true},
-	    'Y': {name: 'Y', value: 1e24, scientific: true},
-
-	    'Ki': {name: 'Ki', value: 1024, scientific: true},
-	    'Mi': {name: 'Mi', value: Math.pow(1024, 2), scientific: true},
-	    'Gi': {name: 'Gi', value: Math.pow(1024, 3), scientific: true},
-	    'Ti': {name: 'Ti', value: Math.pow(1024, 4), scientific: true},
-	    'Pi': {name: 'Pi', value: Math.pow(1024, 5), scientific: true},
-	    'Ei': {name: 'Ei', value: Math.pow(1024, 6), scientific: true},
-	    'Zi': {name: 'Zi', value: Math.pow(1024, 7), scientific: true},
-	    'Yi': {name: 'Yi', value: Math.pow(1024, 8), scientific: true}
-	  },
-	  BINARY_LONG: {
-	    '': {name: '', value: 1, scientific: true},
-	    'kilo': {name: 'kilo', value: 1e3, scientific: true},
-	    'mega': {name: 'mega', value: 1e6, scientific: true},
-	    'giga': {name: 'giga', value: 1e9, scientific: true},
-	    'tera': {name: 'tera', value: 1e12, scientific: true},
-	    'peta': {name: 'peta', value: 1e15, scientific: true},
-	    'exa':  {name: 'exa', value: 1e18, scientific: true},
-	    'zetta': {name: 'zetta', value: 1e21, scientific: true},
-	    'yotta': {name: 'yotta', value: 1e24, scientific: true},
-
-	    'kibi': {name: 'kibi', value: 1024, scientific: true},
-	    'mebi': {name: 'mebi', value: Math.pow(1024, 2), scientific: true},
-	    'gibi': {name: 'gibi', value: Math.pow(1024, 3), scientific: true},
-	    'tebi': {name: 'tebi', value: Math.pow(1024, 4), scientific: true},
-	    'pebi': {name: 'pebi', value: Math.pow(1024, 5), scientific: true},
-	    'exi':  {name: 'exi', value: Math.pow(1024, 6), scientific: true},
-	    'zebi': {name: 'zebi', value: Math.pow(1024, 7), scientific: true},
-	    'yobi': {name: 'yobi', value: Math.pow(1024, 8), scientific: true}
-	  }
-	};
-
-	var PREFIX_NONE = {name: '', value: 1, scientific: true};
-
-	var BASE_UNITS = {
-	  NONE: {},
-
-	  LENGTH: {},               // meter
-	  MASS: {},                 // kilogram
-	  TIME: {},                 // second
-	  CURRENT: {},              // ampere
-	  TEMPERATURE: {},          // kelvin
-	  LUMINOUS_INTENSITY: {},   // candela
-	  AMOUNT_OF_SUBSTANCE: {},  // mole
-
-	  FORCE: {},                // Newton
-	  SURFACE: {},              // m2
-	  VOLUME: {},               // m3
-	  ANGLE: {},                // rad
-	  BIT: {}                   // bit (digital)
-	};
-
-	var BASE_UNIT_NONE = {};
-
-	var UNIT_NONE = {name: '', base: BASE_UNIT_NONE, value: 1, offset: 0};
-
-	var UNITS = {
-	  // length
-	  meter: {name: 'meter', base: BASE_UNITS.LENGTH, prefixes: PREFIXES.LONG, value: 1, offset: 0},
-	  inch: {name: 'inch', base: BASE_UNITS.LENGTH, prefixes: PREFIXES.NONE, value: 0.0254, offset: 0},
-	  foot: {name: 'foot', base: BASE_UNITS.LENGTH, prefixes: PREFIXES.NONE, value: 0.3048, offset: 0},
-	  yard: {name: 'yard', base: BASE_UNITS.LENGTH, prefixes: PREFIXES.NONE, value: 0.9144, offset: 0},
-	  mile: {name: 'mile', base: BASE_UNITS.LENGTH, prefixes: PREFIXES.NONE, value: 1609.344, offset: 0},
-	  link: {name: 'link', base: BASE_UNITS.LENGTH, prefixes: PREFIXES.NONE, value: 0.201168, offset: 0},
-	  rod: {name: 'rod', base: BASE_UNITS.LENGTH, prefixes: PREFIXES.NONE, value: 5.029210, offset: 0},
-	  chain: {name: 'chain', base: BASE_UNITS.LENGTH, prefixes: PREFIXES.NONE, value: 20.1168, offset: 0},
-	  angstrom: {name: 'angstrom', base: BASE_UNITS.LENGTH, prefixes: PREFIXES.NONE, value: 1e-10, offset: 0},
-
-	  m: {name: 'm', base: BASE_UNITS.LENGTH, prefixes: PREFIXES.SHORT, value: 1, offset: 0},
-	  'in': {name: 'in', base: BASE_UNITS.LENGTH, prefixes: PREFIXES.NONE, value: 0.0254, offset: 0},
-	  ft: {name: 'ft', base: BASE_UNITS.LENGTH, prefixes: PREFIXES.NONE, value: 0.3048, offset: 0},
-	  yd: {name: 'yd', base: BASE_UNITS.LENGTH, prefixes: PREFIXES.NONE, value: 0.9144, offset: 0},
-	  mi: {name: 'mi', base: BASE_UNITS.LENGTH, prefixes: PREFIXES.NONE, value: 1609.344, offset: 0},
-	  li: {name: 'li', base: BASE_UNITS.LENGTH, prefixes: PREFIXES.NONE, value: 0.201168, offset: 0},
-	  rd: {name: 'rd', base: BASE_UNITS.LENGTH, prefixes: PREFIXES.NONE, value: 5.029210, offset: 0},
-	  ch: {name: 'ch', base: BASE_UNITS.LENGTH, prefixes: PREFIXES.NONE, value: 20.1168, offset: 0},
-	  mil: {name: 'mil', base: BASE_UNITS.LENGTH, prefixes: PREFIXES.NONE, value: 0.0000254, offset: 0}, // 1/1000 inch
-
-	  // Surface
-	  m2: {name: 'm2', base: BASE_UNITS.SURFACE, prefixes: PREFIXES.SQUARED, value: 1, offset: 0},
-	  sqin: {name: 'sqin', base: BASE_UNITS.SURFACE, prefixes: PREFIXES.NONE, value: 0.00064516, offset: 0}, // 645.16 mm2
-	  sqft: {name: 'sqft', base: BASE_UNITS.SURFACE, prefixes: PREFIXES.NONE, value: 0.09290304, offset: 0}, // 0.09290304 m2
-	  sqyd: {name: 'sqyd', base: BASE_UNITS.SURFACE, prefixes: PREFIXES.NONE, value: 0.83612736, offset: 0}, // 0.83612736 m2
-	  sqmi: {name: 'sqmi', base: BASE_UNITS.SURFACE, prefixes: PREFIXES.NONE, value: 2589988.110336, offset: 0}, // 2.589988110336 km2
-	  sqrd: {name: 'sqrd', base: BASE_UNITS.SURFACE, prefixes: PREFIXES.NONE, value: 25.29295, offset: 0}, // 25.29295 m2
-	  sqch: {name: 'sqch', base: BASE_UNITS.SURFACE, prefixes: PREFIXES.NONE, value: 404.6873, offset: 0}, // 404.6873 m2
-	  sqmil: {name: 'sqmil', base: BASE_UNITS.SURFACE, prefixes: PREFIXES.NONE, value: 6.4516e-10, offset: 0}, // 6.4516 * 10^-10 m2
-
-	  // Volume
-	  m3: {name: 'm3', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.CUBIC, value: 1, offset: 0},
-	  L: {name: 'L', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.SHORT, value: 0.001, offset: 0}, // litre
-	  l: {name: 'l', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.SHORT, value: 0.001, offset: 0}, // litre
-	  litre: {name: 'litre', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.LONG, value: 0.001, offset: 0},
-	  cuin: {name: 'cuin', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 1.6387064e-5, offset: 0}, // 1.6387064e-5 m3
-	  cuft: {name: 'cuft', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.028316846592, offset: 0}, // 28.316 846 592 L
-	  cuyd: {name: 'cuyd', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.764554857984, offset: 0}, // 764.554 857 984 L
-	  teaspoon: {name: 'teaspoon', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.000005, offset: 0}, // 5 mL
-	  tablespoon: {name: 'tablespoon', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.000015, offset: 0}, // 15 mL
-	  //{name: 'cup', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.000240, offset: 0}, // 240 mL  // not possible, we have already another cup
-	  drop: {name: 'drop', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 5e-8, offset: 0},  // 0.05 mL = 5e-8 m3
-	  gtt: {name: 'gtt', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 5e-8, offset: 0},  // 0.05 mL = 5e-8 m3
-
-	  // Liquid volume
-	  minim: {name: 'minim', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.00000006161152, offset: 0}, // 0.06161152 mL
-	  fluiddram: {name: 'fluiddram', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.0000036966911, offset: 0},  // 3.696691 mL
-	  fluidounce: {name: 'fluidounce', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.00002957353, offset: 0}, // 29.57353 mL
-	  gill: {name: 'gill', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.0001182941, offset: 0}, // 118.2941 mL
-	  cc: {name: 'cc', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 1e-6, offset: 0}, // 1e-6 L
-	  cup: {name: 'cup', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.0002365882, offset: 0}, // 236.5882 mL
-	  pint: {name: 'pint', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.0004731765, offset: 0}, // 473.1765 mL
-	  quart: {name: 'quart', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.0009463529, offset: 0}, // 946.3529 mL
-	  gallon: {name: 'gallon', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.003785412, offset: 0}, // 3.785412 L
-	  beerbarrel: {name: 'beerbarrel', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.1173478, offset: 0}, // 117.3478 L
-	  oilbarrel: {name: 'oilbarrel', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.1589873, offset: 0}, // 158.9873 L
-	  hogshead: {name: 'hogshead', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.2384810, offset: 0}, // 238.4810 L
-
-	  //{name: 'min', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.00000006161152, offset: 0}, // 0.06161152 mL // min is already in use as minute
-	  fldr: {name: 'fldr', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.0000036966911, offset: 0},  // 3.696691 mL
-	  floz: {name: 'floz', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.00002957353, offset: 0}, // 29.57353 mL
-	  gi: {name: 'gi', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.0001182941, offset: 0}, // 118.2941 mL
-	  cp: {name: 'cp', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.0002365882, offset: 0}, // 236.5882 mL
-	  pt: {name: 'pt', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.0004731765, offset: 0}, // 473.1765 mL
-	  qt: {name: 'qt', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.0009463529, offset: 0}, // 946.3529 mL
-	  gal: {name: 'gal', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.003785412, offset: 0}, // 3.785412 L
-	  bbl: {name: 'bbl', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.1173478, offset: 0}, // 117.3478 L
-	  obl: {name: 'obl', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.1589873, offset: 0}, // 158.9873 L
-	  //{name: 'hogshead', base: BASE_UNITS.VOLUME, prefixes: PREFIXES.NONE, value: 0.2384810, offset: 0}, // 238.4810 L // TODO: hh?
-
-	  // Mass
-	  g: {name: 'g', base: BASE_UNITS.MASS, prefixes: PREFIXES.SHORT, value: 0.001, offset: 0},
-	  gram: {name: 'gram', base: BASE_UNITS.MASS, prefixes: PREFIXES.LONG, value: 0.001, offset: 0},
-
-	  ton: {name: 'ton', base: BASE_UNITS.MASS, prefixes: PREFIXES.SHORT, value: 907.18474, offset: 0},
-	  tonne: {name: 'tonne', base: BASE_UNITS.MASS, prefixes: PREFIXES.SHORT, value: 1000, offset: 0},
-
-	  grain: {name: 'grain', base: BASE_UNITS.MASS, prefixes: PREFIXES.NONE, value: 64.79891e-6, offset: 0},
-	  dram: {name: 'dram', base: BASE_UNITS.MASS, prefixes: PREFIXES.NONE, value: 1.7718451953125e-3, offset: 0},
-	  ounce: {name: 'ounce', base: BASE_UNITS.MASS, prefixes: PREFIXES.NONE, value: 28.349523125e-3, offset: 0},
-	  poundmass: {name: 'poundmass', base: BASE_UNITS.MASS, prefixes: PREFIXES.NONE, value: 453.59237e-3, offset: 0},
-	  hundredweight: {name: 'hundredweight', base: BASE_UNITS.MASS, prefixes: PREFIXES.NONE, value: 45.359237, offset: 0},
-	  stick: {name: 'stick', base: BASE_UNITS.MASS, prefixes: PREFIXES.NONE, value: 115e-3, offset: 0},
-	  stone: {name: 'stone', base: BASE_UNITS.MASS, prefixes: PREFIXES.NONE, value: 6350, offset: 0},
-
-	  gr: {name: 'gr', base: BASE_UNITS.MASS, prefixes: PREFIXES.NONE, value: 64.79891e-6, offset: 0},
-	  dr: {name: 'dr', base: BASE_UNITS.MASS, prefixes: PREFIXES.NONE, value: 1.7718451953125e-3, offset: 0},
-	  oz: {name: 'oz', base: BASE_UNITS.MASS, prefixes: PREFIXES.NONE, value: 28.349523125e-3, offset: 0},
-	  lbm: {name: 'lbm', base: BASE_UNITS.MASS, prefixes: PREFIXES.NONE, value: 453.59237e-3, offset: 0},
-	  cwt: {name: 'cwt', base: BASE_UNITS.MASS, prefixes: PREFIXES.NONE, value: 45.359237, offset: 0},
-
-	  // Time
-	  s: {name: 's', base: BASE_UNITS.TIME, prefixes: PREFIXES.SHORT, value: 1, offset: 0},
-	  min: {name: 'min', base: BASE_UNITS.TIME, prefixes: PREFIXES.NONE, value: 60, offset: 0},
-	  h: {name: 'h', base: BASE_UNITS.TIME, prefixes: PREFIXES.NONE, value: 3600, offset: 0},
-	  second: {name: 'second', base: BASE_UNITS.TIME, prefixes: PREFIXES.LONG, value: 1, offset: 0},
-	  sec: {name: 'sec', base: BASE_UNITS.TIME, prefixes: PREFIXES.LONG, value: 1, offset: 0},
-	  minute: {name: 'minute', base: BASE_UNITS.TIME, prefixes: PREFIXES.NONE, value: 60, offset: 0},
-	  hour: {name: 'hour', base: BASE_UNITS.TIME, prefixes: PREFIXES.NONE, value: 3600, offset: 0},
-	  day: {name: 'day', base: BASE_UNITS.TIME, prefixes: PREFIXES.NONE, value: 86400, offset: 0},
-
-	  // Angle
-	  rad: {name: 'rad', base: BASE_UNITS.ANGLE, prefixes: PREFIXES.NONE, value: 1, offset: 0},
-	  // deg = rad / (2*pi) * 360 = rad / 0.017453292519943295769236907684888
-	  deg: {name: 'deg', base: BASE_UNITS.ANGLE, prefixes: PREFIXES.NONE, value: 0.017453292519943295769236907684888, offset: 0},
-	  // grad = rad / (2*pi) * 400  = rad / 0.015707963267948966192313216916399
-	  grad: {name: 'grad', base: BASE_UNITS.ANGLE, prefixes: PREFIXES.NONE, value: 0.015707963267948966192313216916399, offset: 0},
-	  // cycle = rad / (2*pi) = rad / 6.2831853071795864769252867665793
-	  cycle: {name: 'cycle', base: BASE_UNITS.ANGLE, prefixes: PREFIXES.NONE, value: 6.2831853071795864769252867665793, offset: 0},
-
-	  // Electric current
-	  A: {name: 'A', base: BASE_UNITS.CURRENT, prefixes: PREFIXES.SHORT, value: 1, offset: 0},
-	  ampere: {name: 'ampere', base: BASE_UNITS.CURRENT, prefixes: PREFIXES.LONG, value: 1, offset: 0},
-
-	  // Temperature
-	  // K(C) = °C + 273.15
-	  // K(F) = (°F + 459.67) / 1.8
-	  // K(R) = °R / 1.8
-	  K: {name: 'K', base: BASE_UNITS.TEMPERATURE, prefixes: PREFIXES.NONE, value: 1, offset: 0},
-	  degC: {name: 'degC', base: BASE_UNITS.TEMPERATURE, prefixes: PREFIXES.NONE, value: 1, offset: 273.15},
-	  degF: {name: 'degF', base: BASE_UNITS.TEMPERATURE, prefixes: PREFIXES.NONE, value: 1/1.8, offset: 459.67},
-	  degR: {name: 'degR', base: BASE_UNITS.TEMPERATURE, prefixes: PREFIXES.NONE, value: 1/1.8, offset: 0},
-	  kelvin: {name: 'kelvin', base: BASE_UNITS.TEMPERATURE, prefixes: PREFIXES.NONE, value: 1, offset: 0},
-	  celsius: {name: 'celsius', base: BASE_UNITS.TEMPERATURE, prefixes: PREFIXES.NONE, value: 1, offset: 273.15},
-	  fahrenheit: {name: 'fahrenheit', base: BASE_UNITS.TEMPERATURE, prefixes: PREFIXES.NONE, value: 1/1.8, offset: 459.67},
-	  rankine: {name: 'rankine', base: BASE_UNITS.TEMPERATURE, prefixes: PREFIXES.NONE, value: 1/1.8, offset: 0},
-
-	  // amount of substance
-	  mol: {name: 'mol', base: BASE_UNITS.AMOUNT_OF_SUBSTANCE, prefixes: PREFIXES.NONE, value: 1, offset: 0},
-	  mole: {name: 'mole', base: BASE_UNITS.AMOUNT_OF_SUBSTANCE, prefixes: PREFIXES.NONE, value: 1, offset: 0},
-
-	  // luminous intensity
-	  cd: {name: 'cd', base: BASE_UNITS.LUMINOUS_INTENSITY, prefixes: PREFIXES.NONE, value: 1, offset: 0},
-	  candela: {name: 'candela', base: BASE_UNITS.LUMINOUS_INTENSITY, prefixes: PREFIXES.NONE, value: 1, offset: 0},
-	  // TODO: units STERADIAN
-	  //{name: 'sr', base: BASE_UNITS.STERADIAN, prefixes: PREFIXES.NONE, value: 1, offset: 0},
-	  //{name: 'steradian', base: BASE_UNITS.STERADIAN, prefixes: PREFIXES.NONE, value: 1, offset: 0},
-
-	  // Force
-	  N: {name: 'N', base: BASE_UNITS.FORCE, prefixes: PREFIXES.SHORT, value: 1, offset: 0},
-	  newton: {name: 'newton', base: BASE_UNITS.FORCE, prefixes: PREFIXES.LONG, value: 1, offset: 0},
-	  lbf: {name: 'lbf', base: BASE_UNITS.FORCE, prefixes: PREFIXES.NONE, value: 4.4482216152605, offset: 0},
-	  poundforce: {name: 'poundforce', base: BASE_UNITS.FORCE, prefixes: PREFIXES.NONE, value: 4.4482216152605, offset: 0},
-
-	  // Binary
-	  b: {name: 'b', base: BASE_UNITS.BIT, prefixes: PREFIXES.BINARY_SHORT, value: 1, offset: 0},
-	  bits: {name: 'bits', base: BASE_UNITS.BIT, prefixes: PREFIXES.BINARY_LONG, value: 1, offset: 0},
-	  B: {name: 'B', base: BASE_UNITS.BIT, prefixes: PREFIXES.BINARY_SHORT, value: 8, offset: 0},
-	  bytes: {name: 'bytes', base: BASE_UNITS.BIT, prefixes: PREFIXES.BINARY_LONG, value: 8, offset: 0}
-	};
-
-	// plurals
-	var PLURALS = {
-	  meters: 'meter',
-	  inches: 'inch',
-	  feet: 'foot',
-	  yards: 'yard',
-	  miles: 'mile',
-	  links: 'link',
-	  rods: 'rod',
-	  chains: 'chain',
-	  angstroms: 'angstrom',
-
-	  litres: 'litre',
-	  teaspoons: 'teaspoon',
-	  tablespoons: 'tablespoon',
-	  minims: 'minim',
-	  fluiddrams: 'fluiddram',
-	  fluidounces: 'fluidounce',
-	  gills: 'gill',
-	  cups: 'cup',
-	  pints: 'pint',
-	  quarts: 'quart',
-	  gallons: 'gallon',
-	  beerbarrels: 'beerbarrel',
-	  oilbarrels: 'oilbarrel',
-	  hogsheads: 'hogshead',
-	  gtts: 'gtt',
-
-	  grams: 'gram',
-	  tons: 'ton',
-	  tonnes: 'tonne',
-	  grains: 'grain',
-	  drams: 'dram',
-	  ounces: 'ounce',
-	  poundmasses: 'poundmass',
-	  hundredweights: 'hundredweight',
-	  sticks: 'stick',
-
-	  seconds: 'second',
-	  minutes: 'minute',
-	  hours: 'hour',
-	  days: 'day',
-
-	  radians: 'rad',
-	  degrees: 'deg',
-	  gradients: 'grad',
-	  cycles: 'cycle',
-
-	  amperes: 'ampere',
-	  moles: 'mole'
-	};
-
-	for (var name in PLURALS) {
-	  /* istanbul ignore next (we cannot really test next statement) */
-	  if (PLURALS.hasOwnProperty(name)) {
-	    var unit = UNITS[PLURALS[name]];
-	    var plural = Object.create(unit);
-	    plural.name = name;
-	    UNITS[name] = plural;
-	  }
-	}
-
-	// aliases
-	UNITS.lt = UNITS.l;
-	UNITS.liter = UNITS.litre;
-	UNITS.liters = UNITS.litres;
-	UNITS.lb = UNITS.lbm;
-	UNITS.lbs = UNITS.lbm;
-
-
-	Unit.PREFIXES = PREFIXES;
-	Unit.BASE_UNITS = BASE_UNITS;
-	Unit.UNITS = UNITS;
-
-	// end of unit aliases
-
-
-	// exports
-	module.exports = Unit;
+	/**
+	 * Create a syntax error with the message:
+	 *     'Wrong number of arguments in function <fn> (<count> provided, <min>-<max> expected)'
+	 * @param {string} fn     Function name
+	 * @param {number} count  Actual argument count
+	 * @param {number} min    Minimum required argument count
+	 * @param {number} [max]  Maximum required argument count
+	 * @extends Error
+	 */
+	function ArgumentsError(fn, count, min, max) {
+	  if (!(this instanceof ArgumentsError)) {
+	    throw new SyntaxError('Constructor must be called with the new operator');
+	  }
+
+	  this.fn = fn;
+	  this.count = count;
+	  this.min = min;
+	  this.max = max;
+
+	  this.message = 'Wrong number of arguments in function ' + fn +
+	      ' (' + count + ' provided, ' +
+	      min + ((max != undefined) ? ('-' + max) : '') + ' expected)';
+
+	  this.stack = (new Error()).stack;
+	}
+
+	ArgumentsError.prototype = new Error();
+	ArgumentsError.prototype.constructor = Error;
+	ArgumentsError.prototype.name = 'ArgumentsError';
+	ArgumentsError.prototype.isArgumentsError = true;
+
+	module.exports = ArgumentsError;
 
 
 /***/ },
@@ -3314,1681 +2863,113 @@
 
 	'use strict';
 
-	var util = __webpack_require__(175);
-	var object = util.object;
-	var string = util.string;
-
-	/**
-	 * Documentation object
-	 * @param {Object} doc  Object containing properties:
-	 *                      {String} name
-	 *                      {String} category
-	 *                      {String} description
-	 *                      {String[]} syntax
-	 *                      {String[]} examples
-	 *                      {String[]} seealso
-	 * @constructor
-	 */
-	function Help (doc) {
-	  if (!(this instanceof Help)) {
-	    throw new SyntaxError('Constructor must be called with the new operator');
-	  }
-
-	  if (!doc)  throw new Error('Argument "doc" missing');
-
-	  this.doc = doc;
+	var object = __webpack_require__(5);
+
+	function factory (type, config, load, typed, math) {
+	  /**
+	   * Set configuration options for math.js, and get current options.
+	   * Will emit a 'config' event, with arguments (curr, prev).
+	   * @param {Object} [options] Available options:
+	   *                            {number} epsilon
+	   *                              Minimum relative difference between two
+	   *                              compared values, used by all comparison functions.
+	   *                            {string} matrix
+	   *                              A string 'matrix' (default) or 'array'.
+	   *                            {string} number
+	   *                              A string 'number' (default) or 'bignumber'
+	   *                            {number} precision
+	   *                              The number of significant digits for BigNumbers.
+	   *                              Not applicable for Numbers.
+	   *                            {string} parenthesis
+	   *                              How to display parentheses in LaTeX and string
+	   *                              output.
+	   * @return {Object} Returns the current configuration
+	   */
+	  return function _config(options) {
+	    if (options) {
+	      var prev = object.clone(config);
+
+	      // merge options
+	      object.deepExtend(config, options);
+
+	      var curr = object.clone(config);
+
+	      // emit 'config' event
+	      math.emit('config', curr, prev);
+
+	      return curr;
+	    }
+	    else {
+	      return object.clone(config);
+	    }
+	  };
 	}
 
-	/**
-	 * Test whether a value is an instance of Help
-	 * @param {*} value
-	 * @return {Boolean} isHelp
-	 */
-	Help.isHelp = function (value) {
-	  return (value instanceof Help);
-	};
-
-	/**
-	 * Generate readable description from a Help object
-	 * @param {Object} [math]   A math instance, used to evaluate the examples
-	 * @return {String} readableDoc
-	 * @private
-	 */
-	Help.prototype.toText = function (math) {
-	  var doc = this.doc || {};
-	  var desc = '\n';
-
-	  if (doc.name) {
-	    desc += 'Name: ' + doc.name + '\n\n';
-	  }
-	  if (doc.category) {
-	    desc += 'Category: ' + doc.category + '\n\n';
-	  }
-	  if (doc.description) {
-	    desc += 'Description:\n    ' + doc.description + '\n\n';
-	  }
-	  if (doc.syntax) {
-	    desc += 'Syntax:\n    ' + doc.syntax.join('\n    ') + '\n\n';
-	  }
-	  if (doc.examples) {
-	    var parser = math && math.parser();
-	    desc += 'Examples:\n';
-	    for (var i = 0; i < doc.examples.length; i++) {
-	      var expr = doc.examples[i];
-	      desc += '    ' + expr + '\n';
-
-	      if (parser) {
-	        var res;
-	        try {
-	          res = parser.eval(expr);
-	        }
-	        catch (e) {
-	          res = e;
-	        }
-	        if (res !== undefined && !(res instanceof Help)) {
-	          desc += '        ' + string.format(res, {precision: 14}) + '\n';
-	        }
-	      }
-	    }
-	    desc += '\n';
-	  }
-	  if (doc.seealso) {
-	    desc += 'See also: ' + doc.seealso.join(', ') + '\n';
-	  }
-
-	  return desc;
-	};
-
-	/**
-	 * Generate a string representation of the Help object
-	 * @return {String} Returns a string
-	 * @private
-	 */
-	Help.prototype.toString = function () {
-	  return this.toText();
-	};
-
-	/**
-	 * Export the help object to JSON
-	 */
-	Help.prototype.toJSON = function () {
-	  var obj = object.clone(this.doc);
-	  obj.mathjs = 'Help';
-	  return obj;
-	};
-
-	/**
-	 * Instantiate a Help object from a JSON object
-	 * @param {Object} json
-	 * @returns {Help} Returns a new Help object
-	 */
-	Help.fromJSON = function (json) {
-	  var doc = {};
-	  for (var prop in json) {
-	    if (prop !== 'mathjs') { // ignore mathjs field
-	      doc[prop] = json[prop];
-	    }
-	  }
-	  return new Help(doc);
-	};
-
-	/**
-	 * Returns a string representation of the Help object
-	 */
-	Help.prototype.valueOf = Help.prototype.toString;
-
-	// exports
-	module.exports = Help;
+	exports.name = 'config';
+	exports.math = true; // request the math namespace as fifth argument
+	exports.factory = factory;
 
 
 /***/ },
 /* 13 */
 /***/ function(module, exports, __webpack_require__) {
 
-	'use strict';
-
-	/**
-	 * A ResultSet contains a list or results
-	 * @param {Array} entries
-	 * @constructor
-	 */
-	function ResultSet(entries) {
-	  if (!(this instanceof ResultSet)) {
-	    throw new SyntaxError('Constructor must be called with the new operator');
-	  }
-
-	  this.entries = entries || [];
-	}
-
-	/**
-	 * Returns the array with results hold by this ResultSet
-	 * @returns {Array} entries
-	 */
-	ResultSet.prototype.valueOf = function () {
-	  return this.entries;
-	};
-
-	/**
-	 * Returns the stringified results of the ResultSet
-	 * @returns {String} string
-	 */
-	ResultSet.prototype.toString = function () {
-	  return '[' + this.entries.join(', ') + ']';
-	};
-
-	/**
-	 * Get a JSON representation of the ResultSet
-	 * @returns {Object} Returns a JSON object structured as:
-	 *                   `{"mathjs": "ResultSet", "entries": [...]}`
-	 */
-	ResultSet.prototype.toJSON = function () {
-	  return {
-	    mathjs: 'ResultSet',
-	    entries: this.entries
-	  };
-	};
-
-	/**
-	 * Instantiate a ResultSet from a JSON object
-	 * @param {Object} json  A JSON object structured as:
-	 *                       `{"mathjs": "ResultSet", "entries": [...]}`
-	 * @return {ResultSet}
-	 */
-	ResultSet.fromJSON = function (json) {
-	  return new ResultSet(json.entries);
-	};
-
-	module.exports = ResultSet;
+	module.exports = [
+	  __webpack_require__(243),        // data types (Matrix, Complex, Unit, ...)
+	  __webpack_require__(280),   // constants
+	  __webpack_require__(282),  // expression parsing
+	  __webpack_require__(14),    // functions
+	  __webpack_require__(487),        // serialization utility (math.json.reviver)
+	  __webpack_require__(489)        // errors
+	];
 
 
 /***/ },
 /* 14 */
 /***/ function(module, exports, __webpack_require__) {
 
-	// utility methods for arrays and matrices
-	'use strict';
-
-	var util = __webpack_require__(175),
-
-	    IndexError = __webpack_require__(173),
-	    DimensionError = __webpack_require__(172),
-
-	    array = util.array,
-	    isArray = util.array.isArray;
-
-	module.exports = function (math) {
-
-	  var Matrix = math.type.Matrix;
-
-	  var collection = {};
-
-	  /**
-	   * Convert function arguments to an array. Arguments can have the following
-	   * signature:
-	   *     fn()
-	   *     fn(n)
-	   *     fn(m, n, p, ...)
-	   *     fn([m, n, p, ...])
-	   * @param {...Number | Array | Matrix} args
-	   * @returns {Array} array
-	   */
-	  collection.argsToArray = function(args) {
-	    if (args.length === 0) {
-	      // fn()
-	      return [];
-	    }
-	    else if (args.length == 1) {
-	      // fn(n)
-	      // fn([m, n, p, ...])
-	      var array = args[0];
-	      if (array instanceof Matrix) {
-	        array = array.valueOf();
-	      }
-	      if (!isArray(array)) {
-	        array = [array];
-	      }
-	      return array;
-	    }
-	    else {
-	      // fn(m, n, p, ...)
-	      return util.array.argsToArray(args);
-	    }
-	  };
-
-
-	  /**
-	   * Test whether a value is a collection: an Array or Matrix
-	   * @param {*} x
-	   * @returns {boolean} isCollection
-	   */
-	  collection.isCollection = function(x) {
-	    return (isArray(x) || (x instanceof Matrix));
-	  };
-
-	  /**
-	   * Execute the callback function element wise for each element in array and any
-	   * nested array
-	   * Returns an array with the results
-	   * @param {Array | Matrix} array
-	   * @param {function} callback   The callback is called with two parameters:
-	   *                              value1 and value2, which contain the current
-	   *                              element of both arrays.
-	   * @param {boolean} [skipZeros] Invoke callback function for non-zero values only.
-	   *
-	   * @return {Array | Matrix} res
-	   */
-	  collection.deepMap = function deepMap(array, callback, skipZeros) {
-	    if (array && (typeof array.map === 'function')) {
-	      return array.map(function (x) {
-	        return deepMap(x, callback, skipZeros);
-	      });
-	    }
-	    else {
-	      return callback(array);
-	    }
-	  };
-
-	  /**
-	   * Execute the callback function element wise for each entry in two given arrays,
-	   * and for any nested array. Objects can also be scalar objects.
-	   * Returns an array with the results.
-	   * @param {Array | Matrix | Object} array1
-	   * @param {Array | Matrix | Object} array2
-	   * @param {function} callback   The callback is called with two parameters:
-	   *                              value1 and value2, which contain the current
-	   *                              element of both arrays.
-	   * @return {Array | Matrix} res
-	   */
-	  collection.deepMap2 = function deepMap2(array1, array2, callback) {
-	    var res, len, i;
-
-	    if (isArray(array1)) {
-	      if (isArray(array2)) {
-	        // callback(array, array)
-	        if (array1.length != array2.length) {
-	          throw new DimensionError(array1.length, array2.length);
-	        }
-
-	        res = [];
-	        len = array1.length;
-	        for (i = 0; i < len; i++) {
-	          res[i] = deepMap2(array1[i], array2[i], callback);
-	        }
-	      }
-	      else if (array2 instanceof Matrix) {
-	        // callback(array, matrix)
-	        res = deepMap2(array1, array2.valueOf(), callback);
-	        return math.matrix(res);
-	      }
-	      else {
-	        // callback(array, object)
-	        res = [];
-	        len = array1.length;
-	        for (i = 0; i < len; i++) {
-	          res[i] = deepMap2(array1[i], array2, callback);
-	        }
-	      }
-	    }
-	    else if (array1 instanceof Matrix) {
-	      if (array2 instanceof Matrix) {
-	        // callback(matrix, matrix)
-	        res = deepMap2(array1.valueOf(), array2.valueOf(), callback);
-	        return math.matrix(res);
-	      }
-	      else {
-	        // callback(matrix, array)
-	        // callback(matrix, object)
-	        res = deepMap2(array1.valueOf(), array2, callback);
-	        return math.matrix(res);
-	      }
-	    }
-	    else {
-	      if (isArray(array2)) {
-	        // callback(object, array)
-	        res = [];
-	        len = array2.length;
-	        for (i = 0; i < len; i++) {
-	          res[i] = deepMap2(array1, array2[i], callback);
-	        }
-	      }
-	      else if (array2 instanceof Matrix) {
-	        // callback(object, matrix)
-	        res = deepMap2(array1, array2.valueOf(), callback);
-	        return math.matrix(res);
-	      }
-	      else {
-	        // callback(object, object)
-	        res = callback(array1, array2);
-	      }
-	    }
-
-	    return res;
-	  };
-
-	  /**
-	   * Reduce a given matrix or array to a new matrix or
-	   * array with one less dimension, applying the given
-	   * callback in the selected dimension.
-	   * @param {Array | Matrix} mat
-	   * @param {Number} dim
-	   * @param {function} callback
-	   * @return {Array | Matrix} res
-	   */
-	  collection.reduce = function(mat, dim, callback) {
-	    var size = isArray(mat) ? array.size(mat) : mat.size();
-	    if (dim < 0) {
-	      // TODO: would be more clear when throwing a DimensionError here
-	      throw new IndexError(dim);
-	    }
-	    if (dim >= size.length) {
-	      // TODO: would be more clear when throwing a DimensionError here
-	      throw new IndexError(dim, size.length);
-	    }
-
-	      if (mat instanceof Matrix) {
-	          return math.matrix(_reduce(mat.valueOf(), dim, callback));
-	      }else {
-	          return _reduce(mat, dim, callback);
-	      }
-	  };
-
-	  /**
-	   * Recursively reduce a matrix
-	   * @param {Array} mat
-	   * @param {Number} dim
-	   * @param {Function} callback
-	   * @returns {Array} ret
-	   * @private
-	   */
-	  function _reduce(mat, dim, callback){
-	    var i, ret, val, tran;
-
-	      if(dim<=0){
-	          if( !isArray(mat[0]) ){
-	              val = mat[0];
-	              for(i=1; i<mat.length; i++){
-	                  val = callback(val, mat[i]);
-	              }
-	              return val;
-	          }else{
-	              tran = _switch(mat);
-	              ret = [];
-	              for(i=0; i<tran.length; i++){
-	                  ret[i] = _reduce(tran[i], dim-1, callback);
-	              }
-	              return ret;
-	          }
-	      }else{
-	          ret = [];
-	          for(i=0; i<mat.length; i++){
-	              ret[i] = _reduce(mat[i], dim-1, callback);
-	          }
-	          return ret;
-	      }
-	  }
-
-	  /**
-	   * Transpose a matrix
-	   * @param {Array} mat
-	   * @returns {Array} ret
-	   * @private
-	   */
-	  function _switch(mat){
-	    var I = mat.length;
-	    var J = mat[0].length;
-	    var i, j;
-	    var ret = [];
-	    for( j=0; j<J; j++) {
-	      var tmp = [];
-	      for( i=0; i<I; i++) {
-	        tmp.push(mat[i][j]);
-	      }
-	      ret.push(tmp);
-	    }
-	    return ret;
-	  }
-
-	  /**
-	   * Recursively loop over all elements in a given multi dimensional array
-	   * and invoke the callback on each of the elements.
-	   * @param {Array | Matrix} array
-	   * @param {function} callback     The callback method is invoked with one
-	   *                                parameter: the current element in the array
-	   */
-	  collection.deepForEach = function deepForEach (array, callback) {
-	    if (array instanceof Matrix) {
-	      array = array.valueOf();
-	    }
-
-	    for (var i = 0, ii = array.length; i < ii; i++) {
-	      var value = array[i];
-
-	      if (isArray(value)) {
-	        deepForEach(value, callback);
-	      }
-	      else {
-	        callback(value);
-	      }
-	    }
-	  };
-	  
-	  return collection;
-	};
+	module.exports = [
+	  __webpack_require__(61),
+	  __webpack_require__(91),
+	  __webpack_require__(120),
+	  __webpack_require__(136),
+	  __webpack_require__(148),
+	  __webpack_require__(153),
+	  __webpack_require__(155),
+	  __webpack_require__(15),
+	  __webpack_require__(160),
+	  __webpack_require__(172),
+	  __webpack_require__(178),
+	  __webpack_require__(190),
+	  __webpack_require__(231),
+	  __webpack_require__(233)
+	];
+
 
 /***/ },
 /* 15 */
 /***/ function(module, exports, __webpack_require__) {
 
-	'use strict';
-
-	var util = __webpack_require__(175);
-	var DimensionError = __webpack_require__(172);
-
-	var array = util.array;
-	var object = util.object;
-	var string = util.string;
-	var number = util.number;
-
-	var isArray = Array.isArray;
-	var isNumber = util.number.isNumber;
-	var isInteger = util.number.isInteger;
-
-	var validateIndex = array.validateIndex;
-
-	module.exports = function (math) {
-	  
-	  var Index = math.type.Index,
-	      BigNumber = math.type.BigNumber,
-	      Matrix = math.type.Matrix;
-	  
-	  function CcsMatrix(data) {
-	    if (!(this instanceof CcsMatrix))
-	      throw new SyntaxError('Constructor must be called with the new operator');
-
-	    if (data instanceof Matrix) {
-	      // check data is a CcsMatrix
-	      if (data.type === 'CcsMatrix') {
-	        // clone arrays
-	        this._values = object.clone(data._values);
-	        this._index = object.clone(data._index);
-	        this._ptr = object.clone(data._ptr);
-	        this._size = object.clone(data._size);
-	      }
-	      else {
-	        // build from matrix data
-	        _createFromArray(this, data.valueOf());
-	      }
-	    }
-	    else if (data && isArray(data.values) && isArray(data.index) && isArray(data.ptr) && isArray(data.size)) {
-	      // initialize fields
-	      this._values = data.values;
-	      this._index = data.index;
-	      this._ptr = data.ptr;
-	      this._size = data.size;
-	    }
-	    else if (isArray(data)) {
-	      // create from array
-	      _createFromArray(this, data);
-	    }
-	    else if (data) {
-	      // unsupported type
-	      throw new TypeError('Unsupported type of data (' + util.types.type(data) + ')');
-	    }
-	    else {
-	      // nothing provided
-	      this._values = [];
-	      this._index = [];
-	      this._ptr = [0];
-	      this._size = [0];
-	    }
-	  }
-	  
-	  var _createFromArray = function (matrix, data) {
-	    // initialize fields
-	    matrix._values = [];
-	    matrix._index = [];
-	    matrix._ptr = [];
-	    // discover rows & columns, do not use math.size() to avoid looping array twice
-	    var rows = data.length;
-	    var columns = 0;
-
-	    // check we have rows (empty array)
-	    if (rows > 0) {
-	      // column index
-	      var j = 0;
-	      do {
-	        // store pointer to values index
-	        matrix._ptr.push(matrix._values.length);
-	        // loop rows
-	        for (var i = 0; i < rows; i++) {
-	          // current row
-	          var row = data[i];
-	          // check row is an array
-	          if (isArray(row)) {
-	            // update columns if needed (only on first column)
-	            if (j ===0 && columns < row.length)
-	              columns = row.length;
-	            // check row has column
-	            if (j < row.length) {
-	              // value
-	              var v = row[j];
-	              // check value != 0
-	              if (!math.equal(v, 0)) {
-	                // store value
-	                matrix._values.push(v);
-	                // index
-	                matrix._index.push(i);
-	              }
-	            }
-	          }
-	          else {
-	            // update columns if needed (only on first column)
-	            if (j === 0 && columns < 1)
-	              columns = 1;
-	            // check value != 0 (row is a scalar)
-	            if (!math.equal(row, 0)) {
-	              // store value
-	              matrix._values.push(row);
-	              // index
-	              matrix._index.push(i);
-	            }
-	          }
-	        }
-	        // increment index
-	        j++;      
-	      }
-	      while (j < columns);
-	    }
-	    // store number of values in ptr
-	    matrix._ptr.push(matrix._values.length);
-	    // size
-	    matrix._size = [rows, columns];
-	  };
-	  
-	  CcsMatrix.prototype = new math.type.Matrix();
-
-	  CcsMatrix.prototype.type = 'CcsMatrix';
-	  
-	  /**
-	   * Get the storage format used by the matrix.
-	   *
-	   * Usage:
-	   *     var format = matrix.storage()                   // retrieve storage format
-	   *
-	   * @return {string}           The storage format.
-	   */
-	  CcsMatrix.prototype.storage = function () {
-	    return 'ccs';
-	  };
-	  
-	  /**
-	   * Get a subset of the matrix, or replace a subset of the matrix.
-	   *
-	   * Usage:
-	   *     var subset = matrix.subset(index)               // retrieve subset
-	   *     var value = matrix.subset(index, replacement)   // replace subset
-	   *
-	   * @param {Index} index
-	   * @param {Array | Maytrix | *} [replacement]
-	   * @param {*} [defaultValue=0]      Default value, filled in on new entries when
-	   *                                  the matrix is resized. If not provided,
-	   *                                  new matrix elements will be filled with zeros.
-	   */
-	  CcsMatrix.prototype.subset = function (index, replacement, defaultValue) {
-	    // check arguments
-	    switch (arguments.length) {
-	      case 1:
-	        return _getsubset(this, index);
-
-	        // intentional fall through
-	      case 2:
-	      case 3:
-	        return _setsubset(this, index, replacement, defaultValue);
-
-	      default:
-	        throw new SyntaxError('Wrong number of arguments');
-	    }
-	  };
-	  
-	  var _getsubset = function (matrix, index) {
-	    // check index
-	    if (!(index instanceof Index)) {
-	      throw new TypeError('Invalid index');
-	    }
-
-	    var isScalar = index.isScalar();
-	    if (isScalar) {
-	      // return a scalar
-	      return matrix.get(index.min());
-	    }
-	    // validate dimensions
-	    var size = index.size();
-	    if (size.length != matrix._size.length) {
-	      throw new DimensionError(size.length, matrix._size.length);
-	    }
-
-	    // validate if any of the ranges in the index is out of range
-	    var min = index.min();
-	    var max = index.max();
-	    for (var i = 0, ii = matrix._size.length; i < ii; i++) {
-	      validateIndex(min[i], matrix._size[i]);
-	      validateIndex(max[i], matrix._size[i]);
-	    }
-
-	    // map callback
-	    var callback = function (v) {
-	      // return value
-	      return v;
-	    };
-	    // get sub-matrix
-	    return _map(matrix, min[0], max[0], min[1], max[1], callback, false);
-	  };
-	  
-	  var _setsubset = function (matrix, index, submatrix, defaultValue) {
-	    // check index
-	    if (!(index instanceof Index)) {
-	      throw new TypeError('Invalid index');
-	    }
-	    
-	    // get index size and check whether the index contains a single value
-	    var iSize = index.size(),
-	        isScalar = index.isScalar();
-	    
-	    // calculate the size of the submatrix, and convert it into an Array if needed
-	    var sSize;
-	    if (submatrix instanceof Matrix) {
-	      // submatrix size
-	      sSize = submatrix.size();
-	      // use array representation
-	      submatrix = submatrix.toArray();
-	    }
-	    else {
-	      // get submatrix size (array, scalar)
-	      sSize = array.size(submatrix);
-	    }
-	    
-	    // check index is a scalar
-	    if (isScalar) {
-	      // verify submatrix is a scalar
-	      if (sSize.length !== 0) {
-	        throw new TypeError('Scalar expected');
-	      }
-	      // set value
-	      matrix.set(index.min(), submatrix, defaultValue);
-	    }
-	    else {
-	      // validate dimensions, index size must be one or two dimensions
-	      if (iSize.length !== 1 && iSize.length !== 2) {
-	        throw new DimensionError(iSize.length, matrix._size.length, '<');
-	      }
-	      
-	      // check submatrix and index have the same dimensions
-	      if (sSize.length < iSize.length) {
-	        // calculate number of missing outer dimensions
-	        var i = 0;
-	        var outer = 0;
-	        while (iSize[i] === 1 && sSize[i] === 1) {
-	          i++;
-	        }
-	        while (iSize[i] === 1) {
-	          outer++;
-	          i++;
-	        }
-	        // unsqueeze both outer and inner dimensions
-	        submatrix = array.unsqueeze(submatrix, iSize.length, outer, sSize);
-	      }
-	      
-	      // check whether the size of the submatrix matches the index size
-	      if (!object.deepEqual(iSize, sSize)) {
-	        throw new DimensionError(iSize, sSize, '>');
-	      }
-	      
-	      // offsets
-	      var x0 = index.min()[0];
-	      var y0 = index.min()[1];      
-	      
-	      // submatrix rows and columns
-	      var m = sSize[0];
-	      var n = sSize[1];
-
-	      // loop submatrix
-	      for (var x = 0; x < m; x++) {
-	        // loop columns
-	        for (var y = 0; y < n; y++) {
-	          // value at i, j
-	          var v = submatrix[x][y];
-	          // invoke set (zero value will remove entry from matrix)
-	          matrix.set([x + x0, y + y0], v, defaultValue);
-	        }
-	      }
-	    }
-	    return matrix;
-	  };
-
-	  /**
-	   * Get a single element from the matrix.
-	   * @param {Number[]} index   Zero-based index
-	   * @return {*} value
-	   */
-	  CcsMatrix.prototype.get = function (index) {
-	    if (!isArray(index))
-	      throw new TypeError('Array expected');
-	    if (index.length != this._size.length)
-	      throw new DimensionError(index.length, this._size.length);
-
-	    // row and column
-	    var i = index[0];
-	    var j = index[1];
-
-	    // check i, j are valid
-	    validateIndex(i, this._size[0]);
-	    validateIndex(j, this._size[1]);
-
-	    // find value index
-	    var k = _getValueIndex(i, this._ptr[j], this._ptr[j + 1], this._index);
-	    // check k is prior to next column k and it is in the correct row
-	    if (k < this._ptr[j + 1] && this._index[k] === i)
-	      return object.clone(this._values[k]);
-
-	    return 0;
-	  };
-	  
-	  /**
-	   * Replace a single element in the matrix.
-	   * @param {Number[]} index   Zero-based index
-	   * @param {*} value
-	   * @param {*} [defaultValue]        Default value, filled in on new entries when
-	   *                                  the matrix is resized. If not provided,
-	   *                                  new matrix elements will be set to zero.
-	   * @return {CcsMatrix} self
-	   */
-	  CcsMatrix.prototype.set = function (index, v, defaultValue) {
-	    if (!isArray(index))
-	      throw new TypeError('Array expected');
-	    if (index.length != this._size.length)
-	      throw new DimensionError(index.length, this._size.length);
-
-	    // row and column
-	    var i = index[0];
-	    var j = index[1];
-
-	    // rows & columns
-	    var rows = this._size[0];
-	    var columns = this._size[1];
-
-	    // check we need to resize matrix
-	    if (i > rows - 1 || j > columns - 1) {
-	      // resize matrix
-	      _resize(this, Math.max(i + 1, rows), Math.max(j + 1, columns), defaultValue);
-	      // update rows & columns
-	      rows = this._size[0];
-	      columns = this._size[1];
-	    }
-
-	    // check i, j are valid
-	    validateIndex(i, rows);
-	    validateIndex(j, columns);
-
-	    // find value index
-	    var k = _getValueIndex(i, this._ptr[j], this._ptr[j + 1], this._index);
-	    // check k is prior to next column k and it is in the correct row
-	    if (k < this._ptr[j + 1] && this._index[k] === i) {
-	      // check value != 0
-	      if (!math.equal(v, 0)) {
-	        // update value
-	        this._values[k] = v;
-	      }
-	      else {
-	        // remove value from matrix
-	        _remove(k, j, this._values, this._index, this._ptr);
-	      }
-	    }
-	    else {
-	      // insert value @ (i, j)
-	      _insert(k, i, j, v, this._values, this._index, this._ptr);
-	    }
-
-	    return this;
-	  };
-	  
-	  var _getValueIndex = function(i, top, bottom, index) {
-	    // check row is on the bottom side
-	    if (bottom - top === 0 || i > index[bottom - 1])
-	      return bottom;
-	    // loop until we find row index
-	    while (top < bottom) {
-	      // point in the middle (fast integer division)
-	      var p = ~~((top + bottom) / 2);
-	      // row @ p
-	      var r = index[p];
-	      // check we have to look on the top side, bottom side or we found the row
-	      if (i < r)
-	        bottom = p;
-	      else if (i > r)
-	        top = p + 1;
-	      else
-	        return p;
-	    }
-	    return top;
-	  };
-
-	  var _remove = function (k, j, values, index, ptr) {
-	    // remove value @ k
-	    values.splice(k, 1);
-	    index.splice(k, 1);
-	    // update pointers
-	    for (var x = j + 1; x < ptr.length; x++)
-	      ptr[x]--;
-	  };
-
-	  var _insert = function (k, i, j, v, values, index, ptr) {
-	    // insert value
-	    values.splice(k, 0, v);
-	    // update row for k
-	    index.splice(k, 0, i);
-	    // update column pointers
-	    for (var x = j + 1; x < ptr.length; x++)
-	      ptr[x]++;
-	  };
-	  
-	  /**
-	   * Resize the matrix to the given size. Returns a copy of the matrix when 
-	   * `copy=true`, otherwise return the matrix itself (resize in place).
-	   *
-	   * @param {Number[]} size           The new size the matrix should have.
-	   * @param {*} [defaultValue=0]      Default value, filled in on new entries.
-	   *                                  If not provided, the matrix elements will
-	   *                                  be filled with zeros.
-	   * @param {boolean} [copy]          Return a resized copy of the matrix
-	   *
-	   * @return {Matrix}                 The resized matrix
-	   */
-	  CcsMatrix.prototype.resize = function (size, defaultValue, copy) {    
-	    // validate arguments
-	    if (!isArray(size))
-	      throw new TypeError('Array expected');
-	    if (size.length !== 2)
-	      throw new Error('Only two dimensions matrix are supported');
-
-	    // check sizes
-	    size.forEach(function (value) {
-	      if (!number.isNumber(value) || !number.isInteger(value) || value < 0) {
-	        throw new TypeError('Invalid size, must contain positive integers ' +
-	                            '(size: ' + string.format(size) + ')');
-	      }
-	    });
-	    
-	    // matrix to resize
-	    var m = copy ? this.clone() : this;
-	    // resize matrix
-	    return _resize(m, size[0], size[1], defaultValue);
-	  };
-	  
-	  var _resize = function (matrix, rows, columns, defaultValue) {
-	    // value to insert at the time of growing matrix
-	    var value = defaultValue || 0;
-	    // should we insert the value?
-	    var ins = !math.equal(value, 0);
-
-	    // old columns and rows
-	    var r = matrix._size[0];
-	    var c = matrix._size[1];
-
-	    var i, j, k;
-
-	    // check we need to increase columns
-	    if (columns > c) {
-	      // loop new columns
-	      for (j = c; j < columns; j++) {
-	        // update matrix._ptr for current column
-	        matrix._ptr[j] = matrix._values.length;
-	        // check we need to insert matrix._values
-	        if (ins) {
-	          // loop rows
-	          for (i = 0; i < r; i++) {
-	            // add new matrix._values
-	            matrix._values.push(value);
-	            // update matrix._index
-	            matrix._index.push(i);
-	          }
-	        }        
-	      }
-	      // store number of matrix._values in matrix._ptr
-	      matrix._ptr[columns] = matrix._values.length;
-	    }
-	    else if (columns < c) {
-	      // truncate matrix._ptr
-	      matrix._ptr.splice(columns + 1, c - columns);
-	      // truncate matrix._values and matrix._index
-	      matrix._values.splice(matrix._ptr[columns], matrix._values.length);
-	      matrix._index.splice(matrix._ptr[columns], matrix._index.length);
-	    }
-	    // update columns
-	    c = columns;
-
-	    // check we need to increase rows
-	    if (rows > r) {
-	      // check we have to insert values
-	      if (ins) {
-	        // inserts
-	        var n = 0;
-	        // loop columns
-	        for (j = 0; j < c; j++) {
-	          // update matrix._ptr for current column
-	          matrix._ptr[j] = matrix._ptr[j] + n;
-	          // where to insert matrix._values
-	          k = matrix._ptr[j + 1] + n;
-	          // pointer
-	          var p = 0;
-	          // loop new rows, initialize pointer
-	          for (i = r; i < rows; i++, p++) {
-	            // add value
-	            matrix._values.splice(k + p, 0, value);
-	            // update matrix._index
-	            matrix._index.splice(k + p, 0, i);
-	            // increment inserts
-	            n++;
-	          }
-	        }
-	        // store number of matrix._values in matrix._ptr
-	        matrix._ptr[c] = matrix._values.length;
-	      }
-	    }
-	    else if (rows < r) {
-	      // deletes
-	      var d = 0;
-	      // loop columns
-	      for (j = 0; j < c; j++) {
-	        // update matrix._ptr for current column
-	        matrix._ptr[j] = matrix._ptr[j] - d;
-	        // where matrix._values start for next column
-	        var k0 = matrix._ptr[j];
-	        var k1 = matrix._ptr[j + 1] - d;
-	        // loop matrix._index
-	        for (k = k0; k < k1; k++) {
-	          // row
-	          i = matrix._index[k];
-	          // check we need to delete value and matrix._index
-	          if (i > rows - 1) {
-	            // remove value
-	            matrix._values.splice(k, 1);
-	            // remove item from matrix._index
-	            matrix._index.splice(k, 1);
-	            // increase deletes
-	            d++;
-	          }
-	        }
-	      }
-	      // update matrix._ptr for current column
-	      matrix._ptr[j] = matrix._values.length;
-	    }
-	    // update matrix._size
-	    matrix._size[0] = rows;
-	    matrix._size[1] = columns;
-	    // return matrix
-	    return matrix;
-	  };
-	  
-	  /**
-	   * Create a clone of the matrix
-	   * @return {CcsMatrix} clone
-	   */
-	  CcsMatrix.prototype.clone = function () {
-	    var m = new CcsMatrix({
-	      values: object.clone(this._values),
-	      index: object.clone(this._index),
-	      ptr: object.clone(this._ptr),
-	      size: object.clone(this._size)
-	    });
-	    return m;
-	  };
-	  
-	  /**
-	   * Retrieve the size of the matrix.
-	   * @returns {Number[]} size
-	   */
-	  CcsMatrix.prototype.size = function() {
-	    return object.clone(this._size);
-	  };
-	  
-	  /**
-	   * Create a new matrix with the results of the callback function executed on
-	   * each entry of the matrix.
-	   * @param {function} callback   The callback function is invoked with three
-	   *                              parameters: the value of the element, the index
-	   *                              of the element, and the Matrix being traversed.
-	   * @param {boolean} [skipZeros] Invoke callback function for non-zero values only.
-	   *
-	   * @return {CcsMatrix} matrix
-	   */
-	  CcsMatrix.prototype.map = function (callback, skipZeros) {
-	    // matrix instance
-	    var me = this;
-	    // rows and columns
-	    var rows = this._size[0];
-	    var columns = this._size[1];
-	    // invoke callback
-	    var invoke = function (v, i, j) {
-	      // invoke callback
-	      return callback(v, [i, j], me);
-	    };
-	    // invoke _map
-	    return _map(this, 0, rows - 1, 0, columns - 1, invoke, skipZeros);
-	  };
-
-	  /**
-	   * Create a new matrix with the results of the callback function executed on the interval
-	   * [minRow..maxRow, minColumn..maxColumn].
-	   */
-	  var _map = function (matrix, minRow, maxRow, minColumn, maxColumn, callback, skipZeros) {
-	    // result arrays
-	    var values = [];
-	    var index = [];
-	    var ptr = [];
-	    // invoke callback
-	    var invoke = function (v, x, y) {
-	      // invoke callback
-	      v = callback(v, x, y);
-	      // check value != 0
-	      if (!math.equal(v, 0)) {
-	        // store value
-	        values.push(v);
-	        // index
-	        index.push(x);
-	      }
-	    };
-	    // loop columns
-	    for (var j = minColumn; j <= maxColumn; j++) {
-	      // store pointer to values index
-	      ptr.push(values.length);
-	      // k0 <= k < k1 where k0 = _ptr[j] && k1 = _ptr[j+1]
-	      var k0 = matrix._ptr[j];
-	      var k1 = matrix._ptr[j + 1];
-	      // row pointer
-	      var p = minRow;
-	      // loop k within [k0, k1[
-	      for (var k = k0; k < k1; k++) {
-	        // row index
-	        var i = matrix._index[k];
-	        // check i is in range
-	        if (i >= minRow && i <= maxRow) {
-	          // zero values
-	          if (!skipZeros) {
-	           for (var x = p; x < i; x++)
-	             invoke(0, x - minRow, j - minColumn);
-	          }
-	          // value @ k
-	          invoke(matrix._values[k], i - minRow, j - minColumn);
-	        }
-	        // update pointer
-	        p = i + 1;
-	      }
-	      // zero values
-	      if (!skipZeros) {
-	        for (var y = p; y <= maxRow; y++)
-	          invoke(0, y - minRow, j - minColumn);
-	      }
-	    }
-	    // store number of values in ptr
-	    ptr.push(values.length);
-	    // return ccs
-	    return new CcsMatrix({
-	      values: values,
-	      index: index,
-	      ptr: ptr,
-	      size: [maxRow - minRow + 1, maxColumn - minColumn + 1]
-	    });
-	  };
-	  
-	  /**
-	   * Execute a callback function on each entry of the matrix.
-	   * @param {function} callback   The callback function is invoked with three
-	   *                              parameters: the value of the element, the index
-	   *                              of the element, and the Matrix being traversed.
-	   * @param {boolean} [skipZeros] Invoke callback function for non-zero values only.
-	   */
-	  CcsMatrix.prototype.forEach = function (callback, skipZeros) {
-	    // matrix instance
-	    var me = this;
-	    // rows and columns
-	    var rows = this._size[0];
-	    var columns = this._size[1];
-	    // loop columns
-	    for (var j = 0; j < columns; j++) {
-	      // k0 <= k < k1 where k0 = _ptr[j] && k1 = _ptr[j+1]
-	      var k0 = this._ptr[j];
-	      var k1 = this._ptr[j + 1];
-	      // column pointer
-	      var p = 0;
-	      // loop k within [k0, k1[
-	      for (var k = k0; k < k1; k++) {
-	        // row index
-	        var i = this._index[k];
-	        // check we need to process zeros
-	        if (!skipZeros) {
-	          // zero values
-	          for (var x = p; x < i; x++)
-	            callback(0, [x, j], me);
-	        }
-	        // value @ k
-	        callback(this._values[k], [i, j], me);
-	        // update pointer
-	        p = i + 1;
-	      }
-	      // check we need to process zeros
-	      if (!skipZeros) {
-	        // zero values
-	        for (var y = p; y < rows; y++)
-	          callback(0, [y, j], me);
-	      }
-	    }
-	  };
-	  
-	  /**
-	   * Create an Array with a copy of the data of the CcsMatrix
-	   * @returns {Array} array
-	   */
-	  CcsMatrix.prototype.toArray = function () {
-	    return _toArray(this, true);
-	  };
-
-	  /**
-	   * Get the primitive value of the CcsMatrix: a two dimensions array
-	   * @returns {Array} array
-	   */
-	  CcsMatrix.prototype.valueOf = function () {
-	    return _toArray(this, false);
-	  };
-	  
-	  var _toArray = function (matrix, copy) {
-	    // result
-	    var a = [];
-	    // rows and columns
-	    var rows = matrix._size[0];
-	    var columns = matrix._size[1];
-	    // loop columns
-	    for (var j = 0; j < columns; j++) {
-	      // k0 <= k < k1 where k0 = _ptr[j] && k1 = _ptr[j+1]
-	      var k0 = matrix._ptr[j];
-	      var k1 = matrix._ptr[j + 1];
-	      // row pointer
-	      var p = 0;
-	      // loop k within [k0, k1[
-	      for (var k = k0; k < k1; k++) {
-	        // row index
-	        var i = matrix._index[k];
-	        // zeros
-	        for (var x = p; x < i; x++)
-	          (a[x] = (a[x] || []))[j] = 0;
-	        // set value
-	        (a[i] = (a[i] || []))[j] = copy ? object.clone(matrix._values[k]) : matrix._values[k];
-	        // update pointer
-	        p = i + 1;
-	      }
-	      // zero values
-	      for (var y = p; y < rows; y++)
-	        (a[y] = (a[y] || []))[j] = 0;
-	    }
-	    return a;
-	  };
-	  
-	  /**
-	   * Get a string representation of the matrix, with optional formatting options.
-	   * @param {Object | Number | Function} [options]  Formatting options. See
-	   *                                                lib/util/number:format for a
-	   *                                                description of the available
-	   *                                                options.
-	   * @returns {String} str
-	   */
-	  CcsMatrix.prototype.format = function (options) {
-	    // rows and columns
-	    var rows = this._size[0];
-	    var columns = this._size[1];
-	    // rows & columns
-	    var str = 'CCS [' + string.format(rows, options) + ' x ' + string.format(columns, options) + '] density: ' + string.format(this._values.length / (rows * columns), options) + '\n';
-	    // loop columns
-	    for (var j = 0; j < columns; j++) {
-	      // k0 <= k < k1 where k0 = _ptr[j] && k1 = _ptr[j+1]
-	      var k0 = this._ptr[j];
-	      var k1 = this._ptr[j + 1];
-	      // loop k within [k0, k1[
-	      for (var k = k0; k < k1; k++) {
-	        // row index
-	        var i = this._index[k];
-	        // append value
-	        str += '\n    (' + string.format(i, options) + ', ' + string.format(j, options) + ') ==> ' + string.format(this._values[k], options);
-	      }
-	    }
-	    return str;
-	  };
-	  
-	  /**
-	   * Get a string representation of the matrix
-	   * @returns {String} str
-	   */
-	  CcsMatrix.prototype.toString = function () {
-	    return string.format(this.toArray());
-	  };
-	  
-	  /**
-	   * Get a JSON representation of the matrix
-	   * @returns {Object}
-	   */
-	  CcsMatrix.prototype.toJSON = function () {
-	    return {
-	      mathjs: 'CcsMatrix',
-	      values: this._values,
-	      index: this._index,
-	      ptr: this._ptr,
-	      size: this._size
-	    };
-	  };
-
-	  /**
-	   * Calculates the transpose of the matrix
-	   * @returns {Matrix}
-	   */
-	  CcsMatrix.prototype.transpose = function () {
-	    // rows and columns
-	    var rows = this._size[0];
-	    var columns = this._size[1];
-	    // check columns
-	    if (columns === 0) {
-	      // throw exception
-	      throw new RangeError('Cannot transpose a 2D matrix with no columns (size: ' + string.format(this._size) + ')');
-	    }
-	    // ccs transpose is a crs matrix with the same structure
-	    return new math.type.CrsMatrix({
-	      values: object.clone(this._values),
-	      index: object.clone(this._index),
-	      ptr: object.clone(this._ptr),
-	      size: [columns, rows]
-	    });
-	  };
-
-	  /**
-	   * Get the kth Matrix diagonal.
-	   *
-	   * @param {Number | BigNumber} [k=0]     The kth diagonal where the vector will retrieved.
-	   *
-	   * @returns {Array}                      The array vector with the diagonal values.
-	   */
-	  CcsMatrix.prototype.diagonal = function(k) {
-	    // validate k if any
-	    if (k) {
-	      // convert BigNumber to a number
-	      if (k instanceof BigNumber) 
-	        k = k.toNumber();
-	      // is must be an integer
-	      if (!isNumber(k) || !isInteger(k)) {
-	        throw new TypeError ('The parameter k must be an integer number');
-	      }
-	    }
-	    else {
-	      // default value
-	      k = 0;
-	    }
-
-	    var kSuper = k > 0 ? k : 0;
-	    var kSub = k < 0 ? -k : 0;
-	    
-	    // rows & columns
-	    var rows = this._size[0];
-	    var columns = this._size[1];
-	    
-	    // number diagonal values
-	    var n = Math.min(rows - kSub, columns -  kSuper);
-	    
-	    // diagonal
-	    var values = [];
-	    // loop columns
-	    for (var j = kSuper; j < columns && values.length < n; j++) {
-	      // k0 <= k < k1 where k0 = _ptr[j] && k1 = _ptr[j+1]
-	      var k0 = this._ptr[j];
-	      var k1 = this._ptr[j + 1];
-	      // column value flag
-	      var cv = false;
-	      // loop x within [k0, k1[
-	      for (var x = k0; x < k1; x++) {
-	        // row index
-	        var i = this._index[x];
-	        // check row
-	        if (i === j - kSuper + kSub) {
-	          // set flag
-	          cv = true;
-	          // value on this column
-	          values.push(object.clone(this._values[x]));
-	          // exit loop
-	          break;
-	        }
-	        else if (i > j - kSuper + kSub) {
-	          // exit loop, no value on the diagonal for column j
-	          break;
-	        }
-	      }
-	      // check this column has a value set
-	      if (!cv && values.length < n) {
-	        // zero on this column
-	        values.push(0);
-	      }
-	    }
-	    return values;
-	  };
-	  
-	  /**
-	   * Generate a matrix from a JSON object
-	   * @param {Object} json  An object structured like
-	   *                       `{"mathjs": "CcsMatrix", "values": [], "index": [], "ptr": [], "size": []}`,
-	   *                       where mathjs is optional
-	   * @returns {CcsMatrix}
-	   */
-	  CcsMatrix.fromJSON = function (json) {
-	    return new CcsMatrix(json);
-	  };
-
-	  /**
-	   * Create a diagonal matrix.
-	   *
-	   * @param {Array} size                   The matrix size.
-	   * @param {Number, Array} value          The values for the diagonal.
-	   * @param {Number | BigNumber} [k=0]     The kth diagonal where the vector will be filled in.
-	   *
-	   * @returns {CcsMatrix}
-	   */
-	  CcsMatrix.diagonal = function (size, value, k) {
-	    if (!isArray(size))
-	      throw new TypeError('Array expected, size parameter');
-	    if (size.length !== 2)
-	      throw new Error('Only two dimensions matrix are supported');
-	    
-	    // map size & validate
-	    size = size.map(function (s) {
-	      // check it is a big number
-	      if (s instanceof BigNumber) {
-	        // convert it
-	        s = s.toNumber();
-	      }
-	      // validate arguments
-	      if (!isNumber(s) || !isInteger(s) || s < 1) {
-	        throw new Error('Size values must be positive integers');
-	      } 
-	      return s;
-	    });
-	    
-	    // validate k if any
-	    if (k) {
-	      // convert BigNumber to a number
-	      if (k instanceof BigNumber) 
-	        k = k.toNumber();
-	      // is must be an integer
-	      if (!isNumber(k) || !isInteger(k)) {
-	        throw new TypeError ('The parameter k must be an integer number');
-	      }
-	    }
-	    else {
-	      // default value
-	      k = 0;
-	    }
-
-	    var kSuper = k > 0 ? k : 0;
-	    var kSub = k < 0 ? -k : 0;
-	    
-	    // rows and columns
-	    var rows = size[0];
-	    var columns = size[1];
-	    
-	    // number of non-zero items
-	    var n = Math.min(rows - kSub, columns -  kSuper);
-	    
-	    // value extraction function
-	    var _value;
-	      
-	    // check value
-	    if (isArray(value)) {
-	      // validate array
-	      if (value.length !== n) {
-	        // number of values in array must be n
-	        throw new Error('Invalid value array length');
-	      }
-	      // define function
-	      _value = function (i) {
-	        // return value @ i
-	        return value[i];
-	      };
-	    }
-	    else {
-	      // define function
-	      _value = function () {
-	        // return value
-	        return value;
-	      };
-	    }
-	    
-	    // create arrays
-	    var values = [];
-	    var index = [];
-	    var ptr = [];
-	    
-	    // loop items
-	    for (var j = 0; j < columns; j++) {
-	      // number of rows with value
-	      ptr.push(values.length);
-	      // diagonal index
-	      var i = j - kSuper;      
-	      // check we need to set diagonal value
-	      if (i >= 0 && i < n) {
-	        // get value @ i
-	        var v = _value(i);
-	        // check for zero
-	        if (!math.equal(v, 0)) {
-	          // column
-	          index.push(i + kSub);
-	          // add value
-	          values.push(v);
-	        }
-	      }
-	    }
-	    // last value should be number of values
-	    ptr.push(values.length);
-	    // create CcsMatrix
-	    return new CcsMatrix({
-	      values: values,
-	      index: index,
-	      ptr: ptr,
-	      size: [rows, columns]
-	    });
-	  };
-	  
-	  /**
-	   * Calculate the trace of a matrix: the sum of the elements on the main
-	   * diagonal of a square matrix.
-	   *
-	   * See also:
-	   *
-	   *    diagonal
-	   *
-	   * @returns {Number}       The matrix trace
-	   */
-	  CcsMatrix.prototype.trace = function () {
-	    // size
-	    var size = this._size;
-	    // check dimensions
-	    var rows = size[0];
-	    var columns = size[1];
-	    // matrix must be square
-	    if (rows === columns) {
-	      // calulate sum
-	      var sum = 0;
-	      // check we have data (avoid looping columns)
-	      if (this._values.length > 0) {
-	        // loop columns
-	        for (var j = 0; j < columns; j++) {
-	          // k0 <= k < k1 where k0 = _ptr[j] && k1 = _ptr[j+1]
-	          var k0 = this._ptr[j];
-	          var k1 = this._ptr[j + 1];
-	          // loop k within [k0, k1[
-	          for (var k = k0; k < k1; k++) {
-	            // row index
-	            var i = this._index[k];
-	            // check row
-	            if (i === j) {
-	              // accumulate value
-	              sum = math.add(sum, this._values[k]);
-	              // exit loop
-	              break;
-	            }
-	            if (i > j) {
-	              // exit loop, no value on the diagonal for column j
-	              break;
-	            }
-	          }
-	        }
-	      }
-	      // return trace
-	      return sum;
-	    }
-	    throw new RangeError('Matrix must be square (size: ' + string.format(size) + ')');        
-	  };
-	  
-	  /**
-	   * Multiply the matrix values times the argument.
-	   *
-	   * @param  {Number | BigNumber | Boolean | Complex | Unit | Array | Matrix | null} Value to multiply.
-	   *
-	   * @return {Number | BigNumber | Complex | Unit | Matrix}
-	   */
-	  CcsMatrix.prototype.multiply = function (value) {
-	    // check dimensions
-	    var rows = this._size[0];
-	    var columns = this._size[1];
-	    
-	    // check value is a matrix
-	    if (value instanceof Matrix) {
-	      // matrix size
-	      var z = value.size();
-	      // check value is a vector
-	      if (z.length === 1) {
-	        // mutiply matrix x vector array
-	        return _multiply(this, z[0], 1, function (i) {
-	          // value[i]
-	          return value.get([i]);
-	        });
-	      }
-	      // check two dimensions matrix
-	      if (z.length === 2) {        
-	        // mutiply matrix x matrix
-	        return _multiply(this, z[0], z[1], function (i, j) {
-	          // value[i, j]
-	          return value.get([i, j]);
-	        });
-	      }
-	      throw new Error('Can only multiply a 1 or 2 dimensional matrix ' +
-	                      '(value has ' + z.length + ' dimensions)');
-	    }
-
-	    // check value is an array
-	    if (isArray(value)) {
-	      // array size
-	      var s = array.size(value);
-	      // check value is a vector
-	      if (s.length === 1) {
-	        // mutiply matrix x vector array
-	        return _multiply(this, s[0], 1, function (i) {
-	          // value[i]
-	          return value[i];
-	        });
-	      }
-	      if (s.length === 2) {
-	        // mutiply matrix x array
-	        return _multiply(this, s[0], s[1], function (i, j) {
-	          // value[i, j]
-	          return value[i][j];
-	        });
-	      }
-	      throw new Error('Can only multiply a 1 or 2 dimensional matrix ' +
-	                      '(value has ' + s.length + ' dimensions)');
-	    }
-	    
-	    var callback = function (v) {
-	      return math.multiply(v, value);
-	    };
-
-	    // map non zero elements
-	    return _map(this, 0, rows - 1, 0, columns - 1, callback, false);
-	  };
-
-	  var _multiply = function (matrix, r, c, get) {
-	  
-	    // matrix dimensions
-	    var rows = matrix._size[0];
-	    var columns = matrix._size[1];
-	    
-	    // check dimensions match
-	    if (columns !== r) {
-	      // throw error
-	      throw new RangeError('Dimension mismatch in multiplication. ' +
-	                           'Columns of A must match length of B ' +
-	                           '(A is ' + rows + 'x' + columns +
-	                           ', B is ' + r + ', ' +
-	                           columns + ' != ' + r + ')');
-	    }
-	    
-	    // result arrays
-	    var values = [];
-	    var index = [];
-	    var ptr = [];
-
-	    // create array with rows entries
-	    var data = [];
-	    for (var x = 0; x < rows; x++)
-	      data[x] = 0;
-	    // loop value columns
-	    for (var z = 0; z < c; z++) {
-	      // update ptr
-	      ptr.push(values.length);
-	      // do not traverse rows in matrix, it is not efficient in CCS
-	      for (var j = 0; j < columns; j++) {          
-	        // k0 <= k < k1 where k0 = _ptr[j] && k1 = _ptr[j+1]
-	        var k0 = matrix._ptr[j];
-	        var k1 = matrix._ptr[j + 1];
-	        // loop k within [k0, k1[
-	        for (var k = k0; k < k1; k++) {
-	          // row
-	          var i = matrix._index[k];
-	          // multiply & aggregate
-	          data[i] = math.add(data[i], math.multiply(matrix._values[k], get(j, z)));
-	        }          
-	      }
-	      // finished processing column z, compress results
-	      for (var y = 0; y < rows; y++) {
-	        // check value is different than zero
-	        if (!math.equal(data[y], 0)) {
-	          // push value
-	          values.push(data[y]);
-	          index.push(y);          
-	        }
-	        // reset value
-	        data[y] = 0;
-	      }
-	    }
-	    // update ptr
-	    ptr.push(values.length);
-	    
-	    // check we need to squeeze the result into a scalar
-	    if (rows === 1 && c === 1)
-	      return values.length === 1 ? values[0] : 0;
-	    
-	    // return CCS matrix
-	    return new CcsMatrix({
-	      values: values,
-	      index: index,
-	      ptr: ptr,
-	      size: [rows, c]
-	    });
-	  };
-	  
-	  return CcsMatrix;
-	};
+	module.exports = [
+	  __webpack_require__(16),
+	  __webpack_require__(24),
+	  __webpack_require__(43),
+	  __webpack_require__(46),
+	  __webpack_require__(47),
+	  __webpack_require__(48),
+	  __webpack_require__(49),
+	  __webpack_require__(50),
+	  __webpack_require__(52),
+	  __webpack_require__(53),
+	  __webpack_require__(54),
+	  __webpack_require__(55),
+	  __webpack_require__(56),
+	  __webpack_require__(57),
+	  __webpack_require__(58),
+	  __webpack_require__(59),
+	  __webpack_require__(60)
+	];
+
 
 /***/ },
 /* 16 */
@@ -4996,2262 +2977,204 @@
 
 	'use strict';
 
-	var util = __webpack_require__(175);
-	var DimensionError = __webpack_require__(172);
-
-	var array = util.array;
-	var object = util.object;
-	var string = util.string;
-	var number = util.number;
-
-	var isArray = Array.isArray;
-	var isNumber = util.number.isNumber;
-	var isInteger = util.number.isInteger;
-
-	var validateIndex = array.validateIndex;
-
-	module.exports = function (math) {
-
-	  var Index = math.type.Index,
-	      BigNumber = math.type.BigNumber,
-	      Matrix = math.type.Matrix;
-
-	  function CrsMatrix(data) {
-	    if (!(this instanceof CrsMatrix))
-	      throw new SyntaxError('Constructor must be called with the new operator');
-
-	    if (data instanceof Matrix) {
-	      // check data is a CrsMatrix
-	      if (data.type === 'CrsMatrix') {
-	        // clone arrays
-	        this._values = object.clone(data._values);
-	        this._index = object.clone(data._index);
-	        this._ptr = object.clone(data._ptr);
-	        this._size = object.clone(data._size);
-	      }
-	      else {
-	        // build from matrix data
-	        _createFromArray(this, data.valueOf());
-	      }
-	    }
-	    else if (data && isArray(data.values) && isArray(data.index) && isArray(data.ptr) && isArray(data.size)) {
-	      // initialize fields
-	      this._values = data.values;
-	      this._index = data.index;
-	      this._ptr = data.ptr;
-	      this._size = data.size;
-	    }
-	    else if (isArray(data)) {
-	      // create from array
-	      _createFromArray(this, data);
-	    }
-	    else if (data) {
-	      // unsupported type
-	      throw new TypeError('Unsupported type of data (' + util.types.type(data) + ')');
-	    }
-	    else {
-	      // nothing provided
-	      this._values = [];
-	      this._index = [];
-	      this._ptr = [0];
-	      this._size = [0];
-	    }
-	  }
-
-	  var _createFromArray = function (matrix, data) {
-	    // initialize fields
-	    matrix._values = [];
-	    matrix._index = [];
-	    matrix._ptr = [];
-	    // discover rows & columns, do not use math.size() to avoid looping array twice
-	    var rows = data.length;
-	    var columns = 0;
-
-	    // loop rows
-	    for (var i = 0; i < rows; i++) {
-	      // store value index in ptr
-	      matrix._ptr.push(matrix._values.length);
-	      // current row
-	      var row = data[i];      
-	      // check row is an array
-	      if (isArray(row)) {
-	        // update columns if needed
-	        if (row.length > columns)
-	          columns = row.length;
-	        // loop columns
-	        for (var j = 0; j < row.length; j++) {
-	          // value at data[i][j]
-	          var v = row[j];
-	          // check value != 0
-	          if (!math.equal(v, 0)) {
-	            // store value
-	            matrix._values.push(v);
-	            // add column index
-	            matrix._index.push(j);
-	          }
-	        }
-	      }
-	      else {
-	        // update columns if needed (only on first row)
-	        if (i === 0 && columns < 1)
-	          columns = 1;
-	        // check value != 0 (row is a scalar)
-	        if (!math.equal(row, 0)) {
-	          // store value
-	          matrix._values.push(row);
-	          // index
-	          matrix._index.push(0);
-	        }
-	      }
-	    }
-	    // store number of values in ptr
-	    matrix._ptr.push(matrix._values.length);
-	    // size
-	    matrix._size = [rows, columns];
-	  };
-
-	  CrsMatrix.prototype = new math.type.Matrix();
-
-	  CrsMatrix.prototype.type = 'CrsMatrix';
-
-	  /**
-	   * Get the storage format used by the matrix.
-	   *
-	   * Usage:
-	   *     var format = matrix.storage()                   // retrieve storage format
-	   *
-	   * @return {string}           The storage format.
-	   */
-	  CrsMatrix.prototype.storage = function () {
-	    return 'crs';
-	  };
-
-	  /**
-	   * Get a subset of the matrix, or replace a subset of the matrix.
-	   *
-	   * Usage:
-	   *     var subset = matrix.subset(index)               // retrieve subset
-	   *     var value = matrix.subset(index, replacement)   // replace subset
-	   *
-	   * @param {Index} index
-	   * @param {Array | Maytrix | *} [replacement]
-	   * @param {*} [defaultValue=0]      Default value, filled in on new entries when
-	   *                                  the matrix is resized. If not provided,
-	   *                                  new matrix elements will be filled with zeros.
-	   */
-	  CrsMatrix.prototype.subset = function (index, replacement, defaultValue) {
-	    // check arguments
-	    switch (arguments.length) {
-	      case 1:
-	        return _getsubset(this, index);
-
-	        // intentional fall through
-	      case 2:
-	      case 3:
-	        return _setsubset(this, index, replacement, defaultValue);
-
-	      default:
-	        throw new SyntaxError('Wrong number of arguments');
-	    }
-	  };
-
-	  var _getsubset = function (matrix, index) {
-	    // check index
-	    if (!(index instanceof Index)) {
-	      throw new TypeError('Invalid index');
-	    }
-
-	    var isScalar = index.isScalar();
-	    if (isScalar) {
-	      // return a scalar
-	      return matrix.get(index.min());
-	    }
-	    // validate dimensions
-	    var size = index.size();
-	    if (size.length != matrix._size.length) {
-	      throw new DimensionError(size.length, matrix._size.length);
-	    }
-
-	    // validate if any of the ranges in the index is out of range
-	    var min = index.min();
-	    var max = index.max();
-	    for (var i = 0, ii = matrix._size.length; i < ii; i++) {
-	      validateIndex(min[i], matrix._size[i]);
-	      validateIndex(max[i], matrix._size[i]);
-	    }
-
-	    // map callback
-	    var callback = function (v) {
-	      // return value
-	      return v;
-	    };
-	    // get sub-matrix
-	    return _map(matrix, min[0], max[0], min[1], max[1], callback, false);
-	  };
-
-	  var _setsubset = function (matrix, index, submatrix, defaultValue) {
-	    // check index
-	    if (!(index instanceof Index)) {
-	      throw new TypeError('Invalid index');
-	    }
-
-	    // get index size and check whether the index contains a single value
-	    var iSize = index.size(),
-	        isScalar = index.isScalar();
-
-	    // calculate the size of the submatrix, and convert it into an Array if needed
-	    var sSize;
-	    if (submatrix instanceof Matrix) {
-	      // submatrix size
-	      sSize = submatrix.size();
-	      // use array representation
-	      submatrix = submatrix.toArray();
-	    }
-	    else {
-	      // get submatrix size (array, scalar)
-	      sSize = array.size(submatrix);
-	    }
-
-	    // check index is a scalar
-	    if (isScalar) {
-	      // verify submatrix is a scalar
-	      if (sSize.length !== 0) {
-	        throw new TypeError('Scalar expected');
-	      }
-	      // set value
-	      matrix.set(index.min(), submatrix, defaultValue);
-	    }
-	    else {
-	      // validate dimensions, index size must be one or two dimensions
-	      if (iSize.length !== 1 && iSize.length !== 2) {
-	        throw new DimensionError(iSize.length, matrix._size.length, '<');
-	      }
-
-	      // check submatrix and index have the same dimensions
-	      if (sSize.length < iSize.length) {
-	        // calculate number of missing outer dimensions
-	        var i = 0;
-	        var outer = 0;
-	        while (iSize[i] === 1 && sSize[i] === 1) {
-	          i++;
-	        }
-	        while (iSize[i] === 1) {
-	          outer++;
-	          i++;
-	        }
-	        // unsqueeze both outer and inner dimensions
-	        submatrix = array.unsqueeze(submatrix, iSize.length, outer, sSize);
-	      }
-
-	      // check whether the size of the submatrix matches the index size
-	      if (!object.deepEqual(iSize, sSize)) {
-	        throw new DimensionError(iSize, sSize, '>');
-	      }
-
-	      // offsets
-	      var x0 = index.min()[0];
-	      var y0 = index.min()[1];      
-
-	      // submatrix rows and columns
-	      var m = sSize[0];
-	      var n = sSize[1];
-
-	      // loop submatrix
-	      for (var x = 0; x < m; x++) {
-	        // loop columns
-	        for (var y = 0; y < n; y++) {
-	          // value at i, j
-	          var v = submatrix[x][y];
-	          // invoke set (zero value will remove entry from matrix)
-	          matrix.set([x + x0, y + y0], v, defaultValue);
-	        }
-	      }
-	    }
-	    return matrix;
-	  };
-
-	  /**
-	   * Get a single element from the matrix.
-	   * @param {Number[]} index   Zero-based index
-	   * @return {*} value
-	   */
-	  CrsMatrix.prototype.get = function (index) {
-	    if (!isArray(index))
-	      throw new TypeError('Array expected');
-	    if (index.length != this._size.length)
-	      throw new DimensionError(index.length, this._size.length);
-
-	    // row and column
-	    var i = index[0];
-	    var j = index[1];
-
-	    // check i, j are valid
-	    validateIndex(i, this._size[0]);
-	    validateIndex(j, this._size[1]);
-
-	    // find value index
-	    var k = _getValueIndex(j, this._ptr[i], this._ptr[i + 1], this._index);
-	    // check k is prior to next row k and it is in the correct row
-	    if (k < this._ptr[i + 1] && this._index[k] === j)
-	      return object.clone(this._values[k]);
-
-	    return 0;
-	  };
-
-	  /**
-	   * Replace a single element in the matrix.
-	   * @param {Number[]} index   Zero-based index
-	   * @param {*} value
-	   * @param {*} [defaultValue]        Default value, filled in on new entries when
-	   *                                  the matrix is resized. If not provided,
-	   *                                  new matrix elements will be set to zero.
-	   * @return {CrsMatrix} self
-	   */
-	  CrsMatrix.prototype.set = function (index, v, defaultValue) {
-	    if (!isArray(index))
-	      throw new TypeError('Array expected');
-	    if (index.length != this._size.length)
-	      throw new DimensionError(index.length, this._size.length);
-
-	    // row and column
-	    var i = index[0];
-	    var j = index[1];
-
-	    // rows & columns
-	    var rows = this._size[0];
-	    var columns = this._size[1];
-
-	    // check we need to resize matrix
-	    if (i > rows - 1 || j > columns - 1) {
-	      // resize matrix
-	      _resize(this, Math.max(i + 1, rows), Math.max(j + 1, columns), defaultValue);
-	      // update rows & columns
-	      rows = this._size[0];
-	      columns = this._size[1];
-	    }
-
-	    // check i, j are valid
-	    validateIndex(i, rows);
-	    validateIndex(j, columns);
-
-	    // find value index
-	    var k = _getValueIndex(j, this._ptr[i], this._ptr[i + 1], this._index);
-	    // check k is prior to next row k and it is in the correct column
-	    if (k < this._ptr[i + 1] && this._index[k] === j) {
-	      // check value != 0
-	      if (!math.equal(v, 0)) {
-	        // update value
-	        this._values[k] = v;
-	      }
-	      else {
-	        // remove value from matrix
-	        _remove(k, i, this._values, this._index, this._ptr);
-	      }
-	    }
-	    else {
-	      // insert value @ (i, j)
-	      _insert(k, i, j, v, this._values, this._index, this._ptr);
-	    }
-
-	    return this;
-	  };
-
-	  var _getValueIndex = function(j, left, right, index) {
-	    // check column is on the right side
-	    if (right - left === 0 || j > index[right - 1])
-	      return right;
-	    // loop until we find row index
-	    while (left < right) {
-	      // point in the middle (fast integer division)
-	      var p = ~~((left + right) / 2);
-	      // column @ p
-	      var c = index[p];
-	      // check we have to look on the left side, right side or we found the column
-	      if (j < c)
-	        right = p;
-	      else if (j > c)
-	        left = p + 1;
-	      else
-	        return p;
-	    }
-	    return left;
-	  };
-
-	  var _remove = function (k, i, values, index, ptr) {
-	    // remove value @ k
-	    values.splice(k, 1);
-	    index.splice(k, 1);
-	    // update pointers
-	    for (var x = i + 1; x < ptr.length; x++)
-	      ptr[x]--;
-	  };
-
-	  var _insert = function (k, i, j, v, values, index, ptr) {
-	    // insert value
-	    values.splice(k, 0, v);
-	    // update column for k
-	    index.splice(k, 0, j);
-	    // update row pointers
-	    for (var x = i + 1; x < ptr.length; x++)
-	      ptr[x]++;
-	  };
-
-	  /**
-	   * Resize the matrix to the given size. Returns a copy of the matrix when 
-	   * `copy=true`, otherwise return the matrix itself (resize in place).
-	   *
-	   * @param {Number[]} size           The new size the matrix should have.
-	   * @param {*} [defaultValue=0]      Default value, filled in on new entries.
-	   *                                  If not provided, the matrix elements will
-	   *                                  be filled with zeros.
-	   * @param {boolean} [copy]          Return a resized copy of the matrix
-	   *
-	   * @return {Matrix}                 The resized matrix
-	   */
-	  CrsMatrix.prototype.resize = function (size, defaultValue, copy) {    
-	    // validate arguments
-	    if (!isArray(size))
-	      throw new TypeError('Array expected');
-	    if (size.length !== 2)
-	      throw new Error('Only two dimensions matrix are supported');
-
-	    // check sizes
-	    size.forEach(function (value) {
-	      if (!number.isNumber(value) || !number.isInteger(value) || value < 0) {
-	        throw new TypeError('Invalid size, must contain positive integers ' +
-	                            '(size: ' + string.format(size) + ')');
-	      }
-	    });
-
-	    // matrix to resize
-	    var m = copy ? this.clone() : this;
-	    // resize matrix
-	    return _resize(m, size[0], size[1], defaultValue);
-	  };
-
-	  var _resize = function (matrix, rows, columns, defaultValue) {
-	    // value to insert at the time of growing matrix
-	    var value = defaultValue || 0;
-	    // should we insert the value?
-	    var ins = !math.equal(value, 0);
-
-	    // old columns and rows
-	    var r = matrix._size[0];
-	    var c = matrix._size[1];
-
-	    var i, j, k;
-
-	    // check we need to increase rows
-	    if (rows > r) {
-	      // loop new rows
-	      for (i = r; i < rows; i++) {
-	        // update matrix._ptr for current column
-	        matrix._ptr[i] = matrix._values.length;
-	        // check we need to insert matrix._values
-	        if (ins) {
-	          // loop columns
-	          for (j = 0; j < c; j++) {
-	            // add new matrix._values
-	            matrix._values.push(value);
-	            // update matrix._index
-	            matrix._index.push(j);
-	          }
-	        }        
-	      }
-	      // store number of matrix._values in matrix._ptr
-	      matrix._ptr[rows] = matrix._values.length;
-	    }
-	    else if (rows < r) {
-	      // truncate matrix._ptr
-	      matrix._ptr.splice(rows + 1, r - rows);
-	      // truncate matrix._values and matrix._index
-	      matrix._values.splice(matrix._ptr[rows], matrix._values.length);
-	      matrix._index.splice(matrix._ptr[rows], matrix._index.length);
-	    }
-	    // update rows
-	    r = rows;
-
-	    // check we need to increase columns
-	    if (columns > c) {
-	      // check we have to insert values
-	      if (ins) {
-	        // inserts
-	        var n = 0;
-	        // loop rows
-	        for (i = 0; i < r; i++) {
-	          // update matrix._ptr for current row
-	          matrix._ptr[i] = matrix._ptr[i] + n;
-	          // where to insert matrix._values
-	          k = matrix._ptr[i + 1] + n;
-	          // pointer
-	          var p = 0;
-	          // loop new columns, initialize pointer
-	          for (j = c; j < columns; j++, p++) {
-	            // add value
-	            matrix._values.splice(k + p, 0, value);
-	            // update matrix._index
-	            matrix._index.splice(k + p, 0, j);
-	            // increment inserts
-	            n++;
-	          }
-	        }
-	        // store number of matrix._values in matrix._ptr
-	        matrix._ptr[r] = matrix._values.length;
-	      }
-	    }
-	    else if (columns < c) {
-	      // deletes
-	      var d = 0;
-	      // loop rows
-	      for (i = 0; i < r; i++) {
-	        // update matrix._ptr for current row
-	        matrix._ptr[i] = matrix._ptr[i] - d;
-	        // where matrix._values start for next column
-	        var k0 = matrix._ptr[i];
-	        var k1 = matrix._ptr[i + 1] - d;
-	        // loop matrix._index
-	        for (k = k0; k < k1; k++) {
-	          // column
-	          j = matrix._index[k];
-	          // check we need to delete value and matrix._index
-	          if (j > columns - 1) {
-	            // remove value
-	            matrix._values.splice(k, 1);
-	            // remove item from matrix._index
-	            matrix._index.splice(k, 1);
-	            // increase deletes
-	            d++;
-	          }
-	        }
-	      }
-	      // update matrix._ptr for current column
-	      matrix._ptr[i] = matrix._values.length;
-	    }
-	    // update matrix._size
-	    matrix._size[0] = rows;
-	    matrix._size[1] = columns;
-	    // return matrix
-	    return matrix;
-	  };
-
-	  /**
-	   * Create a clone of the matrix
-	   * @return {CrsMatrix} clone
-	   */
-	  CrsMatrix.prototype.clone = function () {
-	    var m = new CrsMatrix({
-	      values: object.clone(this._values),
-	      index: object.clone(this._index),
-	      ptr: object.clone(this._ptr),
-	      size: object.clone(this._size)
-	    });
-	    return m;
-	  };
-
-	  /**
-	   * Retrieve the size of the matrix.
-	   * @returns {Number[]} size
-	   */
-	  CrsMatrix.prototype.size = function() {
-	    return object.clone(this._size);
-	  };
-
-	  /**
-	   * Create a new matrix with the results of the callback function executed on
-	   * each entry of the matrix.
-	   * @param {function} callback   The callback function is invoked with three
-	   *                              parameters: the value of the element, the index
-	   *                              of the element, and the Matrix being traversed.
-	   * @param {boolean} [skipZeros] Invoke callback function for non-zero values only.
-	   *
-	   * @return {Matrix} matrix
-	   */
-	  CrsMatrix.prototype.map = function (callback, skipZeros) {
-	    // matrix instance
-	    var me = this;
-	    // rows and columns
-	    var rows = this._size[0];
-	    var columns = this._size[1];
-	    // invoke callback
-	    var invoke = function (v, i, j) {
-	      // invoke callback
-	      return callback(v, [i, j], me);
-	    };
-	    // invoke _map
-	    return _map(this, 0, rows - 1, 0, columns - 1, invoke, skipZeros);
-	  };
-
-	  /**
-	   * Create a new matrix with the results of the callback function executed on the interval
-	   * [minRow..maxRow, minColumn..maxColumn].
-	   */
-	  var _map = function (matrix, minRow, maxRow, minColumn, maxColumn, callback, skipZeros) {
-	    // result arrays
-	    var values = [];
-	    var index = [];
-	    var ptr = [];
-	    // invoke callback
-	    var invoke = function (v, x, y) {
-	      // invoke callback
-	      v = callback(v, x, y);
-	      // check value != 0
-	      if (!math.equal(v, 0)) {
-	        // store value
-	        values.push(v);
-	        // index
-	        index.push(y);
-	      }
-	    };
-	    // loop rows
-	    for (var i = minRow; i <= maxRow; i++) {
-	      // store pointer to values index
-	      ptr.push(values.length);
-	      // k0 <= k < k1 where k0 = _ptr[j] && k1 = _ptr[j+1]
-	      var k0 = matrix._ptr[i];
-	      var k1 = matrix._ptr[i + 1];
-	      // column pointer
-	      var p = minColumn;
-	      // loop k within [k0, k1[
-	      for (var k = k0; k < k1; k++) {
-	        // column index
-	        var j = matrix._index[k];
-	        // check j is in range
-	        if (j >= minColumn && j <= maxColumn) {
-	          // zero values
-	          if (!skipZeros) {
-	            // write zeros from column p to j
-	            for (var x = p; x < j; x++)
-	              invoke(0, i - minRow, x - minColumn);
-	          }
-	          // value @ k
-	          invoke(matrix._values[k], i - minRow, j - minColumn);
-	        }
-	        // update pointer
-	        p = j + 1;
-	      }
-	      // zero values
-	      if (!skipZeros) {
-	        // write zeros from column p to maxColumn
-	        for (var y = p; y <= maxColumn; y++)
-	          invoke(0, i - minRow, y - minColumn);
-	      }
-	    }
-	    // store number of values in ptr
-	    ptr.push(values.length);
-	    // return ccs
-	    return new CrsMatrix({
-	      values: values,
-	      index: index,
-	      ptr: ptr,
-	      size: [maxRow - minRow + 1, maxColumn - minColumn + 1]
-	    });
-	  };
-
-	  /**
-	   * Execute a callback function on each entry of the matrix.
-	   * @param {function} callback   The callback function is invoked with three
-	   *                              parameters: the value of the element, the index
-	   *                              of the element, and the Matrix being traversed.
-	   * @param {boolean} [skipZeros] Invoke callback function for non-zero values only.
-	   */
-	  CrsMatrix.prototype.forEach = function (callback, skipZeros) {
-	    // matrix instance
-	    var me = this;
-	    // rows and columns
-	    var rows = this._size[0];
-	    var columns = this._size[1];
-	    // loop rows
-	    for (var i = 0; i < rows; i++) {
-	      // k0 <= k < k1 where k0 = _ptr[i] && k1 = _ptr[i+1]
-	      var k0 = this._ptr[i];
-	      var k1 = this._ptr[i + 1];
-	      // column pointer
-	      var p = 0;
-	      // loop k within [k0, k1[
-	      for (var k = k0; k < k1; k++) {
-	        // column index
-	        var j = this._index[k];
-	        // check we need to process zeros
-	        if (!skipZeros) {
-	          // zero values
-	          for (var x = p; x < j; x++)
-	            callback(0, [i, x], me);
-	        }
-	        // value @ k
-	        callback(this._values[k], [i, j], me);
-	        // update pointer
-	        p = j + 1;
-	      }
-	      // check we need to process zeros
-	      if (!skipZeros) {
-	        // zero values
-	        for (var y = p; y < columns; y++)
-	          callback(0, [i, y], me);
-	      }
-	    }
-	  };
-
-	  /**
-	   * Create an Array with a copy of the data of the CrsMatrix
-	   * @returns {Array} array
-	   */
-	  CrsMatrix.prototype.toArray = function () {
-	    return _toArray(this, true);
-	  };
-
-	  /**
-	   * Get the primitive value of the CrsMatrix: a two dimensions array
-	   * @returns {Array} array
-	   */
-	  CrsMatrix.prototype.valueOf = function () {
-	    return _toArray(this, false);
-	  };
-
-	  var _toArray = function (matrix, copy) {
-	    // result
-	    var a = [];
-	    // rows and columns
-	    var rows = matrix._size[0];
-	    var columns = matrix._size[1];
-	    // loop rows
-	    for (var i = 0; i < rows; i++) {
-	      // push row
-	      var r = a[i] = [];
-	      // k0 <= k < k1 where k0 = _ptr[i] && k1 = _ptr[i+1]
-	      var k0 = matrix._ptr[i];
-	      var k1 = matrix._ptr[i + 1];
-	      // column pointer
-	      var p = 0;
-	      // loop k is within [k0, k1[
-	      for (var k = k0; k < k1; k++) {
-	        // column index
-	        var j = matrix._index[k];
-	        // zero values
-	        for (var x = p; x < j; x++)
-	          r[x] = 0;
-	        // set value
-	        r[j] = copy ? object.clone(matrix._values[k]) : matrix._values[k];
-	        // update pointer
-	        p = j + 1;
-	      }
-	      // zero values
-	      for (var y = p; y < columns; y++)
-	        r[y] = 0;
-	    }
-	    return a;
-	  };
-
-	  /**
-	   * Get a string representation of the matrix, with optional formatting options.
-	   * @param {Object | Number | Function} [options]  Formatting options. See
-	   *                                                lib/util/number:format for a
-	   *                                                description of the available
-	   *                                                options.
-	   * @returns {String} str
-	   */
-	  CrsMatrix.prototype.format = function (options) {
-	    // rows and columns
-	    var rows = this._size[0];
-	    var columns = this._size[1];
-	    // rows & columns
-	    var str = 'CRS [' + string.format(rows, options) + ' x ' + string.format(columns, options) + '] density: ' + string.format(this._values.length / (rows * columns), options) + '\n';
-	    // loop rows
-	    for (var i = 0; i < rows; i++) {
-	      // k0 <= k < k1 where k0 = _ptr[i] && k1 = _ptr[i+1]
-	      var k0 = this._ptr[i];
-	      var k1 = this._ptr[i + 1];
-	      // loop k within [k0, k1[
-	      for (var k = k0; k < k1; k++) {
-	        // column index
-	        var j = this._index[k];
-	        // append value
-	        str += '\n    (' + string.format(i, options) + ', ' + string.format(j, options) + ') ==> ' + string.format(this._values[k], options);
-	      }
-	    }
-	    return str;
-	  };
-
-	  /**
-	   * Get a string representation of the matrix
-	   * @returns {String} str
-	   */
-	  CrsMatrix.prototype.toString = function () {
-	    return string.format(this.toArray());
-	  };
-
-	  /**
-	   * Get a JSON representation of the matrix
-	   * @returns {Object}
-	   */
-	  CrsMatrix.prototype.toJSON = function () {
-	    return {
-	      mathjs: 'CrsMatrix',
-	      values: this._values,
-	      index: this._index,
-	      ptr: this._ptr,
-	      size: this._size
-	    };
-	  };
-
-	  /**
-	   * Calculates the transpose of the matrix
-	   * @returns {Matrix}
-	   */
-	  CrsMatrix.prototype.transpose = function () {
-	    // rows and columns
-	    var rows = this._size[0];
-	    var columns = this._size[1];
-	    // check columns
-	    if (columns === 0) {
-	      // throw exception
-	      throw new RangeError('Cannot transpose a 2D matrix with no columns (size: ' + string.format(this._size) + ')');
-	    }
-	    // crs transpose is a ccs matrix with the same structure
-	    return new math.type.CcsMatrix({
-	      values: object.clone(this._values),
-	      index: object.clone(this._index),
-	      ptr: object.clone(this._ptr),
-	      size: [columns, rows]
-	    });
-	  };
-
-	  /**
-	   * Get the kth Matrix diagonal.
-	   *
-	   * @param {Number | BigNumber} [k=0]     The kth diagonal where the vector will retrieved.
-	   *
-	   * @returns {Array}                      The array vector with the diagonal values.
-	   */
-	  CrsMatrix.prototype.diagonal = function(k) {
-	    // validate k if any
-	    if (k) {
-	      // convert BigNumber to a number
-	      if (k instanceof BigNumber) 
-	        k = k.toNumber();
-	      // is must be an integer
-	      if (!isNumber(k) || !isInteger(k)) {
-	        throw new TypeError ('The parameter k must be an integer number');
-	      }
-	    }
-	    else {
-	      // default value
-	      k = 0;
-	    }
-
-	    var kSuper = k > 0 ? k : 0;
-	    var kSub = k < 0 ? -k : 0;
-
-	    // rows & columns
-	    var rows = this._size[0];
-	    var columns = this._size[1];
-
-	    // number diagonal values
-	    var n = Math.min(rows - kSub, columns -  kSuper);
-
-	    // diagonal
-	    var values = [];
-	    // loop rows
-	    for (var i = kSub; i < rows && values.length < n; i++) {
-	      // k0 <= k < k1 where k0 = _ptr[i] && k1 = _ptr[i+1]
-	      var k0 = this._ptr[i];
-	      var k1 = this._ptr[i + 1];
-	      // row value flag
-	      var rv = false;
-	      // loop x within [k0, k1[
-	      for (var x = k0; x < k1; x++) {
-	        // column index
-	        var j = this._index[x];
-	        // check column
-	        if (j === i + kSuper - kSub) {
-	          // set flag
-	          rv = true;
-	          // value on this column
-	          values.push(object.clone(this._values[x]));
-	          // exit loop
-	          break;
-	        }
-	        else if (j > i + kSuper - kSub) {
-	          // exit loop, no value on the diagonal for row i
-	          break;
-	        }
-	      }
-	      // check this row has a value set
-	      if (!rv && values.length < n) {
-	        // zero on this column
-	        values.push(0);
-	      }
-	    }
-	    return values;
-	  };
-
-	  /**
-	   * Generate a matrix from a JSON object
-	   * @param {Object} json  An object structured like
-	   *                       `{"mathjs": "CrsMatrix", "values": [], "index": [], "ptr": [], "size": []}`,
-	   *                       where mathjs is optional
-	   * @returns {CrsMatrix}
-	   */
-	  CrsMatrix.fromJSON = function (json) {
-	    return new CrsMatrix(json);
-	  };
-
-	  /**
-	   * Create a diagonal matrix.
-	   *
-	   * @param {Array} size                   The matrix size.
-	   * @param {Number, Array} value          The values for the diagonal.
-	   * @param {Number | BigNumber} [k=0]     The kth diagonal where the vector will be filled in.
-	   *
-	   * @returns {CrsMatrix}
-	   */
-	  CrsMatrix.diagonal = function (size, value, k) {
-	    if (!isArray(size))
-	      throw new TypeError('Array expected, size parameter');
-	    if (size.length !== 2)
-	      throw new Error('Only two dimensions matrix are supported');
-
-	    // map size & validate
-	    size = size.map(function (s) {
-	      // check it is a big number
-	      if (s instanceof BigNumber) {
-	        // convert it
-	        s = s.toNumber();
-	      }
-	      // validate arguments
-	      if (!isNumber(s) || !isInteger(s) || s < 1) {
-	        throw new Error('Size values must be positive integers');
-	      } 
-	      return s;
-	    });
-
-	    // validate k if any
-	    if (k) {
-	      // convert BigNumber to a number
-	      if (k instanceof BigNumber) 
-	        k = k.toNumber();
-	      // is must be an integer
-	      if (!isNumber(k) || !isInteger(k)) {
-	        throw new TypeError ('The parameter k must be an integer number');
-	      }
-	    }
-	    else {
-	      // default value
-	      k = 0;
-	    }
-
-	    var kSuper = k > 0 ? k : 0;
-	    var kSub = k < 0 ? -k : 0;
-
-	    // rows and columns
-	    var rows = size[0];
-	    var columns = size[1];
-
-	    // number of non-zero items
-	    var n = Math.min(rows - kSub, columns -  kSuper);
-
-	    // value extraction function
-	    var _value;
-
-	    // check value
-	    if (isArray(value)) {
-	      // validate array
-	      if (value.length !== n) {
-	        // number of values in array must be n
-	        throw new Error('Invalid value array length');
-	      }
-	      // define function
-	      _value = function (i) {
-	        // return value @ i
-	        return value[i];
-	      };
-	    }
-	    else {
-	      // define function
-	      _value = function () {
-	        // return value
-	        return value;
-	      };
-	    }
-
-	    // create arrays
-	    var values = [];
-	    var index = [];
-	    var ptr = [];
-
-	    // loop items
-	    for (var i = 0; i < rows; i++) {
-	      // number of rows with value
-	      ptr.push(values.length);
-	      // diagonal index
-	      var j = i - kSub;
-	      // check we need to set diagonal value
-	      if (j >= 0 && j < n) {
-	        // get value @ j
-	        var v = _value(j);
-	        // check for zero
-	        if (!math.equal(v, 0)) {
-	          // column
-	          index.push(j + kSuper);
-	          // add value
-	          values.push(v);
-	        }
-	      }
-	    }
-	    // last value should be number of values
-	    ptr.push(values.length);
-	    // create CrsMatrix
-	    return new CrsMatrix({
-	      values: values,
-	      index: index,
-	      ptr: ptr,
-	      size: [rows, columns]
-	    });
-	  };
-
-	  /**
-	   * Calculate the trace of a matrix: the sum of the elements on the main
-	   * diagonal of a square matrix.
+	var clone = __webpack_require__(5).clone;
+	var isInteger = __webpack_require__(8).isInteger;
+	var array = __webpack_require__(18);
+	var IndexError = __webpack_require__(17);
+	var DimensionError = __webpack_require__(22);
+
+	function factory (type, config, load, typed) {
+	  var matrix = load(__webpack_require__(23));
+
+	  /**
+	   * Concatenate two or more matrices.
+	   *
+	   * Syntax:
+	   *
+	   *     math.concat(A, B, C, ...)
+	   *     math.concat(A, B, C, ..., dim)
+	   *
+	   * Where:
+	   *
+	   * - `dim: number` is a zero-based dimension over which to concatenate the matrices.
+	   *   By default the last dimension of the matrices.
+	   *
+	   * Examples:
+	   *
+	   *    var A = [[1, 2], [5, 6]];
+	   *    var B = [[3, 4], [7, 8]];
+	   *
+	   *    math.concat(A, B);                  // returns [[1, 2, 3, 4], [5, 6, 7, 8]]
+	   *    math.concat(A, B, 0);               // returns [[1, 2], [5, 6], [3, 4], [7, 8]]
+	   *    math.concat('hello', ' ', 'world'); // returns 'hello world'
 	   *
 	   * See also:
 	   *
-	   *    diagonal
-	   *
-	   * @returns {Number}       The matrix trace
-	   */
-	  CrsMatrix.prototype.trace = function () {
-	    // size
-	    var size = this._size;
-	    // check dimensions
-	    var rows = size[0];
-	    var columns = size[1];
-	    // matrix must be square
-	    if (rows === columns) {
-	      // calulate sum
-	      var sum = 0;
-	      // check we have data (avoid looping rows)
-	      if (this._values.length > 0) {
-	        // loop rows
-	        for (var i = 0; i < rows; i++) {
-	          // k0 <= k < k1 where k0 = _ptr[i] && k1 = _ptr[i+1]
-	          var k0 = this._ptr[i];
-	          var k1 = this._ptr[i + 1];
-	          // loop k within [k0, k1[
-	          for (var k = k0; k < k1; k++) {
-	            // column index
-	            var j = this._index[k];
-	            // check row
-	            if (i === j) {
-	              // accumulate value
-	              sum = math.add(sum, this._values[k]);
-	              // exit loop
-	              break;
-	            }
-	            if (j > i) {
-	              // exit loop, no value on the diagonal for column j
-	              break;
-	            }
-	          }
-	        }
-	      }
-	      // return trace
-	      return sum;
-	    }
-	    throw new RangeError('Matrix must be square (size: ' + string.format(size) + ')');        
-	  };
-	  
-	  /**
-	   * Multiply the matrix values times the argument.
-	   *
-	   * @param  {Number | BigNumber | Boolean | Complex | Unit | Array | Matrix | null} Value to multiply.
-	   *
-	   * @return {Number | BigNumber | Complex | Unit | Matrix}
-	   */
-	  CrsMatrix.prototype.multiply = function (value) {
-	    // check dimensions
-	    var rows = this._size[0];
-	    var columns = this._size[1];
-
-	    // check value is a matrix
-	    if (value instanceof Matrix) {
-	      // matrix size
-	      var z = value.size();
-	      // check value is a vector
-	      if (z.length === 1) {
-	        // mutiply matrix x vector array
-	        return _multiply(this, z[0], 1, function (i) {
-	          // value[i]
-	          return value.get([i]);
-	        });
-	      }
-	      // check two dimensions matrix
-	      if (z.length === 2) {        
-	        // mutiply matrix x matrix
-	        return _multiply(this, z[0], z[1], function (i, j) {
-	          // value[i, j]
-	          return value.get([i, j]);
-	        });
-	      }
-	      throw new Error('Can only multiply a 1 or 2 dimensional matrix ' +
-	                      '(value has ' + z.length + ' dimensions)');
-	    }
-
-	    // check value is an array
-	    if (isArray(value)) {
-	      // array size
-	      var s = array.size(value);
-	      // check value is a vector
-	      if (s.length === 1) {
-	        // mutiply matrix x vector array
-	        return _multiply(this, s[0], 1, function (i) {
-	          // value[i]
-	          return value[i];
-	        });
-	      }
-	      if (s.length === 2) {
-	        // mutiply matrix x array
-	        return _multiply(this, s[0], s[1], function (i, j) {
-	          // value[i, j]
-	          return value[i][j];
-	        });
-	      }
-	      throw new Error('Can only multiply a 1 or 2 dimensional matrix ' +
-	                      '(value has ' + s.length + ' dimensions)');
-	    }
-
-	    var callback = function (v) {
-	      return math.multiply(v, value);
-	    };
-
-	    // map non zero elements
-	    return _map(this, 0, rows - 1, 0, columns - 1, callback, false);
-	  };
-	  
-	  var _multiply = function (matrix, r, c, get) {
-
-	    // matrix dimensions
-	    var rows = matrix._size[0];
-	    var columns = matrix._size[1];
-
-	    // check dimensions match
-	    if (columns !== r) {
-	      // throw error
-	      throw new RangeError('Dimension mismatch in multiplication. ' +
-	                           'Columns of A must match length of B ' +
-	                           '(A is ' + rows + 'x' + columns +
-	                           ', B is ' + r + ', ' +
-	                           columns + ' != ' + r + ')');
-	    }
-
-	    // result arrays
-	    var values = [];
-	    var index = [];
-	    var ptr = [];
-
-	    // loop rows
-	    for (var i = 0; i < rows; i++) {
-	      // update ptr
-	      ptr.push(values.length);
-	      // k0 <= k < k1 where k0 = _ptr[i] && k1 = _ptr[i+1]
-	      var k0 = matrix._ptr[i];
-	      var k1 = matrix._ptr[i + 1];
-	      // loop value columns
-	      for (var z = 0; z < c; z++) {
-	        // value @ (i, x)
-	        var value = 0;
-	        // loop k within [k0, k1[
-	        for (var k = k0; k < k1; k++) {
-	          // column
-	          var j = matrix._index[k];
-	          // multiply & aggregate
-	          value = math.add(value, math.multiply(matrix._values[k], get(j, z)));
-	        }
-	        // check value is different than zero
-	        if (!math.equal(value, 0)) {
-	          // push value & column
-	          values.push(value);
-	          index.push(z);
-	        }        
-	      }
-	    }
-	    // update ptr
-	    ptr.push(values.length);
-
-	    // check we need to squeeze the result into a scalar
-	    if (rows === 1 && c === 1)
-	      return values.length === 1 ? values[0] : 0;
-
-	    // return CRS matrix
-	    return new CrsMatrix({
-	      values: values,
-	      index: index,
-	      ptr: ptr,
-	      size: [rows, c]
-	    });
-	  };
-
-	  return CrsMatrix;
-	};
+	   *    size, squeeze, subset, transpose
+	   *
+	   * @param {... Array | Matrix} args     Two or more matrices
+	   * @return {Array | Matrix} Concatenated matrix
+	   */
+	  var concat = typed('concat', {
+	    // TODO: change signature to '...Array | Matrix, dim?' when supported
+	    '...Array | Matrix | number | BigNumber': function (args) {
+	      var i;
+	      var len = args.length;
+	      var dim = -1;  // zero-based dimension
+	      var prevDim;
+	      var asMatrix = false;
+	      var matrices = [];  // contains multi dimensional arrays
+
+	      for (i = 0; i < len; i++) {
+	        var arg = args[i];
+
+	        // test whether we need to return a Matrix (if not we return an Array)
+	        if (arg && arg.isMatrix === true) {
+	          asMatrix = true;
+	        }
+
+	        if (typeof arg === 'number' || (arg && arg.isBigNumber === true)) {
+	          if (i !== len - 1) {
+	            throw new Error('Dimension must be specified as last argument');
+	          }
+
+	          // last argument contains the dimension on which to concatenate
+	          prevDim = dim;
+	          dim = arg.valueOf(); // change BigNumber to number
+
+	          if (!isInteger(dim)) {
+	            throw new TypeError('Integer number expected for dimension');
+	          }
+
+	          if (dim < 0) {
+	            // TODO: would be more clear when throwing a DimensionError here
+	            throw new IndexError(dim);
+	          }
+	          if (i > 0 && dim > prevDim) {
+	            // TODO: would be more clear when throwing a DimensionError here
+	            throw new IndexError(dim, prevDim + 1);
+	          }
+	        }
+	        else {
+	          // this is a matrix or array
+	          var m = clone(arg).valueOf();
+	          var size = array.size(m);
+	          matrices[i] = m;
+	          prevDim = dim;
+	          dim = size.length - 1;
+
+	          // verify whether each of the matrices has the same number of dimensions
+	          if (i > 0 && dim != prevDim) {
+	            throw new DimensionError(prevDim + 1, dim + 1);
+	          }
+	        }
+	      }
+
+	      if (matrices.length == 0) {
+	        throw new SyntaxError('At least one matrix expected');
+	      }
+
+	      var res = matrices.shift();
+	      while (matrices.length) {
+	        res = _concat(res, matrices.shift(), dim, 0);
+	      }
+
+	      return asMatrix ? matrix(res) : res;
+	    },
+
+	    '...string': function (args) {
+	      return args.join('');
+	    }
+	  });
+
+	  concat.toTex = '\\mathrm{${name}}\\left(${args}\\right)';
+
+	  return concat;
+	}
+
+	/**
+	 * Recursively concatenate two matrices.
+	 * The contents of the matrices is not cloned.
+	 * @param {Array} a             Multi dimensional array
+	 * @param {Array} b             Multi dimensional array
+	 * @param {number} concatDim    The dimension on which to concatenate (zero-based)
+	 * @param {number} dim          The current dim (zero-based)
+	 * @return {Array} c            The concatenated matrix
+	 * @private
+	 */
+	function _concat(a, b, concatDim, dim) {
+	  if (dim < concatDim) {
+	    // recurse into next dimension
+	    if (a.length != b.length) {
+	      throw new DimensionError(a.length, b.length);
+	    }
+
+	    var c = [];
+	    for (var i = 0; i < a.length; i++) {
+	      c[i] = _concat(a[i], b[i], concatDim, dim + 1);
+	    }
+	    return c;
+	  }
+	  else {
+	    // concatenate this dimension
+	    return a.concat(b);
+	  }
+	}
+
+	exports.name = 'concat';
+	exports.factory = factory;
+
 
 /***/ },
 /* 17 */
-/***/ function(module, exports, __webpack_require__) {
+/***/ function(module, exports) {
 
 	'use strict';
 
-	var util = __webpack_require__(175);
-	var DimensionError = __webpack_require__(172);
-
-	var string = util.string;
-	var array = util.array;
-	var object = util.object;
-
-	var isArray = Array.isArray;
-	var isNumber = util.number.isNumber;
-	var isInteger = util.number.isInteger;
-
-	var validateIndex = array.validateIndex;
-
-	module.exports = function (math) {
-
-	  var Index = math.type.Index,
-	      BigNumber = math.type.BigNumber,
-	      Matrix = math.type.Matrix;
-	  
-	  function DenseMatrix(data) {
-	    if (!(this instanceof DenseMatrix))
-	      throw new SyntaxError('Constructor must be called with the new operator');
-
-	    if (data instanceof Matrix) {
-	      // check data is a DenseMatrix
-	      if (data.type === 'DenseMatrix') {
-	        // clone data & size
-	        this._data = object.clone(data._data);
-	        this._size = object.clone(data._size);
-	      }
-	      else {
-	        // build data from existing matrix
-	        this._data = data.toArray();
-	        this._size = data.size();
-	      }
-	    }
-	    else if (data && isArray(data.data) && isArray(data.size)) {
-	      // initialize fields from JSON representation
-	      this._data = data.data;
-	      this._size = data.size;
-	    }
-	    else if (isArray(data)) {
-	      // replace nested Matrices with Arrays
-	      this._data = preprocess(data);
-	      // verify the size of the array, TODO: compute size while processing array
-	      this._size = array.size(this._data);
-	    }
-	    else if (data) {
-	      // unsupported type
-	      throw new TypeError('Unsupported type of data (' + util.types.type(data) + ')');
-	    }
-	    else {
-	      // nothing provided
-	      this._data = [];
-	      this._size = [0];
-	    }
-	  }
-	  
-	  DenseMatrix.prototype = new math.type.Matrix();
-
-	  DenseMatrix.prototype.type = 'DenseMatrix';
-
-	  /**
-	   * Get the storage format used by the matrix.
-	   *
-	   * Usage:
-	   *     var format = matrix.storage()                   // retrieve storage format
-	   *
-	   * @return {string}           The storage format.
-	   */
-	  DenseMatrix.prototype.storage = function () {
-	    return 'dense';
-	  };
-	  
-	  /**
-	   * Get a subset of the matrix, or replace a subset of the matrix.
-	   *
-	   * Usage:
-	   *     var subset = matrix.subset(index)               // retrieve subset
-	   *     var value = matrix.subset(index, replacement)   // replace subset
-	   *
-	   * @param {Index} index
-	   * @param {Array | DenseMatrix | *} [replacement]
-	   * @param {*} [defaultValue=0]      Default value, filled in on new entries when
-	   *                                  the matrix is resized. If not provided,
-	   *                                  new matrix elements will be filled with zeros.
-	   */
-	  DenseMatrix.prototype.subset = function (index, replacement, defaultValue) {
-	    switch (arguments.length) {
-	      case 1:
-	        return _get(this, index);
-
-	        // intentional fall through
-	      case 2:
-	      case 3:
-	        return _set(this, index, replacement, defaultValue);
-
-	      default:
-	        throw new SyntaxError('Wrong number of arguments');
-	    }
-	  };
-	  
-	  /**
-	   * Get a single element from the matrix.
-	   * @param {Number[]} index   Zero-based index
-	   * @return {*} value
-	   */
-	  DenseMatrix.prototype.get = function (index) {
-	    if (!isArray(index))
-	      throw new TypeError('Array expected');
-	    if (index.length != this._size.length)
-	      throw new DimensionError(index.length, this._size.length);
-
-	    // check index
-	    for (var x = 0; x < index.length; x++)
-	      validateIndex(index[x], this._size[x]);
-
-	    var data = this._data;
-	    for (var i = 0, ii = index.length; i < ii; i++) {
-	      var index_i = index[i];
-	      validateIndex(index_i, data.length);
-	      data = data[index_i];
-	    }
-
-	    return object.clone(data);
-	  };
-	  
-	  /**
-	   * Replace a single element in the matrix.
-	   * @param {Number[]} index   Zero-based index
-	   * @param {*} value
-	   * @param {*} [defaultValue]        Default value, filled in on new entries when
-	   *                                  the matrix is resized. If not provided,
-	   *                                  new matrix elements will be left undefined.
-	   * @return {DenseMatrix} self
-	   */
-	  DenseMatrix.prototype.set = function (index, value, defaultValue) {
-	    if (!isArray(index))
-	      throw new TypeError('Array expected');
-	    if (index.length < this._size.length)
-	      throw new DimensionError(index.length, this._size.length, '<');
-
-	    var i, ii, index_i;
-
-	    // enlarge matrix when needed
-	    var size = index.map(function (i) {
-	      return i + 1;
-	    });
-	    _fit(this, size, defaultValue);
-
-	    // traverse over the dimensions
-	    var data = this._data;
-	    for (i = 0, ii = index.length - 1; i < ii; i++) {
-	      index_i = index[i];
-	      validateIndex(index_i, data.length);
-	      data = data[index_i];
-	    }
-
-	    // set new value
-	    index_i = index[index.length - 1];
-	    validateIndex(index_i, data.length);
-	    data[index_i] = value;
-
-	    return this;
-	  };
-	  
-	  /**
-	   * Get a submatrix of this matrix
-	   * @param {DenseMatrix} matrix
-	   * @param {Index} index   Zero-based index
-	   * @private
-	   */
-	  function _get (matrix, index) {
-	    if (!(index instanceof Index)) {
-	      throw new TypeError('Invalid index');
-	    }
-
-	    var isScalar = index.isScalar();
-	    if (isScalar) {
-	      // return a scalar
-	      return matrix.get(index.min());
-	    }
-	    else {
-	      // validate dimensions
-	      var size = index.size();
-	      if (size.length != matrix._size.length) {
-	        throw new DimensionError(size.length, matrix._size.length);
-	      }
-
-	      // validate if any of the ranges in the index is out of range
-	      var min = index.min();
-	      var max = index.max();
-	      for (var i = 0, ii = matrix._size.length; i < ii; i++) {
-	        validateIndex(min[i], matrix._size[i]);
-	        validateIndex(max[i], matrix._size[i]);
-	      }
-
-	      // retrieve submatrix
-	      // TODO: more efficient when creating an empty matrix and setting _data and _size manually
-	      return new DenseMatrix(_getSubmatrix(matrix._data, index, size.length, 0));
-	    }
-	  }
-	  
-	  /**
-	   * Recursively get a submatrix of a multi dimensional matrix.
-	   * Index is not checked for correct number or length of dimensions.
-	   * @param {Array} data
-	   * @param {Index} index
-	   * @param {number} dims   Total number of dimensions
-	   * @param {number} dim    Current dimension
-	   * @return {Array} submatrix
-	   * @private
-	   */
-	  function _getSubmatrix (data, index, dims, dim) {
-	    var last = (dim == dims - 1);
-	    var range = index.range(dim);
-
-	    if (last) {
-	      return range.map(function (i) {
-	        return data[i];
-	      });
-	    }
-	    else {
-	      return range.map(function (i) {
-	        var child = data[i];
-	        return _getSubmatrix(child, index, dims, dim + 1);
-	      });
-	    }
-	  }
-	  
-	  /**
-	   * Replace a submatrix in this matrix
-	   * Indexes are zero-based.
-	   * @param {DenseMatrix} matrix
-	   * @param {Index} index
-	   * @param {DenseMatrix | Array | *} submatrix
-	   * @param {*} defaultValue          Default value, filled in on new entries when
-	   *                                  the matrix is resized.
-	   * @return {DenseMatrix} matrix
-	   * @private
-	   */
-	  function _set (matrix, index, submatrix, defaultValue) {
-	    if (!(index instanceof Index)) {
-	      throw new TypeError('Invalid index');
-	    }
-
-	    // get index size and check whether the index contains a single value
-	    var iSize = index.size(),
-	        isScalar = index.isScalar();
-
-	    // calculate the size of the submatrix, and convert it into an Array if needed
-	    var sSize;
-	    if (submatrix instanceof math.type.Matrix) {
-	      sSize = submatrix.size();
-	      submatrix = submatrix.valueOf();
-	    }
-	    else {
-	      sSize = array.size(submatrix);
-	    }
-
-	    if (isScalar) {
-	      // set a scalar
-
-	      // check whether submatrix is a scalar
-	      if (sSize.length !== 0) {
-	        throw new TypeError('Scalar expected');
-	      }
-
-	      matrix.set(index.min(), submatrix, defaultValue);
-	    }
-	    else {
-	      // set a submatrix
-
-	      // validate dimensions
-	      if (iSize.length < matrix._size.length) {
-	        throw new DimensionError(iSize.length, matrix._size.length, '<');
-	      }
-
-	      if (sSize.length < iSize.length) {
-	        // calculate number of missing outer dimensions
-	        var i = 0;
-	        var outer = 0;
-	        while (iSize[i] === 1 && sSize[i] === 1) {
-	          i++;
-	        }
-	        while (iSize[i] === 1) {
-	          outer++;
-	          i++;
-	        }
-
-	        // unsqueeze both outer and inner dimensions
-	        submatrix = array.unsqueeze(submatrix, iSize.length, outer, sSize);
-	      }
-
-	      // check whether the size of the submatrix matches the index size
-	      if (!object.deepEqual(iSize, sSize)) {
-	        throw new DimensionError(iSize, sSize, '>');
-	      }
-
-	      // enlarge matrix when needed
-	      var size = index.max().map(function (i) {
-	        return i + 1;
-	      });
-	      _fit(matrix, size, defaultValue);
-
-	      // insert the sub matrix
-	      var dims = iSize.length,
-	          dim = 0;
-	      _setSubmatrix (matrix._data, index, submatrix, dims, dim);
-	    }
-
-	    return matrix;
-	  }
-	  
-	  /**
-	   * Replace a submatrix of a multi dimensional matrix.
-	   * @param {Array} data
-	   * @param {Index} index
-	   * @param {Array} submatrix
-	   * @param {number} dims   Total number of dimensions
-	   * @param {number} dim
-	   * @private
-	   */
-	  function _setSubmatrix (data, index, submatrix, dims, dim) {
-	    var last = (dim == dims - 1),
-	        range = index.range(dim);
-
-	    if (last) {
-	      range.forEach(function (dataIndex, subIndex) {
-	        validateIndex(dataIndex);
-	        data[dataIndex] = submatrix[subIndex];
-	      });
-	    }
-	    else {
-	      range.forEach(function (dataIndex, subIndex) {
-	        validateIndex(dataIndex);
-	        _setSubmatrix(data[dataIndex], index, submatrix[subIndex], dims, dim + 1);
-	      });
-	    }
-	  }
-	  
-	  /**
-	   * Resize the matrix to the given size. Returns a copy of the matrix when
-	   * `copy=true`, otherwise return the matrix itself (resize in place).
-	   *
-	   * @param {Number[]} size           The new size the matrix should have.
-	   * @param {*} [defaultValue=0]      Default value, filled in on new entries.
-	   *                                  If not provided, the matrix elements will
-	   *                                  be filled with zeros.
-	   * @param {boolean} [copy]          Return a resized copy of the matrix
-	   *
-	   * @return {Matrix}                 The resized matrix
-	   */
-	  DenseMatrix.prototype.resize = function (size, defaultValue, copy) {
-	    // validate arguments
-	    if (!isArray(size))
-	      throw new TypeError('Array expected');
-
-	    // matrix to resize
-	    var m = copy ? this.clone() : this;
-	    // resize matrix
-	    return _resize(m, size, defaultValue);
-	  };
-	  
-	  var _resize = function (matrix, size, defaultValue) {
-	    // check size
-	    if (size.length === 0) {
-	      // first value in matrix
-	      var v = matrix._data;
-	      // go deep
-	      while (isArray(v)) {
-	        v = v[0];
-	      }
-	      return object.clone(v);
-	    }
-	    // resize matrix
-	    matrix._size = object.clone(size);
-	    matrix._data = array.resize(matrix._data, matrix._size, defaultValue);
-	    // return matrix
-	    return matrix;
-	  };
-	  
-	  /**
-	   * Enlarge the matrix when it is smaller than given size.
-	   * If the matrix is larger or equal sized, nothing is done.
-	   * @param {DenseMatrix} matrix           The matrix to be resized
-	   * @param {Number[]} size
-	   * @param {*} defaultValue          Default value, filled in on new entries.
-	   * @private
-	   */
-	  function _fit(matrix, size, defaultValue) {
-	    var newSize = object.clone(matrix._size),
-	        changed = false;
-
-	    // add dimensions when needed
-	    while (newSize.length < size.length) {
-	      newSize.push(0);
-	      changed = true;
-	    }
-
-	    // enlarge size when needed
-	    for (var i = 0, ii = size.length; i < ii; i++) {
-	      if (size[i] > newSize[i]) {
-	        newSize[i] = size[i];
-	        changed = true;
-	      }
-	    }
-
-	    if (changed) {
-	      // resize only when size is changed
-	      _resize(matrix, newSize, defaultValue);
-	    }
-	  }
-	  
-	  /**
-	   * Create a clone of the matrix
-	   * @return {DenseMatrix} clone
-	   */
-	  DenseMatrix.prototype.clone = function () {
-	    var m = new DenseMatrix({
-	      data: object.clone(this._data),
-	      size: object.clone(this._size)
-	    });
-	    return m;
-	  };
-	  
-	  /**
-	   * Retrieve the size of the matrix.
-	   * @returns {Number[]} size
-	   */
-	  DenseMatrix.prototype.size = function() {
-	    return this._size;
-	  };
-	  
-	  /**
-	   * Create a new matrix with the results of the callback function executed on
-	   * each entry of the matrix.
-	   * @param {function} callback   The callback function is invoked with three
-	   *                              parameters: the value of the element, the index
-	   *                              of the element, and the Matrix being traversed.
-	   *
-	   * @return {DenseMatrix} matrix
-	   */
-	  DenseMatrix.prototype.map = function (callback) {
-	    // matrix instance
-	    var me = this;
-	    var recurse = function (value, index) {
-	      if (isArray(value)) {
-	        return value.map(function (child, i) {
-	          return recurse(child, index.concat(i));
-	        });
-	      }
-	      else {
-	        return callback(value, index, me);
-	      }
-	    };
-	    // return dense format
-	    return new DenseMatrix({
-	      data: recurse(this._data, []),
-	      size: object.clone(this._size)
-	    });
-	  };
-	  
-	  /**
-	   * Execute a callback function on each entry of the matrix.
-	   * @param {function} callback   The callback function is invoked with three
-	   *                              parameters: the value of the element, the index
-	   *                              of the element, and the Matrix being traversed.
-	   */
-	  DenseMatrix.prototype.forEach = function (callback) {
-	    // matrix instance
-	    var me = this;
-	    var recurse = function (value, index) {
-	      if (isArray(value)) {
-	        value.forEach(function (child, i) {
-	          recurse(child, index.concat(i));
-	        });
-	      }
-	      else {
-	        callback(value, index, me);
-	      }
-	    };
-	    recurse(this._data, []);
-	  };
-	  
-	  /**
-	   * Create an Array with a copy of the data of the DenseMatrix
-	   * @returns {Array} array
-	   */
-	  DenseMatrix.prototype.toArray = function () {
-	    return object.clone(this._data);
-	  };
-	  
-	  /**
-	   * Get the primitive value of the DenseMatrix: a multidimensional array
-	   * @returns {Array} array
-	   */
-	  DenseMatrix.prototype.valueOf = function () {
-	    return this._data;
-	  };
-	  
-	  /**
-	   * Get a string representation of the matrix, with optional formatting options.
-	   * @param {Object | Number | Function} [options]  Formatting options. See
-	   *                                                lib/util/number:format for a
-	   *                                                description of the available
-	   *                                                options.
-	   * @returns {String} str
-	   */
-	  DenseMatrix.prototype.format = function (options) {
-	    return string.format(this._data, options);
-	  };
-	  
-	  /**
-	   * Get a string representation of the matrix
-	   * @returns {String} str
-	   */
-	  DenseMatrix.prototype.toString = function () {
-	    return string.format(this._data);
-	  };
-	  
-	  /**
-	   * Get a JSON representation of the matrix
-	   * @returns {Object}
-	   */
-	  DenseMatrix.prototype.toJSON = function () {
-	    return {
-	      mathjs: 'DenseMatrix',
-	      data: this._data,
-	      size: this._size
-	    };
-	  };
-	  
-	  /**
-	   * Calculates the transpose of the matrix
-	   * @returns {Matrix}
-	   */
-	  DenseMatrix.prototype.transpose = function () {
-	    // check dimensions
-	    switch (this._size.length) {
-	        case 1:
-	          // vector
-	          return this.clone();
-	        case 2:
-	          // rows and columns
-	          var rows = this._size[0];
-	          var columns = this._size[1];
-	          // check columns
-	          if (columns === 0) {
-	            // throw exception
-	            throw new RangeError('Cannot transpose a 2D matrix with no columns (size: ' + string.format(this._size) + ')');
-	          }
-	          // transposed matrix data
-	          var transposed = [];
-	          var transposedRow;
-	          // loop columns
-	          for (var j = 0; j < columns; j++) {
-	            // initialize row
-	            transposedRow = transposed[j] = [];
-	            // loop rows
-	            for (var i = 0; i < rows; i++) {
-	              // set data
-	              transposedRow[i] = object.clone(this._data[i][j]);
-	            }
-	          }
-	          // return matrix
-	          return new DenseMatrix({
-	            data: transposed,
-	            size: [columns, rows]
-	          });
-	        default:
-	          // multi dimensional
-	          throw new RangeError('Matrix must be two dimensional (size: ' + string.format(this._size) + ')');
-	    }
-	  };
-	  
-	  /**
-	   * Get the kth Matrix diagonal.
-	   *
-	   * @param {Number | BigNumber} [k=0]     The kth diagonal where the vector will retrieved.
-	   *
-	   * @returns {Array}                      The array vector with the diagonal values.
-	   */
-	  DenseMatrix.prototype.diagonal = function(k) {
-	    // validate k if any
-	    if (k) {
-	      // convert BigNumber to a number
-	      if (k instanceof BigNumber) 
-	        k = k.toNumber();
-	      // is must be an integer
-	      if (!isNumber(k) || !isInteger(k)) {
-	        throw new TypeError ('The parameter k must be an integer number');
-	      }
-	    }
-	    else {
-	      // default value
-	      k = 0;
-	    }
-
-	    var kSuper = k > 0 ? k : 0;
-	    var kSub = k < 0 ? -k : 0;
-
-	    // rows & columns
-	    var rows = this._size[0];
-	    var columns = this._size[1];
-
-	    // number diagonal values
-	    var n = Math.min(rows - kSub, columns -  kSuper);
-	    
-	    // x is a matrix get diagonal from matrix
-	    var vector = [];
-	    
-	    // loop rows
-	    for (var i = 0; i < n; i++) {
-	      vector[i] = object.clone(this._data[i + kSub][i + kSuper]);
-	    }
-	    return vector;
-	  };
-	  
-	  /**
-	   * Create a diagonal matrix.
-	   *
-	   * @param {Array} size                   The matrix size.
-	   * @param {Number, Array} value          The values for the diagonal.
-	   * @param {Number | BigNumber} [k=0]     The kth diagonal where the vector will be filled in.
-	   * @param {Number} [defaultValue]        The default value for non-diagonal
-	   *
-	   * @returns {DenseMatrix}
-	   */
-	  DenseMatrix.diagonal = function (size, value, k, defaultValue) {
-	    if (!isArray(size))
-	      throw new TypeError('Array expected, size parameter');
-	    if (size.length !== 2)
-	      throw new Error('Only two dimensions matrix are supported');
-
-	    // map size & validate
-	    size = size.map(function (s) {
-	      // check it is a big number
-	      if (s instanceof BigNumber) {
-	        // convert it
-	        s = s.toNumber();
-	      }
-	      // validate arguments
-	      if (!isNumber(s) || !isInteger(s) || s < 1) {
-	        throw new Error('Size values must be positive integers');
-	      } 
-	      return s;
-	    });
-
-	    // validate k if any
-	    if (k) {
-	      // convert BigNumber to a number
-	      if (k instanceof BigNumber) 
-	        k = k.toNumber();
-	      // is must be an integer
-	      if (!isNumber(k) || !isInteger(k)) {
-	        throw new TypeError ('The parameter k must be an integer number');
-	      }
-	    }
-	    else {
-	      // default value
-	      k = 0;
-	    }
-
-	    var kSuper = k > 0 ? k : 0;
-	    var kSub = k < 0 ? -k : 0;
-	    
-	    // rows and columns
-	    var rows = size[0];
-	    var columns = size[1];
-
-	    // number of non-zero items
-	    var n = Math.min(rows - kSub, columns -  kSuper);
-
-	    // value extraction function
-	    var _value;
-
-	    // check value
-	    if (isArray(value)) {
-	      // validate array
-	      if (value.length !== n) {
-	        // number of values in array must be n
-	        throw new Error('Invalid value array length');
-	      }
-	      // define function
-	      _value = function (i) {
-	        // return value @ i
-	        return value[i];
-	      };
-	    }
-	    else {
-	      // define function
-	      _value = function () {
-	        // return value
-	        return value;
-	      };
-	    }
-
-	    // empty array
-	    var data = [];
-
-	    // check we need to resize array
-	    if (size.length > 0) {
-	      // resize array
-	      data = array.resize(data, size, defaultValue);
-	      // fill diagonal
-	      for (var d = 0; d < n; d++) {
-	        data[d + kSub][d + kSuper] = _value(d);
-	      }
-	    }
-	    
-	    // create DenseMatrix
-	    return new DenseMatrix({
-	      data: data,
-	      size: [rows, columns]
-	    });
-	  };
-	  
-	  /**
-	   * Calculate the trace of a matrix: the sum of the elements on the main
-	   * diagonal of a square matrix.
-	   *
-	   * See also:
-	   *
-	   *    diagonal
-	   *
-	   * @returns {Number}       The matrix trace
-	   */
-	  DenseMatrix.prototype.trace = function () {
-	    // size & data
-	    var size = this._size;
-	    var data = this._data;
-	    // check dimensions
-	    switch (size.length) {
-	      case 1:
-	        // vector
-	        if (size[0] == 1) {
-	          // return data[0]
-	          return object.clone(data[0]);
-	        }
-	        throw new RangeError('Matrix must be square (size: ' + string.format(size) + ')');
-	      case 2:
-	        // two dimensional array
-	        var rows = size[0];
-	        var cols = size[1];
-	        if (rows === cols) {
-	          // calulate sum
-	          var sum = 0;
-	          // loop diagonal
-	          for (var i = 0; i < rows; i++)
-	            sum = math.add(sum, data[i][i]);
-	          // return trace
-	          return sum;
-	        }
-	        throw new RangeError('Matrix must be square (size: ' + string.format(size) + ')');        
-	      default:
-	        // multi dimensional array
-	        throw new RangeError('Matrix must be two dimensional (size: ' + string.format(size) + ')');
-	    }
-	  };
-
-	  /**
-	   * Generate a matrix from a JSON object
-	   * @param {Object} json  An object structured like
-	   *                       `{"mathjs": "DenseMatrix", data: [], size: []}`,
-	   *                       where mathjs is optional
-	   * @returns {DenseMatrix}
-	   */
-	  DenseMatrix.fromJSON = function (json) {
-	    return new DenseMatrix(json);
-	  };
-
-	  /**
-	   * Multiply the matrix values times the argument.
-	   *
-	   * @param  {Number | BigNumber | Boolean | Complex | Unit | Array | Matrix | null} Value to multiply.
-	   *
-	   * @return {Number | BigNumber | Complex | Unit | Matrix}
-	   */
-	  DenseMatrix.prototype.multiply = function (value) {
-	    // process matrix size
-	    switch(this._size.length) {
-	      case 1:
-	        // multiply vector
-	        return _multiplyVector(this, this._size[0], value);
-	      case 2:
-	        // multiply matrix
-	        return _multiplyMatrix(this, this._size[0], this._size[1], value);
-	      default:
-	        throw new Error('Can only multiply a 1 or 2 dimensional matrix ' +
-	                        '(matrix has ' + this._size.length + ' dimensions)');
-	    }
-	  };
-	  
-	  var _multiplyVector = function (matrix, m, value) {
-	    // check value is a matrix
-	    if (value instanceof Matrix) {
-	      // matrix size
-	      var z = value.size();
-	      // check value is a vector
-	      if (z.length === 1) {
-	        // vectors must have same length
-	        if (z[0] !== m)
-	          throw new RangeError('Dimension mismatch in multiplication. Vectors must have the same length.');
-	        // multiply vector x vector
-	        return _multiplyVectorVector(matrix, m, function (i) {
-	          // value[i]
-	          return value.get([i]);
-	        });
-	      }
-	      // check two dimensions matrix
-	      if (z.length === 2) {        
-	        // vector length must be equal rows in matrix
-	        if (z[0] !== m)
-	          throw new RangeError('Dimension mismatch in multiplication. Matrix rows and Vector length must be equal.');
-	        // mutiply vector x matrix
-	        return _multiplyVectorMatrix(matrix, m, z[1], function (i, j) {
-	          // value[i]
-	          return value.get([i, j]);
-	        });
-	      }
-	      throw new Error('Can only multiply a 1 or 2 dimensional matrix ' +
-	                      '(value has ' + z.length + ' dimensions)');
-	    }
-
-	    // check value is an array
-	    if (isArray(value)) {
-	      // array size
-	      var s = array.size(value);
-	      // check value is a vector
-	      if (s.length === 1) {
-	        // vectors must have same length
-	        if (s[0] !== m)
-	          throw new RangeError('Dimension mismatch in multiplication. Vectors must have the same length.');
-	        // multiply vector x vector
-	        return _multiplyVectorVector(matrix, m, function (i) {
-	          // value[i]
-	          return value[i];
-	        });
-	      }
-	      if (s.length === 2) {
-	        // vector length must be equal rows in matrix
-	        if (s[0] !== m)
-	          throw new RangeError('Dimension mismatch in multiplication. Matrix rows and Vector length must be equal.');
-	        // mutiply vector x matrix
-	        return _multiplyVectorMatrix(matrix, m, s[1], function (i, j) {
-	          // value[i]
-	          return value[i][j];
-	        });
-	      }
-	      throw new Error('Can only multiply a 1 or 2 dimensional matrix ' +
-	                      '(value has ' + s.length + ' dimensions)');
-	    }
-	    
-	    // value is a scalar
-	    return matrix.map(function (v) {
-	      return math.multiply(value, v);
-	    });
-	  };
-	  
-	  var _multiplyVectorVector = function (matrix, m, get) {
-	    // check empty vector
-	    if (m === 0)
-	      throw new Error('Cannot multiply two empty vectors');
-	    // result
-	    var result = 0;
-	    // loop data
-	    for (var i = 0; i < m; i++) {
-	      // multiply and accumulate
-	      result = math.add(result, math.multiply(matrix._data[i], get(i)));
-	    }
-	    return result;
-	  };
-	                        
-	  var _multiplyVectorMatrix = function (matrix, m, n, get) {
-	    // result
-	    var result = [];
-	    // loop columns in matrix
-	    for (var j = 0; j < n; j++) {
-	      // sum
-	      var sum = 0;
-	      // loop vector
-	      for (var i = 0; i < m; i++) {
-	        // multiply and accumulate
-	        sum = math.add(sum, math.multiply(matrix._data[i], get(i, j)));
-	      }
-	      result[j] = sum;
-	    }
-	    // check we need to squeeze the result into a scalar
-	    if (n === 1)
-	      return result[0];
-	    // return matrix
-	    return new DenseMatrix({
-	      data: result,
-	      size: [n]
-	    });
-	  };
-	      
-	  var _multiplyMatrix = function (matrix, m, n, value) {
-	    // check value is a matrix
-	    if (value instanceof Matrix) {
-	      // matrix size
-	      var z = value.size();
-	      // check value is a vector
-	      if (z.length === 1) {
-	        // vectors must have same length
-	        if (z[0] !== n)
-	          throw new RangeError('Dimension mismatch in multiplication. Matrix columns must match vector length.');
-	        // multiply matrix vector
-	        return _multiplyMatrixVector(matrix, m, n, function (i) {
-	          // value[i]
-	          return value.get([i]);
-	        });
-	      }
-	      // check two dimensions matrix
-	      if (z.length === 2) {        
-	        // vector length must be equal rows in matrix
-	        if (z[0] !== n) {
-	          throw new RangeError('Dimension mismatch in multiplication. ' +
-	                               'Columns of A must match length of B ' +
-	                               '(A is ' + m + 'x' + n +
-	                               ', B is ' + z[0] + ', ' +
-	                               n + ' != ' + z[0] + ')');
-	        }
-	        // mutiply vector x matrix
-	        return _multiplyMatrixMatrix(matrix, m, n, z[1], function (i, j) {
-	          // value[i, j]
-	          return value.get([i, j]);
-	        });
-	      }
-	      throw new Error('Can only multiply a 1 or 2 dimensional matrix ' +
-	                      '(value has ' + z.length + ' dimensions)');
-	    }
-
-	    // check value is an array
-	    if (isArray(value)) {
-	      // array size
-	      var s = array.size(value);
-	      // check value is a vector
-	      if (s.length === 1) {
-	        // vectors must have same length
-	        if (s[0] !== n)
-	          throw new RangeError('Dimension mismatch in multiplication. Matrix columns must match vector length.');
-	        // multiply matrix vector
-	        return _multiplyMatrixVector(matrix, m, n, function (i) {
-	          // value[i]
-	          return value[i];
-	        });
-	      }
-	      if (s.length === 2) {
-	        // vector length must be equal rows in matrix
-	        if (s[0] !== n) {
-	          throw new RangeError('Dimension mismatch in multiplication. ' +
-	                               'Columns of A must match length of B ' +
-	                               '(A is ' + m + 'x' + n +
-	                               ', B is ' + s[0] + ', ' +
-	                               n + ' != ' + s[0] + ')');
-	        }
-	        // mutiply vector x matrix
-	        return _multiplyMatrixMatrix(matrix, m, n, s[1], function (i, j) {
-	          // value[i, j]
-	          return value[i][j];
-	        });
-	      }
-	      throw new Error('Can only multiply a 1 or 2 dimensional matrix ' +
-	                      '(value has ' + s.length + ' dimensions)');
-	    }
-
-	    // value is a scalar
-	    return matrix.map(function (v) {
-	      return math.multiply(value, v);
-	    });
-	  };
-	  
-	  var _multiplyMatrixVector = function (matrix, m, n, get) {
-	    // result
-	    var result = [];
-	    // loop matrix rows
-	    for (var i = 0; i < m; i++) {
-	      // current row
-	      var row = matrix._data[i];
-	      // sum
-	      var sum = 0;
-	      // loop matrix columns
-	      for (var j = 0; j < n; j++) {
-	        // multiply & accumulate
-	        sum = math.add(sum, math.multiply(row[j], get(j)));
-	      }
-	      result[i] = sum;
-	    }
-	    // check we need to squeeze the result into a scalar
-	    if (m === 1)
-	      return result[0];
-	    // return matrix
-	    return new DenseMatrix({
-	      data: result,
-	      size: [m]
-	    });
-	  };
-	  
-	  var _multiplyMatrixMatrix = function (matrix, m, n, c, get) {
-	    // result
-	    var result = [];
-	    // loop matrix rows
-	    for (var i = 0; i < m; i++) {
-	      // current row
-	      var row = matrix._data[i];
-	      // initialize row array
-	      result[i] = [];
-	      // loop other matrix columns
-	      for (var j = 0; j < c; j++) {
-	        // sum
-	        var sum = 0;
-	        // loop matrix columns
-	        for (var x = 0; x < n; x++) {
-	          // multiply & accumulate
-	          sum = math.add(sum, math.multiply(row[x], get(x, j)));
-	        }
-	        result[i][j] = sum;
-	      }
-	    }
-	    // check we need to squeeze the result into a scalar
-	    if (m === 1 && c === 1)
-	      return result[0][0];
-	    // return matrix
-	    return new DenseMatrix({
-	      data: result,
-	      size: [m, c]
-	    });
-	  };
-	  
-	  /**
-	   * Preprocess data, which can be an Array or DenseMatrix with nested Arrays and
-	   * Matrices. Replaces all nested Matrices with Arrays
-	   * @param {Array} data
-	   * @return {Array} data
-	   */
-	  function preprocess(data) {
-	    for (var i = 0, ii = data.length; i < ii; i++) {
-	      var elem = data[i];
-	      if (isArray(elem)) {
-	        data[i] = preprocess(elem);
-	      }
-	      else if (elem instanceof math.type.Matrix) {
-	        data[i] = preprocess(elem.valueOf());
-	      }
-	    }
-
-	    return data;
-	  }
-
-	  // exports
-	  return DenseMatrix;
-	};
+	/**
+	 * Create a range error with the message:
+	 *     'Index out of range (index < min)'
+	 *     'Index out of range (index < max)'
+	 *
+	 * @param {number} index     The actual index
+	 * @param {number} [min=0]   Minimum index (included)
+	 * @param {number} [max]     Maximum index (excluded)
+	 * @extends RangeError
+	 */
+	function IndexError(index, min, max) {
+	  if (!(this instanceof IndexError)) {
+	    throw new SyntaxError('Constructor must be called with the new operator');
+	  }
+
+	  this.index = index;
+	  if (arguments.length < 3) {
+	    this.min = 0;
+	    this.max = min;
+	  }
+	  else {
+	    this.min = min;
+	    this.max = max;
+	  }
+
+	  if (this.min !== undefined && this.index < this.min) {
+	    this.message = 'Index out of range (' + this.index + ' < ' + this.min + ')';
+	  }
+	  else if (this.max !== undefined && this.index >= this.max) {
+	    this.message = 'Index out of range (' + this.index + ' > ' + (this.max - 1) + ')';
+	  }
+	  else {
+	    this.message = 'Index out of range (' + this.index + ')';
+	  }
+
+	  this.stack = (new Error()).stack;
+	}
+
+	IndexError.prototype = new RangeError();
+	IndexError.prototype.constructor = RangeError;
+	IndexError.prototype.name = 'IndexError';
+	IndexError.prototype.isIndexError = true;
+
+	module.exports = IndexError;
 
 
 /***/ },
@@ -7260,2752 +3183,778 @@
 
 	'use strict';
 
-	exports.ArrayNode = __webpack_require__(177);
-	exports.AssignmentNode = __webpack_require__(178);
-	exports.BlockNode = __webpack_require__(179);
-	exports.ConditionalNode = __webpack_require__(180);
-	exports.ConstantNode = __webpack_require__(181);
-	exports.IndexNode = __webpack_require__(182);
-	exports.FunctionAssignmentNode = __webpack_require__(183);
-	exports.FunctionNode = __webpack_require__(184);
-	exports.Node = __webpack_require__(185);
-	exports.OperatorNode = __webpack_require__(186);
-	exports.RangeNode = __webpack_require__(187);
-	exports.SymbolNode = __webpack_require__(188);
-	exports.UpdateNode = __webpack_require__(189);
+	var number = __webpack_require__(8);
+	var string = __webpack_require__(20);
+	var object = __webpack_require__(5);
+	var types = __webpack_require__(19);
+
+	var DimensionError = __webpack_require__(22);
+	var IndexError = __webpack_require__(17);
+
+	/**
+	 * Calculate the size of a multi dimensional array.
+	 * This function checks the size of the first entry, it does not validate
+	 * whether all dimensions match. (use function `validate` for that)
+	 * @param {Array} x
+	 * @Return {Number[]} size
+	 */
+	exports.size = function (x) {
+	  var s = [];
+
+	  while (Array.isArray(x)) {
+	    s.push(x.length);
+	    x = x[0];
+	  }
+
+	  return s;
+	};
+
+	/**
+	 * Recursively validate whether each element in a multi dimensional array
+	 * has a size corresponding to the provided size array.
+	 * @param {Array} array    Array to be validated
+	 * @param {number[]} size  Array with the size of each dimension
+	 * @param {number} dim   Current dimension
+	 * @throws DimensionError
+	 * @private
+	 */
+	function _validate(array, size, dim) {
+	  var i;
+	  var len = array.length;
+
+	  if (len != size[dim]) {
+	    throw new DimensionError(len, size[dim]);
+	  }
+
+	  if (dim < size.length - 1) {
+	    // recursively validate each child array
+	    var dimNext = dim + 1;
+	    for (i = 0; i < len; i++) {
+	      var child = array[i];
+	      if (!Array.isArray(child)) {
+	        throw new DimensionError(size.length - 1, size.length, '<');
+	      }
+	      _validate(array[i], size, dimNext);
+	    }
+	  }
+	  else {
+	    // last dimension. none of the childs may be an array
+	    for (i = 0; i < len; i++) {
+	      if (Array.isArray(array[i])) {
+	        throw new DimensionError(size.length + 1, size.length, '>');
+	      }
+	    }
+	  }
+	}
+
+	/**
+	 * Validate whether each element in a multi dimensional array has
+	 * a size corresponding to the provided size array.
+	 * @param {Array} array    Array to be validated
+	 * @param {number[]} size  Array with the size of each dimension
+	 * @throws DimensionError
+	 */
+	exports.validate = function(array, size) {
+	  var isScalar = (size.length == 0);
+	  if (isScalar) {
+	    // scalar
+	    if (Array.isArray(array)) {
+	      throw new DimensionError(array.length, 0);
+	    }
+	  }
+	  else {
+	    // array
+	    _validate(array, size, 0);
+	  }
+	};
+
+	/**
+	 * Test whether index is an integer number with index >= 0 and index < length
+	 * @param {number} index    Zero-based index
+	 * @param {number} [length] Length of the array
+	 */
+	exports.validateIndex = function(index, length) {
+	  if (!number.isNumber(index) || !number.isInteger(index)) {
+	    throw new TypeError('Index must be an integer (value: ' + index + ')');
+	  }
+	  if (index < 0) {
+	    throw new IndexError(index);
+	  }
+	  if (length !== undefined && index >= length) {
+	    throw new IndexError(index, length);
+	  }
+	};
+
+	// a constant used to specify an undefined defaultValue
+	exports.UNINITIALIZED = {};
+
+	/**
+	 * Resize a multi dimensional array. The resized array is returned.
+	 * @param {Array} array         Array to be resized
+	 * @param {Array.<number>} size Array with the size of each dimension
+	 * @param {*} [defaultValue=0]  Value to be filled in in new entries,
+	 *                              zero by default. To leave new entries undefined,
+	 *                              specify array.UNINITIALIZED as defaultValue
+	 * @return {Array} array         The resized array
+	 */
+	exports.resize = function(array, size, defaultValue) {
+	  // TODO: add support for scalars, having size=[] ?
+
+	  // check the type of the arguments
+	  if (!Array.isArray(array) || !Array.isArray(size)) {
+	    throw new TypeError('Array expected');
+	  }
+	  if (size.length === 0) {
+	    throw new Error('Resizing to scalar is not supported');
+	  }
+
+	  // check whether size contains positive integers
+	  size.forEach(function (value) {
+	    if (!number.isNumber(value) || !number.isInteger(value) || value < 0) {
+	      throw new TypeError('Invalid size, must contain positive integers ' +
+	          '(size: ' + string.format(size) + ')');
+	    }
+	  });
+
+	  // recursively resize the array
+	  var _defaultValue = (defaultValue !== undefined) ? defaultValue : 0;
+	  _resize(array, size, 0, _defaultValue);
+
+	  return array;
+	};
+
+	/**
+	 * Recursively resize a multi dimensional array
+	 * @param {Array} array         Array to be resized
+	 * @param {number[]} size       Array with the size of each dimension
+	 * @param {number} dim          Current dimension
+	 * @param {*} [defaultValue]    Value to be filled in in new entries,
+	 *                              undefined by default.
+	 * @private
+	 */
+	function _resize (array, size, dim, defaultValue) {
+	  var i;
+	  var elem;
+	  var oldLen = array.length;
+	  var newLen = size[dim];
+	  var minLen = Math.min(oldLen, newLen);
+
+	  // apply new length
+	  array.length = newLen;
+
+	  if (dim < size.length - 1) {
+	    // non-last dimension
+	    var dimNext = dim + 1;
+
+	    // resize existing child arrays
+	    for (i = 0; i < minLen; i++) {
+	      // resize child array
+	      elem = array[i];
+	      if (!Array.isArray(elem)) {
+	        elem = [elem]; // add a dimension
+	        array[i] = elem;
+	      }
+	      _resize(elem, size, dimNext, defaultValue);
+	    }
+
+	    // create new child arrays
+	    for (i = minLen; i < newLen; i++) {
+	      // get child array
+	      elem = [];
+	      array[i] = elem;
+
+	      // resize new child array
+	      _resize(elem, size, dimNext, defaultValue);
+	    }
+	  }
+	  else {
+	    // last dimension
+
+	    // remove dimensions of existing values
+	    for (i = 0; i < minLen; i++) {
+	      while (Array.isArray(array[i])) {
+	        array[i] = array[i][0];
+	      }
+	    }
+
+	    if(defaultValue !== exports.UNINITIALIZED) {
+	      // fill new elements with the default value
+	      for (i = minLen; i < newLen; i++) {
+	        array[i] = object.clone(defaultValue);
+	      }
+	    }
+	  }
+	}
+
+	/**
+	 * Squeeze a multi dimensional array
+	 * @param {Array} array
+	 * @param {Array} [size]
+	 * @returns {Array} returns the array itself
+	 */
+	exports.squeeze = function(array, size) {
+	  var s = size || exports.size(array);
+
+	  // squeeze outer dimensions
+	  while (Array.isArray(array) && array.length === 1) {
+	    array = array[0];
+	    s.shift();
+	  }
+
+	  // find the first dimension to be squeezed
+	  var dims = s.length;
+	  while (s[dims - 1] === 1) {
+	    dims--;
+	  }
+
+	  // squeeze inner dimensions
+	  if (dims < s.length) {
+	    array = _squeeze(array, dims, 0);
+	    s.length = dims;
+	  }
+
+	  return array;
+	};
+
+	/**
+	 * Recursively squeeze a multi dimensional array
+	 * @param {Array} array
+	 * @param {number} dims Required number of dimensions
+	 * @param {number} dim  Current dimension
+	 * @returns {Array | *} Returns the squeezed array
+	 * @private
+	 */
+	function _squeeze (array, dims, dim) {
+	  var i, ii;
+
+	  if (dim < dims) {
+	    var next = dim + 1;
+	    for (i = 0, ii = array.length; i < ii; i++) {
+	      array[i] = _squeeze(array[i], dims, next);
+	    }
+	  }
+	  else {
+	    while (Array.isArray(array)) {
+	      array = array[0];
+	    }
+	  }
+
+	  return array;
+	}
+
+	/**
+	 * Unsqueeze a multi dimensional array: add dimensions when missing
+	 * @param {Array} array
+	 * @param {number} dims     Desired number of dimensions of the array
+	 * @param {number} [outer]  Number of outer dimensions to be added
+	 * @param {Array} [size]    Current size of array
+	 * @returns {Array} returns the array itself
+	 * @private
+	 */
+	exports.unsqueeze = function(array, dims, outer, size) {
+	  var s = size || exports.size(array);
+
+	  // unsqueeze outer dimensions
+	  if (outer) {
+	    for (var i = 0; i < outer; i++) {
+	      array = [array];
+	      s.unshift(1);
+	    }
+	  }
+
+	  // unsqueeze inner dimensions
+	  array = _unsqueeze(array, dims, 0);
+	  while (s.length < dims) {
+	    s.push(1);
+	  }
+
+	  return array;
+	};
+
+	/**
+	 * Recursively unsqueeze a multi dimensional array
+	 * @param {Array} array
+	 * @param {number} dims Required number of dimensions
+	 * @param {number} dim  Current dimension
+	 * @returns {Array | *} Returns the squeezed array
+	 * @private
+	 */
+	function _unsqueeze (array, dims, dim) {
+	  var i, ii;
+
+	  if (Array.isArray(array)) {
+	    var next = dim + 1;
+	    for (i = 0, ii = array.length; i < ii; i++) {
+	      array[i] = _unsqueeze(array[i], dims, next);
+	    }
+	  }
+	  else {
+	    for (var d = dim; d < dims; d++) {
+	      array = [array];
+	    }
+	  }
+
+	  return array;
+	}
+	/**
+	 * Flatten a multi dimensional array, put all elements in a one dimensional
+	 * array
+	 * @param {Array} array   A multi dimensional array
+	 * @return {Array}        The flattened array (1 dimensional)
+	 */
+	exports.flatten = function(array) {
+	  if (!Array.isArray(array)) {
+	    //if not an array, return as is
+	    return array;
+	  }
+	  var flat = [];
+
+	  array.forEach(function callback(value) {
+	    if (Array.isArray(value)) {
+	      value.forEach(callback);  //traverse through sub-arrays recursively
+	    }
+	    else {
+	      flat.push(value);
+	    }
+	  });
+
+	  return flat;
+	};
+
+	/**
+	 * Test whether an object is an array
+	 * @param {*} value
+	 * @return {boolean} isArray
+	 */
+	exports.isArray = Array.isArray;
 
 
 /***/ },
 /* 19 */
-/***/ function(module, exports, __webpack_require__) {
+/***/ function(module, exports) {
 
 	'use strict';
 
-	var util = __webpack_require__(175),
-
-	    ArgumentsError = __webpack_require__(171),
-
-	    isString = util.string.isString,
-	    isArray = Array.isArray,
-
-	    // scope and nodes
-	    ArrayNode = __webpack_require__(177),
-	    AssignmentNode = __webpack_require__(178),
-	    BlockNode = __webpack_require__(179),
-	    ConditionalNode = __webpack_require__(180),
-	    ConstantNode = __webpack_require__(181),
-	    FunctionAssignmentNode = __webpack_require__(183),
-	    IndexNode = __webpack_require__(182),
-	    OperatorNode = __webpack_require__(186),
-	    FunctionNode = __webpack_require__(184),
-	    RangeNode = __webpack_require__(187),
-	    SymbolNode = __webpack_require__(188),
-	    UpdateNode = __webpack_require__(189);
-
-	module.exports = function (math) {
-
-	  // types
-	  var Matrix = math.type.Matrix,
-	      collection = math.collection;
-	    
-	  /**
-	   * Parse an expression. Returns a node tree, which can be evaluated by
-	   * invoking node.eval();
-	   *
-	   * Syntax:
-	   *
-	   *     parse(expr)
-	   *     parse(expr, options)
-	   *     parse([expr1, expr2, expr3, ...])
-	   *     parse([expr1, expr2, expr3, ...], options)
-	   *
-	   * Example:
-	   *
-	   *     var node = parse('sqrt(3^2 + 4^2)');
-	   *     node.compile(math).eval(); // 5
-	   *
-	   *     var scope = {a:3, b:4}
-	   *     var node = parse('a * b'); // 12
-	   *     var code = node.compile(math);
-	   *     code.eval(scope); // 12
-	   *     scope.a = 5;
-	   *     code.eval(scope); // 20
-	   *
-	   *     var nodes = math.parse(['a = 3', 'b = 4', 'a * b']);
-	   *     nodes[2].compile(math).eval(); // 12
-	   *
-	   * @param {String | String[] | Matrix} expr
-	   * @param {{nodes: Object<String, Node>}} [options]  Available options:
-	   *                                                   - `nodes` a set of custom nodes
-	   * @return {Node | Node[]} node
-	   * @throws {Error}
-	   */
-	  function parse (expr, options) {
-	    if (arguments.length != 1 && arguments.length != 2) {
-	      throw new ArgumentsError('parse', arguments.length, 1, 2);
-	    }
-
-	    // pass extra nodes
-	    extra_nodes = (options && options.nodes) ? options.nodes : {};
-
-	    if (isString(expr)) {
-	      // parse a single expression
-	      expression = expr;
-	      return parseStart();
-	    }
-	    else if (isArray(expr) || expr instanceof Matrix) {
-	      // parse an array or matrix with expressions
-	      return collection.deepMap(expr, function (elem) {
-	        if (!isString(elem)) throw new TypeError('String expected');
-
-	        expression = elem;
-	        return parseStart();
-	      });
-	    }
-	    else {
-	      // oops
-	      throw new TypeError('String or matrix expected');
-	    }
-	  }
-
-	  // token types enumeration
-	  var TOKENTYPE = {
-	    NULL : 0,
-	    DELIMITER : 1,
-	    NUMBER : 2,
-	    SYMBOL : 3,
-	    UNKNOWN : 4
-	  };
-
-	  // map with all delimiters
-	  var DELIMITERS = {
-	    ',': true,
-	    '(': true,
-	    ')': true,
-	    '[': true,
-	    ']': true,
-	    '\"': true,
-	    ';': true,
-
-	    '+': true,
-	    '-': true,
-	    '*': true,
-	    '.*': true,
-	    '/': true,
-	    './': true,
-	    '%': true,
-	    '^': true,
-	    '.^': true,
-	    '~': true,
-	    '!': true,
-	    '&': true,
-	    '|': true,
-	    '^|': true,
-	    '\'': true,
-	    '=': true,
-	    ':': true,
-	    '?': true,
-
-	    '==': true,
-	    '!=': true,
-	    '<': true,
-	    '>': true,
-	    '<=': true,
-	    '>=': true,
-
-	    '<<': true,
-	    '>>': true,
-	    '>>>': true
-	  };
-
-	  // map with all named delimiters
-	  var NAMED_DELIMITERS = {
-	    'mod': true,
-	    'to': true,
-	    'in': true,
-	    'and': true,
-	    'xor': true,
-	    'or': true,
-	    'not': true
-	  };
-
-	  var extra_nodes = {};             // current extra nodes
-	  var expression = '';              // 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
-	  var nesting_level = 0;            // level of nesting inside parameters, used to ignore newline characters
-	  var conditional_level = null;     // when a conditional is being parsed, the level of the conditional is stored here
-
-	  /**
-	   * Get the first character from the expression.
-	   * The character is stored into the char c. If the end of the expression is
-	   * reached, the function puts an empty string in c.
-	   * @private
-	   */
-	  function first() {
-	    index = 0;
-	    c = expression.charAt(0);
-	    nesting_level = 0;
-	    conditional_level = null;
-	  }
-
-	  /**
-	   * Get the next character from the expression.
-	   * The character is stored into the char c. If the end of the expression is
-	   * reached, the function puts an empty string in c.
-	   * @private
-	   */
-	  function next() {
-	    index++;
-	    c = expression.charAt(index);
-	  }
-
-	  /**
-	   * Preview the next character from the expression.
-	   * @return {String} cNext
-	   * @private
-	   */
-	  function nextPreview() {
-	    return expression.charAt(index + 1);
-	  }
-
-	  /**
-	   * Preview the second next character from the expression.
-	   * @return {String} cNext
-	   * @private
-	   */
-	  function nextNextPreview() {
-	    return expression.charAt(index + 2);
-	  }
-
-	  /**
-	   * Get next token in the current string expr.
-	   * The token and token type are available as token and token_type
-	   * @private
-	   */
-	  function getToken() {
-	    token_type = TOKENTYPE.NULL;
-	    token = '';
-
-	    // skip over whitespaces
-	    // space, tab, and newline when inside parameters
-	    while (c == ' ' || c == '\t' || (c == '\n' && nesting_level)) {
-	      // TODO: also take '\r' carriage return as newline? Or does that give problems on mac?
-	      next();
-	    }
-
-	    // skip comment
-	    if (c == '#') {
-	      while (c != '\n' && c != '') {
-	        next();
-	      }
-	    }
-
-	    // check for end of expression
-	    if (c == '') {
-	      // token is still empty
-	      token_type = TOKENTYPE.DELIMITER;
-	      return;
-	    }
-
-	    // check for new line character
-	    if (c == '\n' && !nesting_level) {
-	      token_type = TOKENTYPE.DELIMITER;
-	      token = c;
-	      next();
-	      return;
-	    }
-
-	    // check for delimiters consisting of 3 characters
-	    var c2 = c + nextPreview();
-	    var c3 = c2 + nextNextPreview();
-	    if (c3.length == 3 && DELIMITERS[c3]) {
-	      token_type = TOKENTYPE.DELIMITER;
-	      token = c3;
-	      next();
-	      next();
-	      next();
-	      return;
-	    }
-
-	    // check for delimiters consisting of 2 characters
-	    if (c2.length == 2 && DELIMITERS[c2]) {
-	      token_type = TOKENTYPE.DELIMITER;
-	      token = c2;
-	      next();
-	      next();
-	      return;
-	    }
-
-	    // check for delimiters consisting of 1 character
-	    if (DELIMITERS[c]) {
-	      token_type = TOKENTYPE.DELIMITER;
-	      token = c;
-	      next();
-	      return;
-	    }
-
-	    // check for a number
-	    if (isDigitDot(c)) {
-	      token_type = TOKENTYPE.NUMBER;
-
-	      // get number, can have a single dot
-	      if (c == '.') {
-	        token += c;
-	        next();
-
-	        if (!isDigit(c)) {
-	          // this is no legal number, it is just a dot
-	          token_type = TOKENTYPE.UNKNOWN;
-	        }
-	      }
-	      else {
-	        while (isDigit(c)) {
-	          token += c;
-	          next();
-	        }
-	        if (c == '.') {
-	          token += c;
-	          next();
-	        }
-	      }
-	      while (isDigit(c)) {
-	        token += c;
-	        next();
-	      }
-
-	      // check for exponential notation like "2.3e-4", "1.23e50" or "2e+4"
-	      c2 = nextPreview();
-	      if ((c == 'E' || c == 'e') && (isDigit(c2) || c2 == '-' || c2 == '+')) {
-	        token += c;
-	        next();
-
-	        if (c == '+' || c == '-') {
-	          token += c;
-	          next();
-	        }
-
-	        // 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;
-	          next();
-	        }
-	      }
-
-	      return;
-	    }
-
-	    // check for variables, functions, named operators
-	    if (isAlpha(c)) {
-	      while (isAlpha(c) || isDigit(c)) {
-	        token += c;
-	        next();
-	      }
-
-	      if (NAMED_DELIMITERS[token]) {
-	        token_type = TOKENTYPE.DELIMITER;
-	      }
-	      else {
-	        token_type = TOKENTYPE.SYMBOL;
-	      }
-
-	      return;
-	    }
-
-	    // something unknown is found, wrong characters -> a syntax error
-	    token_type = TOKENTYPE.UNKNOWN;
-	    while (c != '') {
-	      token += c;
-	      next();
-	    }
-	    throw createSyntaxError('Syntax error in part "' + token + '"');
-	  }
-
-	  /**
-	   * Get next token and skip newline tokens
-	   */
-	  function getTokenSkipNewline () {
-	    do {
-	      getToken();
-	    }
-	    while (token == '\n');
-	  }
-
-	  /**
-	   * Open parameters.
-	   * New line characters will be ignored until closeParams() is called
-	   */
-	  function openParams() {
-	    nesting_level++;
-	  }
-
-	  /**
-	   * Close parameters.
-	   * New line characters will no longer be ignored
-	   */
-	  function closeParams() {
-	    nesting_level--;
-	  }
-
-	  /**
-	   * 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
-	   * @return {Node} node
-	   * @private
-	   */
-	  function parseStart () {
-	    // get the first character in expression
-	    first();
-
-	    getToken();
-
-	    var node = parseBlock();
-
-	    // 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('Unexpected 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.
-	   * @return {Node} node
-	   * @private
-	   */
-	  function parseBlock () {
-	    var node;
-	    var blocks = [];
-	    var visible;
-
-	    if (token == '') {
-	      // empty expression
-	      return new ConstantNode('undefined', 'undefined');
-	    }
-
-	    if (token != '\n' && token != ';') {
-	      node = parseFunctionAssignment();
-	    }
-
-	    // TODO: simplify this loop
-	    while (token == '\n' || token == ';') {
-	      if (blocks.length == 0 && node) {
-	        visible = (token != ';');
-	        blocks.push({
-	          node: node,
-	          visible: visible
-	        });
-	      }
-
-	      getToken();
-	      if (token != '\n' && token != ';' && token != '') {
-	        node = parseFunctionAssignment();
-
-	        visible = (token != ';');
-	        blocks.push({
-	          node: node,
-	          visible: visible
-	        });
-	      }
-	    }
-
-	    if (blocks.length > 0) {
-	      return new BlockNode(blocks);
-	    }
-	    else {
-	      return node;
-	    }
-	  }
-
-	  /**
-	   * Parse a function assignment like "function f(a,b) = a*b"
-	   * @return {Node} node
-	   * @private
-	   */
-	  function parseFunctionAssignment () {
-	    // TODO: function assignment using keyword 'function' is deprecated since version 0.18.0, cleanup some day
-	    if (token_type == TOKENTYPE.SYMBOL && token == 'function') {
-	      throw createSyntaxError('Deprecated keyword "function". ' +
-	          'Functions can now be assigned without it, like "f(x) = x^2".');
-	    }
-
-	    return parseAssignment();
-	  }
-
-	  /**
-	   * 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]"
-	   * @return {Node} node
-	   * @private
-	   */
-	  function parseAssignment () {
-	    var name, args, expr, valid;
-
-	    var node = parseConditional();
-
-	    if (token == '=') {
-	      if (node instanceof SymbolNode) {
-	        // parse a variable assignment like 'a = 2/3'
-	        name = node.name;
-	        getTokenSkipNewline();
-	        expr = parseAssignment();
-	        return new AssignmentNode(name, expr);
-	      }
-	      else if (node instanceof IndexNode) {
-	        // parse a matrix subset assignment like 'A[1,2] = 4'
-	        getTokenSkipNewline();
-	        expr = parseAssignment();
-	        return new UpdateNode(node, expr);
-	      }
-	      else if (node instanceof FunctionNode) {
-	        // parse function assignment like 'f(x) = x^2'
-	        valid = true;
-	        args = [];
-
-	        name = node.name;
-	        node.args.forEach(function (arg, index) {
-	          if (arg instanceof SymbolNode) {
-	            args[index] = arg.name;
-	          }
-	          else {
-	            valid = false;
-	          }
-	        });
-
-	        if (valid) {
-	          getTokenSkipNewline();
-	          expr = parseAssignment();
-	          return new FunctionAssignmentNode(name, args, expr);
-	        }
-	      }
-
-	      throw createSyntaxError('Invalid left hand side of assignment operator =');
-	    }
-
-	    return node;
-	  }
-
-	  /**
-	   * conditional operation
-	   *
-	   *     condition ? truePart : falsePart
-	   *
-	   * Note: conditional operator is right-associative
-	   *
-	   * @return {Node} node
-	   * @private
-	   */
-	  function parseConditional () {
-	    var node = parseLogicalOr();
-
-	    while (token == '?') {
-	      // set a conditional level, the range operator will be ignored as long
-	      // as conditional_level == nesting_level.
-	      var prev = conditional_level;
-	      conditional_level = nesting_level;
-	      getTokenSkipNewline();
-
-	      var condition = node;
-	      var trueExpr = parseLogicalOr();
-
-	      if (token != ':') throw createSyntaxError('False part of conditional expression expected');
-
-	      conditional_level = null;
-	      getTokenSkipNewline();
-
-	      var falseExpr = parseConditional(); // Note: check for conditional operator again, right associativity
-
-	      node = new ConditionalNode(condition, trueExpr, falseExpr);
-
-	      // restore the previous conditional level
-	      conditional_level = prev;
-	    }
-
-	    return node;
-	  }
-
-	  /**
-	   * logical or, 'x or y'
-	   * @return {Node} node
-	   * @private
-	   */
-	  function parseLogicalOr() {
-	    var node = parseLogicalXor();
-
-	    while (token == 'or') {
-	      getTokenSkipNewline();
-	      node = new OperatorNode('or', 'or', [node, parseLogicalXor()]);
-	    }
-
-	    return node;
-	  }
-
-	  /**
-	   * logical exclusive or, 'x xor y'
-	   * @return {Node} node
-	   * @private
-	   */
-	  function parseLogicalXor() {
-	    var node = parseLogicalAnd();
-
-	    while (token == 'xor') {
-	      getTokenSkipNewline();
-	      node = new OperatorNode('xor', 'xor', [node, parseLogicalAnd()]);
-	    }
-
-	    return node;
-	  }
-
-	  /**
-	   * logical and, 'x and y'
-	   * @return {Node} node
-	   * @private
-	   */
-	  function parseLogicalAnd() {
-	    var node = parseBitwiseOr();
-
-	    while (token == 'and') {
-	      getTokenSkipNewline();
-	      node = new OperatorNode('and', 'and', [node, parseBitwiseOr()]);
-	    }
-
-	    return node;
-	  }
-
-	  /**
-	   * bitwise or, 'x | y'
-	   * @return {Node} node
-	   * @private
-	   */
-	  function parseBitwiseOr() {
-	    var node = parseBitwiseXor();
-
-	    while (token == '|') {
-	      getTokenSkipNewline();
-	      node = new OperatorNode('|', 'bitOr', [node, parseBitwiseXor()]);
-	    }
-
-	    return node;
-	  }
-
-	  /**
-	   * bitwise exclusive or (xor), 'x ^| y'
-	   * @return {Node} node
-	   * @private
-	   */
-	  function parseBitwiseXor() {
-	    var node = parseBitwiseAnd();
-
-	    while (token == '^|') {
-	      getTokenSkipNewline();
-	      node = new OperatorNode('^|', 'bitXor', [node, parseBitwiseAnd()]);
-	    }
-
-	    return node;
-	  }
-
-	  /**
-	   * bitwise and, 'x & y'
-	   * @return {Node} node
-	   * @private
-	   */
-	  function parseBitwiseAnd () {
-	    var node = parseRelational();
-
-	    while (token == '&') {
-	      getTokenSkipNewline();
-	      node = new OperatorNode('&', 'bitAnd', [node, parseRelational()]);
-	    }
-
-	    return node;
-	  }
-
-	  /**
-	   * relational operators
-	   * @return {Node} node
-	   * @private
-	   */
-	  function parseRelational () {
-	    var node, operators, name, fn, params;
-
-	    node = parseShift();
-
-	    operators = {
-	      '==': 'equal',
-	      '!=': 'unequal',
-	      '<': 'smaller',
-	      '>': 'larger',
-	      '<=': 'smallerEq',
-	      '>=': 'largerEq'
-	    };
-	    while (token in operators) {
-	      name = token;
-	      fn = operators[name];
-
-	      getTokenSkipNewline();
-	      params = [node, parseShift()];
-	      node = new OperatorNode(name, fn, params);
-	    }
-
-	    return node;
-	  }
-
-	  /**
-	   * Bitwise left shift, bitwise right arithmetic shift, bitwise right logical shift
-	   * @return {Node} node
-	   * @private
-	   */
-	  function parseShift () {
-	    var node, operators, name, fn, params;
-
-	    node = parseConversion();
-
-	    operators = {
-	      '<<' : 'leftShift',
-	      '>>' : 'rightArithShift',
-	      '>>>' : 'rightLogShift'
-	    };
-
-	    while (token in operators) {
-	      name = token;
-	      fn = operators[name];
-
-	      getTokenSkipNewline();
-	      params = [node, parseConversion()];
-	      node = new OperatorNode(name, fn, params);
-	    }
-
-	    return node;
-	  }
-
-	  /**
-	   * conversion operators 'to' and 'in'
-	   * @return {Node} node
-	   * @private
-	   */
-	  function parseConversion () {
-	    var node, operators, name, fn, params;
-
-	    node = parseRange();
-
-	    operators = {
-	      'to' : 'to',
-	      'in' : 'to'   // alias of 'to'
-	    };
-
-	    while (token in operators) {
-	      name = token;
-	      fn = operators[name];
-
-	      getTokenSkipNewline();
-	      params = [node, parseRange()];
-	      node = new OperatorNode(name, fn, params);
-	    }
-
-	    return node;
-	  }
-
-	  /**
-	   * parse range, "start:end", "start:step:end", ":", "start:", ":end", etc
-	   * @return {Node} node
-	   * @private
-	   */
-	  function parseRange () {
-	    var node, params = [];
-
-	    if (token == ':') {
-	      // implicit start=1 (one-based)
-	      node = new ConstantNode('1', 'number');
-	    }
-	    else {
-	      // explicit start
-	      node = parseAddSubtract();
-	    }
-
-	    if (token == ':' && (conditional_level !== nesting_level)) {
-	      // we ignore the range operator when a conditional operator is being processed on the same level
-	      params.push(node);
-
-	      // parse step and end
-	      while (token == ':' && params.length < 3) {
-	        getTokenSkipNewline();
-
-	        if (token == ')' || token == ']' || token == ',' || token == '') {
-	          // implicit end
-	          params.push(new SymbolNode('end'));
-	        }
-	        else {
-	          // explicit end
-	          params.push(parseAddSubtract());
-	        }
-	      }
-
-	      if (params.length == 3) {
-	        // params = [start, step, end]
-	        node = new RangeNode(params[0], params[2], params[1]); // start, end, step
-	      }
-	      else { // length == 2
-	        // params = [start, end]
-	        node = new RangeNode(params[0], params[1]); // start, end
-	      }
-	    }
-
-	    return node;
-	  }
-
-	  /**
-	   * add or subtract
-	   * @return {Node} node
-	   * @private
-	   */
-	  function parseAddSubtract ()  {
-	    var node, operators, name, fn, params;
-
-	    node = parseMultiplyDivide();
-
-	    operators = {
-	      '+': 'add',
-	      '-': 'subtract'
-	    };
-	    while (token in operators) {
-	      name = token;
-	      fn = operators[name];
-
-	      getTokenSkipNewline();
-	      params = [node, parseMultiplyDivide()];
-	      node = new OperatorNode(name, fn, params);
-	    }
-
-	    return node;
-	  }
-
-	  /**
-	   * multiply, divide, modulus
-	   * @return {Node} node
-	   * @private
-	   */
-	  function parseMultiplyDivide () {
-	    var node, operators, name, fn, params;
-
-	    node = parseUnary();
-
-	    operators = {
-	      '*': 'multiply',
-	      '.*': 'dotMultiply',
-	      '/': 'divide',
-	      './': 'dotDivide',
-	      '%': 'mod',
-	      'mod': 'mod'
-	    };
-
-	    if (token in operators) {
-	      while (token in operators) {
-	        name = token;
-	        fn = operators[name];
-
-	        getTokenSkipNewline();
-	        params = [node, parseUnary()];
-	        node = new OperatorNode(name, fn, params);
-	      }
-	    }
-
-	    // parse implicit multiplication
-	    if ((token_type == TOKENTYPE.SYMBOL) ||
-	        (token == 'in' && (node instanceof ConstantNode)) ||
-	        (token_type == TOKENTYPE.NUMBER && !(node instanceof ConstantNode)) ||
-	        (token == '(' || token == '[')) {
-	      // symbol:      implicit multiplication like '2a', '(2+3)a', 'a b'
-	      // number:      implicit multiplication like '(2+3)2'
-	      //              Note: we don't allow implicit multiplication between numbers,
-	      //              like '2 3'. I'm not sure whether that is a good idea.
-	      // parenthesis: implicit multiplication like '2(3+4)', '(3+4)(1+2)', '2[1,2,3]'
-	      node = new OperatorNode('*', 'multiply', [node, parseMultiplyDivide()]);
-	    }
-
-	    return node;
-	  }
-
-	  /**
-	   * Unary plus and minus, and logical and bitwise not
-	   * @return {Node} node
-	   * @private
-	   */
-	  function parseUnary () {
-	    var name, params;
-	    var fn = {
-	      '-': 'unaryMinus',
-	      '+': 'unaryPlus',
-	      '~': 'bitNot',
-	      'not': 'not'
-	    }[token];
-
-	    if (fn) {
-	      name = token;
-
-	      getTokenSkipNewline();
-	      params = [parseUnary()];
-
-	      return new OperatorNode(name, fn, params);
-	    }
-
-	    return parsePow();
-	  }
-
-	  /**
-	   * power
-	   * Note: power operator is right associative
-	   * @return {Node} node
-	   * @private
-	   */
-	  function parsePow () {
-	    var node, name, fn, params;
-
-	    node = parseLeftHandOperators();
-
-	    if (token == '^' || token == '.^') {
-	      name = token;
-	      fn = (name == '^') ? 'pow' : 'dotPow';
-
-	      getTokenSkipNewline();
-	      params = [node, parseUnary()]; // Go back to unary, we can have '2^-3'
-	      node = new OperatorNode(name, fn, params);
-	    }
-
-	    return node;
-	  }
-
-	  /**
-	   * Left hand operators: factorial x!, transpose x'
-	   * @return {Node} node
-	   * @private
-	   */
-	  function parseLeftHandOperators ()  {
-	    var node, operators, name, fn, params;
-
-	    node = parseCustomNodes();
-
-	    operators = {
-	      '!': 'factorial',
-	      '\'': 'transpose'
-	    };
-
-	    while (token in operators) {
-	      name = token;
-	      fn = operators[name];
-
-	      getToken();
-	      params = [node];
-
-	      node = new OperatorNode(name, fn, params);
-	    }
-
-	    return node;
-	  }
-
-	  /**
-	   * Parse a custom node handler. A node handler can be used to process
-	   * nodes in a custom way, for example for handling a plot.
-	   *
-	   * A handler must be passed as second argument of the parse function.
-	   * - must extend math.expression.node.Node
-	   * - must contain a function _compile(defs: Object) : String
-	   * - must contain a function find(filter: Object) : Node[]
-	   * - must contain a function toString() : String
-	   * - the constructor is called with a single argument containing all parameters
-	   *
-	   * For example:
-	   *
-	   *     nodes = {
-	   *       'plot': PlotHandler
-	   *     };
-	   *
-	   * The constructor of the handler is called as:
-	   *
-	   *     node = new PlotHandler(params);
-	   *
-	   * The handler will be invoked when evaluating an expression like:
-	   *
-	   *     node = math.parse('plot(sin(x), x)', nodes);
-	   *
-	   * @return {Node} node
-	   * @private
-	   */
-	  function parseCustomNodes () {
-	    var params = [], handler;
-
-	    if (token_type == TOKENTYPE.SYMBOL && extra_nodes[token]) {
-	      handler = extra_nodes[token];
-
-	      getToken();
-
-	      // parse parameters
-	      if (token == '(') {
-	        params = [];
-
-	        openParams();
-	        getToken();
-
-	        if (token != ')') {
-	          params.push(parseConditional());
-
-	          // parse a list with parameters
-	          while (token == ',') {
-	            getToken();
-	            params.push(parseConditional());
-	          }
-	        }
-
-	        if (token != ')') {
-	          throw createSyntaxError('Parenthesis ) expected');
-	        }
-	        closeParams();
-	        getToken();
-	      }
-
-	      // create a new node handler
-	      //noinspection JSValidateTypes
-	      return new handler(params);
-	    }
-
-	    return parseSymbol();
-	  }
-
-	  /**
-	   * parse symbols: functions, variables, constants, units
-	   * @return {Node} node
-	   * @private
-	   */
-	  function parseSymbol () {
-	    var node, name;
-
-	    if (token_type == TOKENTYPE.SYMBOL ||
-	        (token_type == TOKENTYPE.DELIMITER && token in NAMED_DELIMITERS)) {
-	      name = token;
-
-	      getToken();
-
-	      // parse function parameters and matrix index
-	      node = parseFunctions(name);
-	      node = parseIndex(node);
-	      return node;
-	    }
-
-	    return parseString();
-	  }
-
-	  /**
-	   * parse a function call like fn(a, b, c)
-	   * @param {string} name    Function name
-	   * @return {FunctionNode | SymbolNode} node
-	   * @private
-	   */
-	  function parseFunctions (name) {
-	    var params;
-
-	    if (token == '(') {
-	      params = [];
-
-	      openParams();
-	      getToken();
-
-	      if (token != ')') {
-	        params.push(parseConditional());
-
-	        // parse a list with parameters
-	        while (token == ',') {
-	          getToken();
-	          params.push(parseConditional());
-	        }
-	      }
-
-	      if (token != ')') {
-	        throw createSyntaxError('Parenthesis ) expected');
-	      }
-	      closeParams();
-	      getToken();
-
-	      return new FunctionNode(name, params);
-	    }
-
-	    return new SymbolNode(name);
-	  }
-
-	  /**
-	   * parse index parameters, enclosed in square brackets [...], for example A[2,3]
-	   * @param {Node} node    Node on which to apply the parameters. If there
-	   *                       are no parameters in the expression, the node
-	   *                       itself is returned
-	   * @return {Node} node
-	   * @private
-	   */
-	  function parseIndex (node) {
-	    var params;
-
-	    while (token == '[') {
-	      params = [];
-
-	      openParams();
-	      getToken();
-
-	      if (token != ']') {
-	        params.push(parseConditional());
-
-	        // parse a list with parameters
-	        while (token == ',') {
-	          getToken();
-	          params.push(parseConditional());
-	        }
-	      }
-
-	      if (token != ']') {
-	        throw createSyntaxError('Parenthesis ] expected');
-	      }
-	      closeParams();
-	      getToken();
-
-	      node = new IndexNode(node, params);
-	    }
-
-	    return node;
-	  }
-
-	  /**
-	   * parse a string.
-	   * A string is enclosed by double quotes
-	   * @return {Node} node
-	   * @private
-	   */
-	  function parseString () {
-	    var node, str, tPrev;
-
-	    if (token == '"') {
-	      // string "..."
-	      str = '';
-	      tPrev = '';
-	      while (c != '' && (c != '\"' || tPrev == '\\')) { // also handle escape character
-	        str += c;
-	        tPrev = c;
-	        next();
-	      }
-
-	      getToken();
-	      if (token != '"') {
-	        throw createSyntaxError('End of string " expected');
-	      }
-	      getToken();
-
-	      // create constant
-	      node = new ConstantNode(str, 'string');
-
-	      // parse index parameters
-	      node = parseIndex(node);
-
-	      return node;
-	    }
-
-	    return parseMatrix();
-	  }
-
-	  /**
-	   * parse the matrix
-	   * @return {Node} node
-	   * @private
-	   */
-	  function parseMatrix () {
-	    var array, params, rows, cols;
-
-	    if (token == '[') {
-	      // matrix [...]
-	      openParams();
-	      getToken();
-
-	      if (token != ']') {
-	        // this is a non-empty matrix
-	        var row = parseRow();
-
-	        if (token == ';') {
-	          // 2 dimensional array
-	          rows = 1;
-	          params = [row];
-
-	          // the rows of the matrix are separated by dot-comma's
-	          while (token == ';') {
-	            getToken();
-
-	            params[rows] = parseRow();
-	            rows++;
-	          }
-
-	          if (token != ']') {
-	            throw createSyntaxError('End of matrix ] expected');
-	          }
-	          closeParams();
-	          getToken();
-
-	          // check if the number of columns matches in all rows
-	          cols = params[0].nodes.length;
-	          for (var r = 1; r < rows; r++) {
-	            if (params[r].nodes.length != cols) {
-	              throw createError('Column dimensions mismatch ' +
-	                  '(' + params[r].nodes.length + ' != ' + cols + ')');
-	            }
-	          }
-
-	          array = new ArrayNode(params);
-	        }
-	        else {
-	          // 1 dimensional vector
-	          if (token != ']') {
-	            throw createSyntaxError('End of matrix ] expected');
-	          }
-	          closeParams();
-	          getToken();
-
-	          array = row;
-	        }
-	      }
-	      else {
-	        // this is an empty matrix "[ ]"
-	        closeParams();
-	        getToken();
-	        array = new ArrayNode([]);
-	      }
-
-	      return array;
-	    }
-
-	    return parseNumber();
-	  }
-
-	  /**
-	   * Parse a single comma-separated row from a matrix, like 'a, b, c'
-	   * @return {ArrayNode} node
-	   */
-	  function parseRow () {
-	    var params = [parseAssignment()];
-	    var len = 1;
-
-	    while (token == ',') {
-	      getToken();
-
-	      // parse expression
-	      params[len] = parseAssignment();
-	      len++;
-	    }
-
-	    return new ArrayNode(params);
-	  }
-
-	  /**
-	   * parse a number
-	   * @return {Node} node
-	   * @private
-	   */
-	  function parseNumber () {
-	    var number;
-
-	    if (token_type == TOKENTYPE.NUMBER) {
-	      // this is a number
-	      number = token;
-	      getToken();
-
-	      return new ConstantNode(number, 'number');
-	    }
-
-	    return parseParentheses();
-	  }
-
-	  /**
-	   * parentheses
-	   * @return {Node} node
-	   * @private
-	   */
-	  function parseParentheses () {
-	    var node;
-
-	    // check if it is a parenthesized expression
-	    if (token == '(') {
-	      // parentheses (...)
-	      openParams();
-	      getToken();
-
-	      node = parseAssignment(); // start again
-
-	      if (token != ')') {
-	        throw createSyntaxError('Parenthesis ) expected');
-	      }
-	      closeParams();
-	      getToken();
-
-	      return node;
-	    }
-
-	    return parseEnd();
-	  }
-
-	  /**
-	   * Evaluated when the expression is not yet ended but expected to end
-	   * @return {Node} res
-	   * @private
-	   */
-	  function parseEnd () {
-	    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
-	   */
-	  /* TODO: implement keeping track on the row number
-	  function row () {
-	    return null;
-	  }
-	  */
-
-	  /**
-	   * 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;
-	  }
-
-	  /**
-	   * Create an error
-	   * @param {String} message
-	   * @return {SyntaxError} instantiated error
-	   * @private
-	   */
-	  function createSyntaxError (message) {
-	    var c = col();
-	    var error = new SyntaxError(message + ' (char ' + c + ')');
-	    error['char'] = c;
-
-	    return error;
-	  }
-
-	  /**
-	   * Create an error
-	   * @param {String} message
-	   * @return {Error} instantiated error
-	   * @private
-	   */
-	  function createError (message) {
-	    var c = col();
-	    var error = new Error(message + ' (char ' + c + ')');
-	    error['char'] = c;
-
-	    return error;
-	  }
-
-	  return parse;
+	/**
+	 * Determine the type of a variable
+	 *
+	 *     type(x)
+	 *
+	 * The following types are recognized:
+	 *
+	 *     'undefined'
+	 *     'null'
+	 *     'boolean'
+	 *     'number'
+	 *     'string'
+	 *     'Array'
+	 *     'Function'
+	 *     'Date'
+	 *     'RegExp'
+	 *     'Object'
+	 *
+	 * @param {*} x
+	 * @return {string} Returns the name of the type. Primitive types are lower case,
+	 *                  non-primitive types are upper-camel-case.
+	 *                  For example 'number', 'string', 'Array', 'Date'.
+	 */
+	exports.type = function(x) {
+	  var type = typeof x;
+
+	  if (type === 'object') {
+	    if (x === null)           return 'null';
+	    if (x instanceof Boolean) return 'boolean';
+	    if (x instanceof Number)  return 'number';
+	    if (x instanceof String)  return 'string';
+	    if (Array.isArray(x))     return 'Array';
+	    if (x instanceof Date)    return 'Date';
+	    if (x instanceof RegExp)  return 'RegExp';
+
+	    return 'Object';
+	  }
+
+	  if (type === 'function')    return 'Function';
+
+	  return type;
 	};
 
+
 /***/ },
 /* 20 */
 /***/ function(module, exports, __webpack_require__) {
 
 	'use strict';
 
-	module.exports = function (math) {
-
-	  var _parse = math.expression.parse;
-
-	  /**
-	   * @constructor Parser
-	   * Parser contains methods to evaluate or parse expressions, and has a number
-	   * of convenience methods to get, set, and remove variables from memory. Parser
-	   * keeps a scope containing variables in memory, which is used for all
-	   * evaluations.
-	   *
-	   * 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
-	   *    parser.remove(name);               // clear a variable from the
-	   *                                       // parsers scope
-	   *    parser.clear();                    // clear the parsers scope
-	   *
-	   * Example usage:
-	   *    var parser = new Parser();
-	   *    // Note: there is a convenience method which can be used instead:
-	   *    // var parser = new math.parser();
-	   *
-	   *    // evaluate expressions
-	   *    parser.eval('sqrt(3^2 + 4^2)');         // 5
-	   *    parser.eval('sqrt(-4)');                // 2i
-	   *    parser.eval('2 inch in cm');            // 5.08 cm
-	   *    parser.eval('cos(45 deg)');             // 0.7071067811865476
-	   *
-	   *    // define variables and functions
-	   *    parser.eval('x = 7 / 2');               // 3.5
-	   *    parser.eval('x + 3');                   // 6.5
-	   *    parser.eval('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();
-	   *
-	   */
-	  function Parser() {
-	    if (!(this instanceof Parser)) {
-	      throw new SyntaxError(
-	          'Constructor must be called with the new operator');
-	    }
-	    this.scope = {};
-	  }
-
-	  /**
-	   * Parse an expression and return the parsed function node.
-	   * The node tree can be compiled via `code = node.compile(math)`,
-	   * and the compiled code can be executed as `code.eval([scope])`
-	   * @param {String} expr
-	   * @return {Node} node
-	   * @throws {Error}
-	   */
-	  Parser.prototype.parse = function (expr) {
-	    throw new Error('Parser.parse is deprecated. Use math.parse instead.');
-	  };
-
-	  /**
-	   * Parse and compile an expression, return the compiled javascript code.
-	   * The node can be evaluated via code.eval([scope])
-	   * @param {String} expr
-	   * @return {{eval: function}} code
-	   * @throws {Error}
-	   */
-	  Parser.prototype.compile = function (expr) {
-	    throw new Error('Parser.compile is deprecated. Use math.compile instead.');
-	  };
-
-	  /**
-	   * Parse and evaluate the given expression
-	   * @param {String} expr   A string containing an expression, for example "2+3"
-	   * @return {*} result     The result, or undefined when the expression was empty
-	   * @throws {Error}
-	   */
-	  Parser.prototype.eval = function (expr) {
-	    // TODO: validate arguments
-	    return _parse(expr)
-	        .compile(math)
-	        .eval(this.scope);
-	  };
-
-	  /**
-	   * Get a variable (a function or variable) by name from the parsers scope.
-	   * Returns undefined when not found
-	   * @param {String} name
-	   * @return {* | undefined} value
-	   */
-	  Parser.prototype.get = function (name) {
-	    // TODO: validate arguments
-	    return this.scope[name];
-	  };
-
-	  /**
-	   * Set a symbol (a function or variable) by name from the parsers scope.
-	   * @param {String} name
-	   * @param {* | undefined} value
-	   */
-	  Parser.prototype.set = function (name, value) {
-	    // TODO: validate arguments
-	    return this.scope[name] = value;
-	  };
-
-	  /**
-	   * Remove a variable from the parsers scope
-	   * @param {String} name
-	   */
-	  Parser.prototype.remove = function (name) {
-	    // TODO: validate arguments
-	    delete this.scope[name];
-	  };
-
-	  /**
-	   * Clear the scope with variables and functions
-	   */
-	  Parser.prototype.clear = function () {
-	    for (var name in this.scope) {
-	      if (this.scope.hasOwnProperty(name)) {
-	        delete this.scope[name];
+	var formatNumber = __webpack_require__(8).format;
+	var formatBigNumber = __webpack_require__(21).format;
+
+	/**
+	 * Test whether value is a string
+	 * @param {*} value
+	 * @return {boolean} isString
+	 */
+	exports.isString = function(value) {
+	  return typeof value === 'string';
+	};
+
+	/**
+	 * Check if a text ends with a certain string.
+	 * @param {string} text
+	 * @param {string} search
+	 */
+	exports.endsWith = function(text, search) {
+	  var start = text.length - search.length;
+	  var end = text.length;
+	  return (text.substring(start, end) === search);
+	};
+
+	/**
+	 * Format a value of any type into a string.
+	 *
+	 * Usage:
+	 *     math.format(value)
+	 *     math.format(value, precision)
+	 *
+	 * If value is a function, the returned string is 'function' unless the function
+	 * has a property `description`, in that case this properties value is returned.
+	 *
+	 * Example usage:
+	 *     math.format(2/7);                // '0.2857142857142857'
+	 *     math.format(math.pi, 3);         // '3.14'
+	 *     math.format(new Complex(2, 3));  // '2 + 3i'
+	 *     math.format('hello');            // '"hello"'
+	 *
+	 * @param {*} value             Value to be stringified
+	 * @param {Object | number | Function} [options]  Formatting options. See
+	 *                                                lib/utils/number:format for a
+	 *                                                description of the available
+	 *                                                options.
+	 * @return {string} str
+	 */
+	exports.format = function(value, options) {
+	  if (typeof value === 'number') {
+	    return formatNumber(value, options);
+	  }
+
+	  if (value && value.isBigNumber === true) {
+	    return formatBigNumber(value, options);
+	  }
+
+	  if (value && value.isFraction === true) {
+	    if (!options || options.fraction !== 'decimal') {
+	      // output as ratio, like '1/3'
+	      return (value.s * value.n) + '/' + value.d;
+	    }
+	    else {
+	      // output as decimal, like '0.(3)'
+	      return value.toString();
+	    }
+	  }
+
+	  if (Array.isArray(value)) {
+	    return formatArray(value, options);
+	  }
+
+	  if (exports.isString(value)) {
+	    return '"' + value + '"';
+	  }
+
+	  if (typeof value === 'function') {
+	    return value.syntax ? value.syntax + '' : 'function';
+	  }
+
+	  if (typeof value === 'object') {
+	    if (typeof value.format === 'function') {
+	      return value.format(options);
+	    }
+	    else {
+	      return value.toString();
+	    }
+	  }
+
+	  return String(value);
+	};
+
+	/**
+	 * Recursively format an n-dimensional matrix
+	 * Example output: "[[1, 2], [3, 4]]"
+	 * @param {Array} array
+	 * @param {Object | number | Function} [options]  Formatting options. See
+	 *                                                lib/utils/number:format for a
+	 *                                                description of the available
+	 *                                                options.
+	 * @returns {string} str
+	 */
+	function formatArray (array, options) {
+	  if (Array.isArray(array)) {
+	    var str = '[';
+	    var len = array.length;
+	    for (var i = 0; i < len; i++) {
+	      if (i != 0) {
+	        str += ', ';
 	      }
+	      str += formatArray(array[i], options);
 	    }
-	  };
+	    str += ']';
+	    return str;
+	  }
+	  else {
+	    return exports.format(array, options);
+	  }
+	}
 
-	  return Parser;
-	};
 
 /***/ },
 /* 21 */
-/***/ function(module, exports, __webpack_require__) {
-
-	// constants
-	exports.e = __webpack_require__(190);
-	exports.E = __webpack_require__(190);
-	exports['false'] = __webpack_require__(191);
-	exports.i = __webpack_require__(192);
-	exports['Infinity'] = __webpack_require__(193);
-	exports.LN2 = __webpack_require__(194);
-	exports.LN10 = __webpack_require__(195);
-	exports.LOG2E = __webpack_require__(196);
-	exports.LOG10E = __webpack_require__(197);
-	exports.NaN = __webpack_require__(198);
-	exports['null'] = __webpack_require__(199);
-	exports.pi = __webpack_require__(200);
-	exports.PI = __webpack_require__(200);
-	exports.phi = __webpack_require__(201);
-	exports.SQRT1_2 = __webpack_require__(202);
-	exports.SQRT2 = __webpack_require__(203);
-	exports.tau = __webpack_require__(204);
-	exports['true'] = __webpack_require__(205);
-	exports.version = __webpack_require__(206);
-
-	// functions - arithmetic
-	exports.abs = __webpack_require__(210);
-	exports.add = __webpack_require__(211);
-	exports.ceil = __webpack_require__(212);
-	exports.cube = __webpack_require__(213);
-	exports.divide = __webpack_require__(214);
-	exports.dotDivide = __webpack_require__(215);
-	exports.dotMultiply = __webpack_require__(216);
-	exports.dotPow = __webpack_require__(217);
-	exports.exp = __webpack_require__(218);
-	exports.fix = __webpack_require__(219);
-	exports.floor = __webpack_require__(220);
-	exports.gcd = __webpack_require__(221);
-	exports.lcm = __webpack_require__(222);
-	exports.log = __webpack_require__(223);
-	exports.log10 = __webpack_require__(224);
-	exports.mod = __webpack_require__(225);
-	exports.multiply = __webpack_require__(226);
-	exports.norm = __webpack_require__(227);
-	exports.nthRoot = __webpack_require__(228);
-	exports.pow = __webpack_require__(229);
-	exports.round = __webpack_require__(230);
-	exports.sign = __webpack_require__(231);
-	exports.sqrt = __webpack_require__(232);
-	exports.square = __webpack_require__(233);
-	exports.subtract = __webpack_require__(234);
-	exports.unaryMinus = __webpack_require__(235);
-	exports.unaryPlus = __webpack_require__(236);
-	exports.xgcd = __webpack_require__(237);
-
-	// functions - bitwise
-	exports.bitAnd = __webpack_require__(238);
-	exports.bitNot = __webpack_require__(239);
-	exports.bitOr = __webpack_require__(240);
-	exports.bitXor = __webpack_require__(241);
-	exports.leftShift = __webpack_require__(242);
-	exports.rightArithShift = __webpack_require__(243);
-	exports.rightLogShift = __webpack_require__(244);
-
-	// functions - complex
-	exports.arg = __webpack_require__(245);
-	exports.conj = __webpack_require__(246);
-	exports.re = __webpack_require__(247);
-	exports.im = __webpack_require__(248);
-
-	// functions - construction
-	exports.bignumber = __webpack_require__(249);
-	exports['boolean'] = __webpack_require__(250);
-	exports.complex = __webpack_require__(251);
-	exports.index = __webpack_require__(252);
-	exports.matrix = __webpack_require__(253);
-	exports.number = __webpack_require__(254);
-	exports.string = __webpack_require__(255);
-	exports.unit = __webpack_require__(256);
-
-	// functions - expression
-	exports['eval'] =  __webpack_require__(257);
-	exports.help =  __webpack_require__(258);
-
-	// functions - logical
-	exports['and'] = __webpack_require__(259);
-	exports['not'] = __webpack_require__(260);
-	exports['or'] = __webpack_require__(261);
-	exports['xor'] = __webpack_require__(262);
-
-	// functions - matrix
-	exports['concat'] = __webpack_require__(263);
-	exports.cross = __webpack_require__(264);
-	exports.det = __webpack_require__(265);
-	exports.diag = __webpack_require__(266);
-	exports.dot = __webpack_require__(267);
-	exports.eye = __webpack_require__(268);
-	exports.flatten = __webpack_require__(269);
-	exports.inv = __webpack_require__(270);
-	exports.ones = __webpack_require__(271);
-	exports.range = __webpack_require__(272);
-	exports.resize = __webpack_require__(273);
-	exports.size = __webpack_require__(274);
-	exports.squeeze = __webpack_require__(275);
-	exports.subset = __webpack_require__(276);
-	exports.trace = __webpack_require__(277);
-	exports.transpose = __webpack_require__(278);
-	exports.zeros = __webpack_require__(279);
-
-	// functions - probability
-	exports.combinations = __webpack_require__(280);
-	//exports.distribution = require('./function/probability/distribution');
-	exports.factorial = __webpack_require__(281);
-	exports.gamma = __webpack_require__(282);
-	exports.permutations = __webpack_require__(283);
-	exports.pickRandom = __webpack_require__(284);
-	exports.random = __webpack_require__(285);
-	exports.randomInt = __webpack_require__(286);
-
-	// functions - relational
-	exports.compare = __webpack_require__(287);
-	exports.deepEqual = __webpack_require__(288);
-	exports['equal'] = __webpack_require__(289);
-	exports.larger = __webpack_require__(290);
-	exports.largerEq = __webpack_require__(291);
-	exports.smaller = __webpack_require__(292);
-	exports.smallerEq = __webpack_require__(293);
-	exports.unequal = __webpack_require__(294);
-
-	// functions - statistics
-	exports.max = __webpack_require__(295);
-	exports.mean = __webpack_require__(296);
-	exports.median = __webpack_require__(297);
-	exports.min = __webpack_require__(298);
-	exports.prod = __webpack_require__(299);
-	exports.std = __webpack_require__(300);
-	exports.sum = __webpack_require__(301);
-	exports['var'] = __webpack_require__(302);
-
-	// functions - trigonometry
-	exports.acos = __webpack_require__(303);
-	exports.acosh = __webpack_require__(304);
-	exports.acot = __webpack_require__(305);
-	exports.acoth = __webpack_require__(306);
-	exports.acsc = __webpack_require__(307);
-	exports.acsch = __webpack_require__(308);
-	exports.asec = __webpack_require__(309);
-	exports.asech = __webpack_require__(310);
-	exports.asin = __webpack_require__(311);
-	exports.asinh = __webpack_require__(312);
-	exports.atan = __webpack_require__(313);
-	exports.atanh = __webpack_require__(314);
-	exports.atan2 = __webpack_require__(315);
-	exports.cos = __webpack_require__(316);
-	exports.cosh = __webpack_require__(317);
-	exports.cot = __webpack_require__(318);
-	exports.coth = __webpack_require__(319);
-	exports.csc = __webpack_require__(320);
-	exports.csch = __webpack_require__(321);
-	exports.sec = __webpack_require__(322);
-	exports.sech = __webpack_require__(323);
-	exports.sin = __webpack_require__(324);
-	exports.sinh = __webpack_require__(325);
-	exports.tan = __webpack_require__(326);
-	exports.tanh = __webpack_require__(327);
-
-	// functions - units
-	exports.to = __webpack_require__(328);
-
-	// functions - utils
-	exports.clone =  __webpack_require__(329);
-	exports.map =  __webpack_require__(330);
-	exports.filter =  __webpack_require__(331);
-	exports.forEach =  __webpack_require__(332);
-	exports.format =  __webpack_require__(333);
-	// exports.print =  require('./function/utils/print'); // TODO: add documentation for print as soon as the parser supports objects.
-	exports['import'] =  __webpack_require__(334);
-	exports.sort =  __webpack_require__(335);
-	exports['typeof'] =  __webpack_require__(336);
+/***/ function(module, exports) {
+
+	/**
+	 * Convert a BigNumber to a formatted string representation.
+	 *
+	 * Syntax:
+	 *
+	 *    format(value)
+	 *    format(value, options)
+	 *    format(value, precision)
+	 *    format(value, fn)
+	 *
+	 * Where:
+	 *
+	 *    {number} value   The value to be formatted
+	 *    {Object} options An object with formatting options. Available options:
+	 *                     {string} notation
+	 *                         Number notation. Choose from:
+	 *                         'fixed'          Always use regular number notation.
+	 *                                          For example '123.40' and '14000000'
+	 *                         'exponential'    Always use exponential notation.
+	 *                                          For example '1.234e+2' and '1.4e+7'
+	 *                         'auto' (default) Regular number notation for numbers
+	 *                                          having an absolute value between
+	 *                                          `lower` and `upper` bounds, and uses
+	 *                                          exponential notation elsewhere.
+	 *                                          Lower bound is included, upper bound
+	 *                                          is excluded.
+	 *                                          For example '123.4' and '1.4e7'.
+	 *                     {number} precision   A number between 0 and 16 to round
+	 *                                          the digits of the number.
+	 *                                          In case of notations 'exponential' and
+	 *                                          'auto', `precision` defines the total
+	 *                                          number of significant digits returned
+	 *                                          and is undefined by default.
+	 *                                          In case of notation 'fixed',
+	 *                                          `precision` defines the number of
+	 *                                          significant digits after the decimal
+	 *                                          point, and is 0 by default.
+	 *                     {Object} exponential An object containing two parameters,
+	 *                                          {number} lower and {number} upper,
+	 *                                          used by notation 'auto' to determine
+	 *                                          when to return exponential notation.
+	 *                                          Default values are `lower=1e-3` and
+	 *                                          `upper=1e5`.
+	 *                                          Only applicable for notation `auto`.
+	 *    {Function} fn    A custom formatting function. Can be used to override the
+	 *                     built-in notations. Function `fn` is called with `value` as
+	 *                     parameter and must return a string. Is useful for example to
+	 *                     format all values inside a matrix in a particular way.
+	 *
+	 * Examples:
+	 *
+	 *    format(6.4);                                        // '6.4'
+	 *    format(1240000);                                    // '1.24e6'
+	 *    format(1/3);                                        // '0.3333333333333333'
+	 *    format(1/3, 3);                                     // '0.333'
+	 *    format(21385, 2);                                   // '21000'
+	 *    format(12.071, {notation: 'fixed'});                // '12'
+	 *    format(2.3,    {notation: 'fixed', precision: 2});  // '2.30'
+	 *    format(52.8,   {notation: 'exponential'});          // '5.28e+1'
+	 *
+	 * @param {BigNumber} value
+	 * @param {Object | Function | number} [options]
+	 * @return {string} str The formatted value
+	 */
+	exports.format = function (value, options) {
+	  if (typeof options === 'function') {
+	    // handle format(value, fn)
+	    return options(value);
+	  }
+
+	  // handle special cases
+	  if (!value.isFinite()) {
+	    return value.isNaN() ? 'NaN' : (value.gt(0) ? 'Infinity' : '-Infinity');
+	  }
+
+	  // default values for options
+	  var notation = 'auto';
+	  var precision = undefined;
+
+	  if (options !== undefined) {
+	    // determine notation from options
+	    if (options.notation) {
+	      notation = options.notation;
+	    }
+
+	    // determine precision from options
+	    if (typeof options === 'number') {
+	      precision = options;
+	    }
+	    else if (options.precision) {
+	      precision = options.precision;
+	    }
+	  }
+
+	  // handle the various notations
+	  switch (notation) {
+	    case 'fixed':
+	      return exports.toFixed(value, precision);
+
+	    case 'exponential':
+	      return exports.toExponential(value, precision);
+
+	    case 'auto':
+	      // determine lower and upper bound for exponential notation.
+	      // TODO: implement support for upper and lower to be BigNumbers themselves
+	      var lower = 1e-3;
+	      var upper = 1e5;
+	      if (options && options.exponential) {
+	        if (options.exponential.lower !== undefined) {
+	          lower = options.exponential.lower;
+	        }
+	        if (options.exponential.upper !== undefined) {
+	          upper = options.exponential.upper;
+	        }
+	      }
+
+	      // adjust the configuration of the BigNumber constructor (yeah, this is quite tricky...)
+	      var oldConfig = {
+	        toExpNeg: value.constructor.toExpNeg,
+	        toExpPos: value.constructor.toExpPos
+	      };
+
+	      value.constructor.config({
+	        toExpNeg: Math.round(Math.log(lower) / Math.LN10),
+	        toExpPos: Math.round(Math.log(upper) / Math.LN10)
+	      });
+
+	      // handle special case zero
+	      if (value.isZero()) return '0';
+
+	      // determine whether or not to output exponential notation
+	      var str;
+	      var abs = value.abs();
+	      if (abs.gte(lower) && abs.lt(upper)) {
+	        // normal number notation
+	        str = value.toSignificantDigits(precision).toFixed();
+	      }
+	      else {
+	        // exponential notation
+	        str = exports.toExponential(value, precision);
+	      }
+
+	      // remove trailing zeros after the decimal point
+	      return str.replace(/((\.\d*?)(0+))($|e)/, function () {
+	        var digits = arguments[2];
+	        var e = arguments[4];
+	        return (digits !== '.') ? digits + e : e;
+	      });
+
+	    default:
+	      throw new Error('Unknown notation "' + notation + '". ' +
+	          'Choose "auto", "exponential", or "fixed".');
+	  }
+	};
+
+	/**
+	 * Format a number in exponential notation. Like '1.23e+5', '2.3e+0', '3.500e-3'
+	 * @param {BigNumber} value
+	 * @param {number} [precision]  Number of digits in formatted output.
+	 *                              If not provided, the maximum available digits
+	 *                              is used.
+	 * @returns {string} str
+	 */
+	exports.toExponential = function (value, precision) {
+	  if (precision !== undefined) {
+	    return value.toExponential(precision - 1); // Note the offset of one
+	  }
+	  else {
+	    return value.toExponential();
+	  }
+	};
+
+	/**
+	 * Format a number with fixed notation.
+	 * @param {BigNumber} value
+	 * @param {number} [precision=0]        Optional number of decimals after the
+	 *                                      decimal point. Zero by default.
+	 */
+	exports.toFixed = function (value, precision) {
+	  return value.toFixed(precision || 0);
+	  // Note: the (precision || 0) is needed as the toFixed of BigNumber has an
+	  // undefined default precision instead of 0.
+	}
 
 
 /***/ },
 /* 22 */
-/***/ function(module, exports, __webpack_require__) {
+/***/ function(module, exports) {
 
 	'use strict';
 
-	module.exports = function (math) {
-	  /**
-	   * Instantiate mathjs data types from their JSON representation
-	   * @param {string} key
-	   * @param {*} value
-	   * @returns {*} Returns the revived object
-	   */
-	  function reviver(key, value) {
-	    var name = value && value.mathjs;
-
-	    var constructor = math.type[name];
-	    if (constructor && constructor.fromJSON) {
-	      return constructor.fromJSON(value);
-	    }
-
-	    return value;
+	/**
+	 * Create a range error with the message:
+	 *     'Dimension mismatch (<actual size> != <expected size>)'
+	 * @param {number | number[]} actual        The actual size
+	 * @param {number | number[]} expected      The expected size
+	 * @param {string} [relation='!=']          Optional relation between actual
+	 *                                          and expected size: '!=', '<', etc.
+	 * @extends RangeError
+	 */
+	function DimensionError(actual, expected, relation) {
+	  if (!(this instanceof DimensionError)) {
+	    throw new SyntaxError('Constructor must be called with the new operator');
 	  }
 
-	  return reviver;
-	};
+	  this.actual   = actual;
+	  this.expected = expected;
+	  this.relation = relation;
+
+	  this.message = 'Dimension mismatch (' +
+	      (Array.isArray(actual) ? ('[' + actual.join(', ') + ']') : actual) +
+	      ' ' + (this.relation || '!=') + ' ' +
+	      (Array.isArray(expected) ? ('[' + expected.join(', ') + ']') : expected) +
+	      ')';
+
+	  this.stack = (new Error()).stack;
+	}
+
+	DimensionError.prototype = new RangeError();
+	DimensionError.prototype.constructor = RangeError;
+	DimensionError.prototype.name = 'DimensionError';
+	DimensionError.prototype.isDimensionError = true;
+
+	module.exports = DimensionError;
+
 
 /***/ },
 /* 23 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var BigNumber = __webpack_require__(5);
-	var errorTransform = __webpack_require__(208).transform;
-	var isNumber = __webpack_require__(3).isNumber;
-	var argsToArray = __webpack_require__(169).argsToArray;
-
-	/**
-	 * Attach a transform function to math.range
-	 * Adds a property transform containing the transform function.
-	 *
-	 * This transform changed the last `dim` parameter of function concat
-	 * from one-based to zero based
-	 * @param {Object} math
-	 */
-	module.exports = function (math) {
-	  var transform = function () {
-	    // copy arguments into an array
-	    var args = argsToArray(arguments);
-
-	    // change last argument from one-based to zero-based
-	    var lastIndex = args.length - 1;
-	    var last = args[lastIndex];
-	    if (isNumber(last)) {
-	      args[lastIndex] = last - 1;
-	    }
-	    else if (last instanceof BigNumber) {
-	      args[lastIndex] = last.minus(1);
-	    }
-
-	    try {
-	      return math.concat.apply(math, args);
-	    }
-	    catch (err) {
-	      throw errorTransform(err);
-	    }
-	  };
-
-	  math.concat.transform = transform;
-
-	  return transform;
-	};
-
-
-/***/ },
-/* 24 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var SymbolNode = __webpack_require__(188);
-	var isBoolean = __webpack_require__(209).isBoolean;
-	var argsToArray = __webpack_require__(169).argsToArray;
-	var ArgumentsError = __webpack_require__(171);
-
-	/**
-	 * Attach a transform function to math.filter
-	 * Adds a property transform containing the transform function.
-	 *
-	 * This transform adds support for equations as test function for math.filter,
-	 * so you can do something like 'filter([3, -2, 5], x > 0)'.
-	 * @param {Object} math
-	 */
-	module.exports = function (math) {
-	  var _filter = math.filter;
-
-	  var transform = function (args, math, scope) {
-	    if (args.length !== 2) {
-	      throw new ArgumentsError('filter', arguments.length, 2);
-	    }
-
-	    var x = args[0].compile(math).eval(scope);
-	    var test;
-	    if (args[1] instanceof SymbolNode) {
-	      // a function pointer, like filter([3, -2, 5], myTestFunction);
-	      test = args[1].compile(math).eval(scope);
-	    }
-	    else {
-	      // an equation like filter([3, -2, 5], x > 0)
-
-	      // find an undefined symbol
-	      var _scope = scope || {};
-	      var symbol = args[1]
-	          .filter(function (node) {
-	            return (node instanceof SymbolNode) &&
-	                !(node.name in math) &&
-	                !(node.name in _scope);
-	          })[0];
-
-	      // create a test function for this equation
-	      var sub = Object.create(_scope);
-	      var eq = args[1].compile(math);
-	      if (symbol) {
-	        var name = symbol.name;
-	        test = function (x) {
-	          sub[name] = x;
-	          return eq.eval(sub);
-	        }
-	      }
-	      else {
-	        throw new Error('No undefined variable found in filter equation');
-	      }
-	    }
-
-	    return _filter(x, test);
-	  };
-
-	  transform.rawArgs = true;
-	  math.filter.transform = transform;
-
-	  return transform;
-	};
-
-
-/***/ },
-/* 25 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	/**
-	 * Attach a transform function to math.forEach
-	 * Adds a property transform containing the transform function.
-	 *
-	 * This transform creates a one-based index instead of a zero-based index
-	 * @param {Object} math
-	 */
-	module.exports = function (math) {
-
-	  var Matrix = math.type.Matrix;
-
-	  var transform = function (x, callback) {
-	    if (arguments.length != 2) {
-	      throw new math.error.ArgumentsError('forEach', arguments.length, 2);
-	    }
-
-	    if (Array.isArray(x)) {
-	      _forEachArray(x, callback, x);
-	    } else if (x instanceof Matrix) {
-	      _forEachArray(x.valueOf(), callback, x);
-	    } else {
-	      throw new math.error.UnsupportedTypeError('forEach', math['typeof'](x));
-	    }
-	  };
-
-	  function _forEachArray (array, callback, arrayOrig) {
-	    var recurse = function (value, index) {
-	      if (Array.isArray(value)) {
-	        value.forEach(function (child, i) {
-	          // we create a copy of the index array and append the new index value
-	          recurse(child, index.concat(i + 1)); // one based index, hence i+1
-	        });
-	      }
-	      else {
-	        callback(value, index, arrayOrig);
-	      }
-	    };
-	    recurse(array, []);
-	  }
-
-	  math.forEach.transform = transform;
-
-	  return transform;
-	};
-
-
-/***/ },
-/* 26 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var BigNumber = __webpack_require__(5);
-	var Range = __webpack_require__(8);
-	var Index = __webpack_require__(9);
-	var isNumber = __webpack_require__(3).isNumber;
-
-	/**
-	 * Attach a transform function to math.index
-	 * Adds a property transform containing the transform function.
-	 *
-	 * This transform creates a one-based index instead of a zero-based index
-	 * @param {Object} math
-	 */
-	module.exports = function (math) {
-	  var transform = function () {
-	    var args = [];
-	    for (var i = 0, ii = arguments.length; i < ii; i++) {
-	      var arg = arguments[i];
-
-	      // change from one-based to zero based, and convert BigNumber to number
-	      if (arg instanceof Range) {
-	        arg.start--;
-	        arg.end -= (arg.step > 0 ? 0 : 2);
-	      }
-	      else if (isNumber(arg)) {
-	        arg--;
-	      }
-	      else if (arg instanceof BigNumber) {
-	        arg = arg.toNumber() - 1;
-	      }
-	      else {
-	        throw new TypeError('Ranges must be a Number or Range');
-	      }
-
-	      args[i] = arg;
-	    }
-
-	    var res = new Index();
-	    Index.apply(res, args);
-	    return res;
-	  };
-
-	  math.index.transform = transform;
-
-	  return transform;
-	};
-
-
-/***/ },
-/* 27 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	/**
-	 * Attach a transform function to math.map
-	 * Adds a property transform containing the transform function.
-	 *
-	 * This transform creates a one-based index instead of a zero-based index
-	 * @param {Object} math
-	 */
-	module.exports = function (math) {
-
-	  var Matrix = math.type.Matrix;
-
-	  var transform = function (x, callback) {
-	    if (arguments.length != 2) {
-	      throw new math.error.ArgumentsError('map', arguments.length, 2);
-	    }
-
-	    if (Array.isArray(x)) {
-	      return _mapArray(x, callback, x);
-	    } else if (x instanceof Matrix) {
-	      return math.matrix(_mapArray(x.valueOf(), callback, x));
-	    } else {
-	      throw new math.error.UnsupportedTypeError('map', math['typeof'](x));
-	    }
-	  };
-
-	  function _mapArray (arrayIn, callback, arrayOrig) {
-	    var recurse = function (value, index) {
-	      if (Array.isArray(value)) {
-	        return value.map(function (child, i) {
-	          // we create a copy of the index array and append the new index value
-	          return recurse(child, index.concat(i + 1)); // one based index, hence i + 1
-	        });
-	      }
-	      else {
-	        return callback(value, index, arrayOrig);
-	      }
-	    };
-
-	    return recurse(arrayIn, []);
-	  }
-
-	  math.map.transform = transform;
-
-	  return transform;
-	};
-
-
-/***/ },
-/* 28 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var BigNumber = __webpack_require__(5);
-	var errorTransform = __webpack_require__(208).transform;
-	var isNumber = __webpack_require__(3).isNumber;
-	var argsToArray = __webpack_require__(169).argsToArray;
-
-	/**
-	 * Attach a transform function to math.max
-	 * Adds a property transform containing the transform function.
-	 *
-	 * This transform changed the last `dim` parameter of function max
-	 * from one-based to zero based
-	 * @param {Object} math
-	 */
-	module.exports = function (math) {
-
-	  var isCollection = math.collection.isCollection;
-
-	  var transform = function () {
-	    var args = argsToArray(arguments);
-
-	    // change last argument dim from one-based to zero-based
-	    if (args.length == 2 && isCollection(args[0])) {
-	      var dim = args[1];
-	      if (isNumber(dim)) {
-	        args[1] = dim - 1;
-	      }
-	      else if (dim instanceof BigNumber) {
-	        args[1] = dim.minus(1);
-	      }
-	    }
-
-	    try {
-	      return math.max.apply(math, args);
-	    }
-	    catch (err) {
-	      throw errorTransform(err);
-	    }
-	  };
-
-	  math.max.transform = transform;
-
-	  return transform;
-	};
-
-
-/***/ },
-/* 29 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var BigNumber = __webpack_require__(5);
-	var errorTransform = __webpack_require__(208).transform;
-	var isNumber = __webpack_require__(3).isNumber;
-	var argsToArray = __webpack_require__(169).argsToArray;
-
-	/**
-	 * Attach a transform function to math.mean
-	 * Adds a property transform containing the transform function.
-	 *
-	 * This transform changed the last `dim` parameter of function mean
-	 * from one-based to zero based
-	 * @param {Object} math
-	 */
-	module.exports = function (math) {
-
-	  var isCollection = math.collection.isCollection;
-
-	  var transform = function () {
-	    var args = argsToArray(arguments);
-
-	    // change last argument dim from one-based to zero-based
-	    if (args.length == 2 && isCollection(args[0])) {
-	      var dim = args[1];
-	      if (isNumber(dim)) {
-	        args[1] = dim - 1;
-	      }
-	      else if (dim instanceof BigNumber) {
-	        args[1] = dim.minus(1);
-	      }
-	    }
-
-	    try {
-	      return math.mean.apply(math, args);
-	    }
-	    catch (err) {
-	      throw errorTransform(err);
-	    }
-	  };
-
-	  math.mean.transform = transform;
-
-	  return transform;
-	};
-
-
-/***/ },
-/* 30 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var BigNumber = __webpack_require__(5);
-	var errorTransform = __webpack_require__(208).transform;
-	var isNumber = __webpack_require__(3).isNumber;
-	var argsToArray = __webpack_require__(169).argsToArray;
-
-	/**
-	 * Attach a transform function to math.min
-	 * Adds a property transform containing the transform function.
-	 *
-	 * This transform changed the last `dim` parameter of function min
-	 * from one-based to zero based
-	 * @param {Object} math
-	 */
-	module.exports = function (math) {
-
-	  var isCollection = math.collection.isCollection;
-
-	  var transform = function () {
-	    var args = argsToArray(arguments);
-
-	    // change last argument dim from one-based to zero-based
-	    if (args.length == 2 && isCollection(args[0])) {
-	      var dim = args[1];
-	      if (isNumber(dim)) {
-	        args[1] = dim - 1;
-	      }
-	      else if (dim instanceof BigNumber) {
-	        args[1] = dim.minus(1);
-	      }
-	    }
-
-	    try {
-	      return math.min.apply(math, args);
-	    }
-	    catch (err) {
-	      throw errorTransform(err);
-	    }
-	  };
-
-	  math.min.transform = transform;
-
-	  return transform;
-	};
-
-
-/***/ },
-/* 31 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var isBoolean = __webpack_require__(209).isBoolean;
-	var argsToArray = __webpack_require__(169).argsToArray;
-
-	/**
-	 * Attach a transform function to math.range
-	 * Adds a property transform containing the transform function.
-	 *
-	 * This transform creates a range which includes the end value
-	 * @param {Object} math
-	 */
-	module.exports = function (math) {
-	  var transform = function () {
-	    var args = argsToArray(arguments);
-
-	    var lastIndex = args.length - 1;
-	    var last = args[lastIndex];
-	    if (!isBoolean(last)) {
-	      args.push(true); // append a parameter includeEnd=true
-	    }
-
-	    return math.range.apply(math, args);
-	  };
-
-	  math.range.transform = transform;
-
-	  return transform;
-	};
-
-
-/***/ },
-/* 32 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var errorTransform = __webpack_require__(208).transform;
-	var isBoolean = __webpack_require__(209).isBoolean;
-	var argsToArray = __webpack_require__(169).argsToArray;
-
-	/**
-	 * Attach a transform function to math.subset
-	 * Adds a property transform containing the transform function.
-	 *
-	 * This transform creates a range which includes the end value
-	 * @param {Object} math
-	 */
-	module.exports = function (math) {
-	  var transform = function () {
-	    try {
-	      return math.subset.apply(math, argsToArray(arguments));
-	    }
-	    catch (err) {
-	      throw errorTransform(err);
-	    }
-	  };
-
-	  math.subset.transform = transform;
-
-	  return transform;
-	};
-
-
-/***/ },
-/* 33 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var string = __webpack_require__(176);
-
-	  /**
-	   * @constructor Chain
-	   * Wrap any value in a chain, allowing to perform chained operations on
-	   * the value.
-	   *
-	   * All methods available in the math.js library can be called upon the chain,
-	   * and then will be evaluated with the value itself as first argument.
-	   * The chain can be closed by executing chain.done(), which will return
-	   * the final value.
-	   *
-	   * The Chain has a number of special functions:
-	   * - done()             Finalize the chained operation and return the
-	   *                      chain's value.
-	   * - valueOf()          The same as done()
-	   * - toString()         Returns a string representation of the chain's value.
-	   *
-	   * @param {*} [value]
-	   */
-	  function Chain (value) {
-	    if (!(this instanceof Chain)) {
-	      throw new SyntaxError('Constructor must be called with the new operator');
-	    }
-
-	    if (value instanceof Chain) {
-	      this.value = value.value;
-	    }
-	    else {
-	      this.value = value;
-	    }
-	  }
-
-	  /**
-	   * Close the chain. Returns the final value.
-	   * Does the same as method valueOf()
-	   * @returns {*} value
-	   */
-	  Chain.prototype.done = function () {
-	    return this.value;
-	  };
-
-	  /**
-	   * Close the chain. Returns the final value.
-	   * Does the same as method done()
-	   * @returns {*} value
-	   */
-	  Chain.prototype.valueOf = function () {
-	    return this.value;
-	  };
-
-	  /**
-	   * Get a string representation of the value in the chain
-	   * @returns {String}
-	   */
-	  Chain.prototype.toString = function () {
-	    return string.format(this.value);
-	  };
-
-	  /**
-	   * Create a proxy method for the chain
-	   * @param {String} name
-	   * @param {*} value       The value or function to be proxied
-	   */
-	  function createProxy(name, value) {
-	    var slice = Array.prototype.slice;
-	    if (typeof value === 'function') {
-	      // a function
-	      Chain.prototype[name] = function () {
-	        var args = [this.value].concat(slice.call(arguments, 0));
-	        return new Chain(value.apply(this, args));
-	      }
-	    }
-	    else {
-	      // a constant
-	      Chain.prototype[name] = new Chain(value);
-	    }
-	  }
-
-	  Chain.createProxy = createProxy;
-
-	  /**
-	   * initialise the Chain prototype with all functions and constants in math
-	   */
-	  for (var prop in math) {
-	    if (math.hasOwnProperty(prop)) {
-	      createProxy(prop, math[prop]);
-	    }
-	  }
-
-	  return Chain;
-	};
-
-
-/***/ },
-/* 34 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175),
-
-	      // take the BigNumber instance the provided math.js instance
-	      BigNumber = math.type.BigNumber,
-	      collection = math.collection,
-
-	      isCollection = collection.isCollection,
-	      isNumber = util.number.isNumber,
-	      isString = util.string.isString,
-	      isBoolean = util['boolean'].isBoolean;
-
-	  /**
-	   * Create a BigNumber, which can store numbers with arbitrary precision.
-	   * When a matrix is provided, all elements will be converted to BigNumber.
-	   *
-	   * Syntax:
-	   *
-	   *    math.bignumber(x)
-	   *
-	   * Examples:
-	   *
-	   *    0.1 + 0.2;                                  // returns Number 0.30000000000000004
-	   *    math.bignumber(0.1) + math.bignumber(0.2);  // returns BigNumber 0.3
-	   *
-	   *
-	   *    7.2e500;                                    // returns Number Infinity
-	   *    math.bignumber('7.2e500');                  // returns BigNumber 7.2e500
-	   *
-	   * See also:
-	   *
-	   *    boolean, complex, index, matrix, string, unit
-	   *
-	   * @param {Number | String | Array | Matrix | Boolean | null} [value]  Value for the big number,
-	   *                                                    0 by default.
-	   * @returns {BigNumber} The created bignumber
-	   */
-	  math.bignumber = function bignumber(value) {
-	    if (arguments.length > 1) {
-	      throw new math.error.ArgumentsError('bignumber', arguments.length, 0, 1);
-	    }
-
-	    if ((value instanceof BigNumber) || isNumber(value) || isString(value)) {
-	      return new BigNumber(value);
-	    }
-
-	    if (isBoolean(value) || value === null) {
-	      return new BigNumber(+value);
-	    }
-
-	    if (isCollection(value)) {
-	      return collection.deepMap(value, bignumber);
-	    }
-
-	    if (arguments.length == 0) {
-	      return new BigNumber(0);
-	    }
-
-	    throw new math.error.UnsupportedTypeError('bignumber', math['typeof'](value));
-	  };
-	};
-
-
-/***/ },
-/* 35 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175),
-
-	      BigNumber = math.type.BigNumber,
-	      collection = math.collection,
-
-	      isCollection = collection.isCollection,
-	      isNumber = util.number.isNumber,
-	      isString = util.string.isString;
-
-	  /**
-	   * Create a boolean or convert a string or number to a boolean.
-	   * In case of a number, `true` is returned for non-zero numbers, and `false` in
-	   * case of zero.
-	   * Strings can be `'true'` or `'false'`, or can contain a number.
-	   * When value is a matrix, all elements will be converted to boolean.
-	   *
-	   * Syntax:
-	   *
-	   *    math.boolean(x)
-	   *
-	   * Examples:
-	   *
-	   *    math.boolean(0);     // returns false
-	   *    math.boolean(1);     // returns true
-	   *    math.boolean(-3);     // returns true
-	   *    math.boolean('true');     // returns true
-	   *    math.boolean('false');     // returns false
-	   *    math.boolean([1, 0, 1, 1]);     // returns [true, false, true, true]
-	   *
-	   * See also:
-	   *
-	   *    bignumber, complex, index, matrix, string, unit
-	   *
-	   * @param {String | Number | Boolean | Array | Matrix | null} value  A value of any type
-	   * @return {Boolean | Array | Matrix} The boolean value
-	   */
-	  math['boolean'] = function bool (value) {
-	    if (arguments.length != 1) {
-	      throw new math.error.ArgumentsError('boolean', arguments.length, 0, 1);
-	    }
-
-	    if (value === 'true' || value === true) {
-	      return true;
-	    }
-
-	    if (value === 'false' || value === false || value === null) {
-	      return false;
-	    }
-
-	    if (value instanceof Boolean) {
-	      return value == true;
-	    }
-
-	    if (isNumber(value)) {
-	      return (value !== 0);
-	    }
-
-	    if (value instanceof BigNumber) {
-	      return !value.isZero();
-	    }
-
-	    if (isString(value)) {
-	      // try case insensitive
-	      var lcase = value.toLowerCase();
-	      if (lcase === 'true') {
-	        return true;
-	      }
-	      else if (lcase === 'false') {
-	        return false;
-	      }
-
-	      // test whether value is a valid number
-	      var num = Number(value);
-	      if (value != '' && !isNaN(num)) {
-	        return (num !== 0);
-	      }
-	    }
-
-	    if (isCollection(value)) {
-	      return collection.deepMap(value, bool);
-	    }
-
-	    throw new SyntaxError(value.toString() + ' is no valid boolean');
-	  };
-	};
-
-
-/***/ },
-/* 36 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175),
-
-	      BigNumber = math.type.BigNumber,
-	      Complex = __webpack_require__(7),
-	      collection = math.collection,
-
-	      isCollection = collection.isCollection,
-	      isNumber = util.number.isNumber,
-	      isString = util.string.isString,
-	      isComplex = Complex.isComplex;
-
-	  /**
-	   * Create a complex value or convert a value to a complex value.
-	   *
-	   * Syntax:
-	   *
-	   *     math.complex()                           // creates a complex value with zero
-	   *                                              // as real and imaginary part.
-	   *     math.complex(re : number, im : string)   // creates a complex value with provided
-	   *                                              // values for real and imaginary part.
-	   *     math.complex(re : number)                // creates a complex value with provided
-	   *                                              // real value and zero imaginary part.
-	   *     math.complex(complex : Complex)          // clones the provided complex value.
-	   *     math.complex(arg : string)               // parses a string into a complex value.
-	   *     math.complex(array : Array)              // converts the elements of the array
-	   *                                              // or matrix element wise into a
-	   *                                              // complex value.
-	   *     math.complex({re: number, im: number})   // creates a complex value with provided
-	   *                                              // values for real an imaginary part.
-	   *     math.complex({r: number, phi: number})   // creates a complex value with provided
-	   *                                              // polar coordinates
-	   *
-	   * Examples:
-	   *
-	   *    var a = math.complex(3, -4);     // a = Complex 3 - 4i
-	   *    a.re = 5;                        // a = Complex 5 - 4i
-	   *    var i = a.im;                    // Number -4;
-	   *    var b = math.complex('2 + 6i');  // Complex 2 + 6i
-	   *    var c = math.complex();          // Complex 0 + 0i
-	   *    var d = math.add(a, b);          // Complex 5 + 2i
-	   *
-	   * See also:
-	   *
-	   *    bignumber, boolean, index, matrix, number, string, unit
-	   *
-	   * @param {* | Array | Matrix} [args]
-	   *            Arguments specifying the real and imaginary part of the complex number
-	   * @return {Complex | Array | Matrix} Returns a complex value
-	   */
-	  math.complex = function complex(args) {
-	    switch (arguments.length) {
-	      case 0:
-	        // no parameters. Set re and im zero
-	        return new Complex(0, 0);
-
-	      case 1:
-	        // parse string into a complex number
-	        var arg = arguments[0];
-
-	        if (isNumber(arg)) {
-	          return new Complex(arg, 0);
-	        }
-
-	        if (arg instanceof BigNumber) {
-	          // convert to Number
-	          return new Complex(arg.toNumber(), 0);
-	        }
-
-	        if (isComplex(arg)) {
-	          // create a clone
-	          return arg.clone();
-	        }
-
-	        if (isString(arg)) {
-	          var c = Complex.parse(arg);
-	          if (c) {
-	            return c;
-	          }
-	          else {
-	            throw new SyntaxError('String "' + arg + '" is no valid complex number');
-	          }
-	        }
-
-	        if (isCollection(arg)) {
-	          return collection.deepMap(arg, complex);
-	        }
-
-	        if (typeof arg === 'object') {
-	          if('re' in arg && 'im' in arg) {
-	            return new Complex(arg.re, arg.im);
-	          } else if ('r' in arg && 'phi' in arg) {
-	            return Complex.fromPolar(arg.r, arg.phi);
-	          }
-	        } 
-
-	        throw new TypeError('Two numbers, single string or an fitting object expected in function complex');
-
-	      case 2:
-	        // re and im provided
-	        var re = arguments[0],
-	            im = arguments[1];
-
-	        // convert re to number
-	        if (re instanceof BigNumber) {
-	          re = re.toNumber();
-	        }
-
-	        // convert im to number
-	        if (im instanceof BigNumber) {
-	          im = im.toNumber();
-	        }
-
-	        if (isNumber(re) && isNumber(im)) {
-	          return new Complex(re, im);
-	        }
-	        else {
-	          throw new TypeError('Two numbers or a single string expected in function complex');
-	        }
-
-	      default:
-	        throw new math.error.ArgumentsError('complex', arguments.length, 0, 2);
-	    }
-	  };
-	};
-
-
-/***/ },
-/* 37 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175),
-
-	      BigNumber = math.type.BigNumber,
-	      Index = __webpack_require__(9);
-
-	  /**
-	   * Create an index. An Index can store ranges having start, step, and end
-	   * for multiple dimensions.
-	   * Matrix.get, Matrix.set, and math.subset accept an Index as input.
-	   *
-	   * Syntax:
-	   *
-	   *     math.index(range1, range2, ...)
-	   *
-	   * Where:
-	   *
-	   * Each range can be any of:
-	   *
-	   * - An array [start, end]
-	   * - An array [start, end, step]
-	   * - A number
-	   * - An instance of `Range`
-	   *
-	   * The parameters start, end, and step must be integer numbers. Start and end
-	   * are zero based. The start of a range is included, the end is excluded.
-	   *
-	   * Examples:
-	   *
-	   *    var math = math.js
-	   *
-	   *    var b = [1, 2, 3, 4, 5];
-	   *    math.subset(b, math.index([1, 3]));     // returns [2, 3]
-	   *
-	   *    var a = math.matrix([[1, 2], [3, 4]]);
-	   *    a.subset(math.index(0, 1));             // returns 2
-	   *    a.subset(math.index(1, null));          // returns [3, 4]
-	   *
-	   * See also:
-	   *
-	   *    bignumber, boolean, complex, matrix, number, string, unit
-	   *
-	   * @param {...*} ranges   Zero or more ranges or numbers.
-	   * @return {Index}        Returns the created index
-	   */
-	  math.index = function(ranges) {
-	    // downgrade BigNumber to Number
-	    var args = Array.prototype.slice.apply(arguments).map(function (arg) {
-	      if (arg instanceof BigNumber) {
-	        return arg.toNumber();
-	      }
-	      else if (Array.isArray(arg)) {
-	        return arg.map(function (elem) {
-	          return (elem instanceof BigNumber) ? elem.toNumber() : elem;
-	        });
-	      }
-	      else {
-	        return arg;
-	      }
-	    });
-
-	    var res = new Index();
-	    Index.apply(res, args);
-	    return res;
-	  };
-	};
-
-
-/***/ },
-/* 38 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var string = __webpack_require__(176);
-
-	var isArray = Array.isArray;
-	var isString = string.isString;
-
-	module.exports = function (math) {
-	  var Matrix = math.type.Matrix;
-
+/***/ function(module, exports) {
+
+	'use strict';
+
+	function factory (type, config, load, typed) {
 	  /**
 	   * Create a Matrix. The function creates a new `math.type.Matrix` object from
 	   * an `Array`. A Matrix has utility functions to manipulate the data in the
 	   * matrix, like getting the size and getting or setting values in the matrix.
+	   * Supported storage formats are 'dense' and 'sparse'.
 	   *
 	   * Syntax:
 	   *
-	   *    math.matrix()               // creates an empty matrix using default storage format (dense).
-	   *    math.matrix(data)           // creates a matrix with initial data using default storage format (dense).
-	   *    math.matrix('dense')        // creates an empty matrix using the given storage format.
-	   *    math.matrix(data, 'dense')  // creates a matrix with initial data using the given storage format.
+	   *    math.matrix()                         // creates an empty matrix using default storage format (dense).
+	   *    math.matrix(data)                     // creates a matrix with initial data using default storage format (dense).
+	   *    math.matrix('dense')                  // creates an empty matrix using the given storage format.
+	   *    math.matrix(data, 'dense')            // creates a matrix with initial data using the given storage format.
+	   *    math.matrix(data, 'sparse')           // creates a sparse matrix with initial data.
+	   *    math.matrix(data, 'sparse', 'number') // creates a sparse matrix with initial data, number data type.
 	   *
 	   * Examples:
 	   *
@@ -10017,3567 +3966,179 @@
 	   *
 	   * See also:
 	   *
-	   *    bignumber, boolean, complex, index, number, string, unit
+	   *    bignumber, boolean, complex, index, number, string, unit, sparse
 	   *
 	   * @param {Array | Matrix} [data]    A multi dimensional array
 	   * @param {string} [format]          The Matrix storage format
 	   *
 	   * @return {Matrix} The created matrix
 	   */
-	  math.matrix = function matrix(data, format) {
-	    // check arguments
-	    switch (arguments.length) {
-	      case 0:
-	        // set data and format
-	        data = [];
-	        format = 'default';
-	        break;
-	      case 1:
-	        // check data was provided
-	        if (isArray(data)) {
-	          // use default format
-	          format = 'default';          
-	        }
-	        else if (data instanceof Matrix) {
-	          // same format as matrix
-	          format = data.storage();
-	        }
-	        else if (isString(data)) {
-	          // set format
-	          format = data;
-	          // empty array
-	          data = [];
-	        }
-	        break;
-	      case 2:
-	        // check data is an array
-	        if (!isArray(data) && !(data instanceof Matrix)) {
-	          // throw
-	          throw new TypeError('data must be an array value or Matrix instance');
-	        }
-	        break;
-	      default:
-	        throw new math.error.ArgumentsError('matrix', arguments.length, 0, 2);  
-	    }
-
+	  var matrix = typed('matrix', {
+	    '': function () {
+	      return _create([]);
+	    },
+
+	    'string': function (format) {
+	      return _create([], format);
+	    },
+	    
+	    'string, string': function (format, datatype) {
+	      return _create([], format, datatype);
+	    },
+
+	    'Array': function (data) {
+	      return _create(data);
+	    },
+	      
+	    'Matrix': function (data) {
+	      return _create(data, data.storage());
+	    },
+	    
+	    'Array | Matrix, string': _create,
+	    
+	    'Array | Matrix, string, string': _create
+	  });
+
+	  matrix.toTex = {
+	    0: '\\begin{bmatrix}\\end{bmatrix}',
+	    1: '\\left(${args[0]}\\right)',
+	    2: '\\left(${args[0]}\\right)'
+	  };
+
+	  return matrix;
+
+	  /**
+	   * Create a new Matrix with given storage format
+	   * @param {Array} data
+	   * @param {string} [format]
+	   * @param {string} [datatype]
+	   * @returns {Matrix} Returns a new Matrix
+	   * @private
+	   */
+	  function _create(data, format, datatype) {
 	    // get storage format constructor
-	    var constructor = Matrix.storage(format);
+	    var M = type.Matrix.storage(format || 'default');
 
 	    // create instance
-	    return new constructor(data);
-	  };
-	};
-
-
-/***/ },
-/* 39 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175);
-
-	  var BigNumber = math.type.BigNumber;
-	  var Unit = math.type.Unit;
-	  var collection = math.collection;
-
-	  var isCollection = collection.isCollection;
-	  var isNumber = util.number.isNumber;
-	  var isBoolean = util['boolean'].isBoolean;
-	  var isString = util.string.isString;
-
-	  /**
-	   * Create a number or convert a string, boolean, or unit to a number.
-	   * When value is a matrix, all elements will be converted to number.
-	   *
-	   * Syntax:
-	   *
-	   *    math.number(value)
-	   *    math.number(unit, valuelessUnit)
-	   *
-	   * Examples:
-	   *
-	   *    math.number(2);                         // returns number 2
-	   *    math.number('7.2');                     // returns number 7.2
-	   *    math.number(true);                      // returns number 1
-	   *    math.number([true, false, true, true]); // returns [1, 0, 1, 1]
-	   *    math.number(math.unit('52cm'), 'm');    // returns 0.52
-	   *
-	   * See also:
-	   *
-	   *    bignumber, boolean, complex, index, matrix, string, unit
-	   *
-	   * @param {String | Number | Boolean | Array | Matrix | Unit | null} [value]  Value to be converted
-	   * @param {Unit | string} [valuelessUnit] A valueless unit, used to convert a unit to a number
-	   * @return {Number | Array | Matrix} The created number
-	   */
-	  math.number = function number (value, valuelessUnit) {
-	    switch (arguments.length) {
-	      case 0:
-	        return 0;
-
-	      case 1:
-	        if (isCollection(value)) {
-	          return collection.deepMap(value, number);
-	        }
-
-	        if (value instanceof BigNumber) {
-	          return value.toNumber();
-	        }
-
-	        if (isString(value)) {
-	          var num = Number(value);
-	          if (isNaN(num)) {
-	            num = Number(value.valueOf());
-	          }
-	          if (isNaN(num)) {
-	            throw new SyntaxError(value.toString() + ' is no valid number');
-	          }
-	          return num;
-	        }
-
-	        if (isBoolean(value) || value === null) {
-	          return +value;
-	        }
-
-	        if (isNumber(value)) {
-	          return value;
-	        }
-
-	        if (value instanceof Unit) {
-	          throw new Error('Second argument with valueless unit expected');
-	        }
-
-	        throw new math.error.UnsupportedTypeError('number', math['typeof'](value));
-
-	      case 2:
-	        if (value instanceof Unit && isString(valuelessUnit) || valuelessUnit instanceof Unit) {
-	          return value.toNumber(valuelessUnit);
-	        }
-
-	        throw new math.error.UnsupportedTypeError('number', math['typeof'](value), math['typeof'](valuelessUnit));
-
-
-	      default:
-	        throw new math.error.ArgumentsError('number', arguments.length, 0, 1);
-	    }
-	  };
-	};
-
-
-/***/ },
-/* 40 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var Parser = math.expression.Parser;
-
-	  /**
-	   * Create a parser. The function creates a new `math.expression.Parser` object.
-	   *
-	   * Syntax:
-	   *
-	   *    math.parser()
-	   *
-	   * Examples:
-	   *
-	   *     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();
-	   *
-	   * See also:
-	   *
-	   *    eval, compile, parse
-	   *
-	   * @return {Parser} Parser
-	   */
-	  math.parser = function parser() {
-	    return new Parser();
-	  };
-	};
-
-
-/***/ },
-/* 41 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  /**
-	   * Wrap any value in a chain, allowing to perform chained operations on
-	   * the value.
-	   *
-	   * All methods available in the math.js library can be called upon the chain,
-	   * and then will be evaluated with the value itself as first argument.
-	   * The chain can be closed by executing `chain.done()`, which returns
-	   * the final value.
-	   *
-	   * The chain has a number of special functions:
-	   *
-	   * - `done()`     Finalize the chain and return the chain's value.
-	   * - `valueOf()`  The same as `done()`
-	   * - `toString()` Executes `math.format()` onto the chain's value, returning
-	   *                a string representation of the value.
-	   *
-	   * Syntax:
-	   *
-	   *    math.chain(value)
-	   *
-	   * Examples:
-	   *
-	   *     math.chain(3)
-	   *         .add(4)
-	   *         .subtract(2)
-	   *         .done();     // 5
-	   *
-	   *     math.chain( [[1, 2], [3, 4]] )
-	   *         .subset(math.index(0, 0), 8)
-	   *         .multiply(3)
-	   *         .done();     // [[24, 6], [9, 12]]
-	   *
-	   * @param {*} [value]   A value of any type on which to start a chained operation.
-	   * @return {math.chaining.Chain} The created chain
-	   */
-	  math.chain = function(value) {
-	    // TODO: check number of arguments
-	    return new math.chaining.Chain(value);
-	  };
-
-	  // TODO: deprecate math.select in v2.0
-	  math.select = function(value) {
-	    // give a warning once.
-	    if (console && typeof console.log === 'function') {
-	      console.log('WARNING: Function "select" is renamed to "chain". It will be deprecated in v2.0.')
-	    }
-
-	    // replace warning function with chain function
-	    math.select = math.chain;
-	    math.chaining.Chain.prototype['select'] = math.select;
-
-	    return math.chain(value);
-	  }
-	};
-
-
-/***/ },
-/* 42 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175),
-
-	      collection = math.collection,
-
-	      number = util.number,
-	      isNumber = util.number.isNumber,
-	      isCollection = collection.isCollection;
-
-	  /**
-	   * Create a string or convert any object into a string.
-	   * Elements of Arrays and Matrices are processed element wise.
-	   *
-	   * Syntax:
-	   *
-	   *    math.string(value)
-	   *
-	   * Examples:
-	   *
-	   *    math.string(4.2);               // returns string '4.2'
-	   *    math.string(math.complex(3, 2); // returns string '3 + 2i'
-	   *
-	   *    var u = math.unit(5, 'km');
-	   *    math.string(u.to('m'));         // returns string '5000 m'
-	   *
-	   *    math.string([true, false]);     // returns ['true', 'false']
-	   *
-	   * See also:
-	   *
-	   *    bignumber, boolean, complex, index, matrix, number, unit
-	   *
-	   * @param {* | Array | Matrix | null} [value]  A value to convert to a string
-	   * @return {String | Array | Matrix} The created string
-	   */
-	  math.string = function string (value) {
-	    switch (arguments.length) {
-	      case 0:
-	        return '';
-
-	      case 1:
-	        if (isNumber(value)) {
-	          return number.format(value);
-	        }
-
-	        if (isCollection(value)) {
-	          return collection.deepMap(value, string);
-	        }
-
-	        if (value === null) {
-	          return 'null';
-	        }
-
-	        return value.toString();
-
-	      default:
-	        throw new math.error.ArgumentsError('string', arguments.length, 0, 1);
-	    }
-	  };
-	};
-
-
-/***/ },
-/* 43 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175),
-
-	      BigNumber = math.type.BigNumber,
-	      Unit = __webpack_require__(11),
-	      collection = math.collection,
-
-	      isCollection = collection.isCollection,
-	      isString = util.string.isString;
-
-	  /**
-	   * Create a unit. Depending on the passed arguments, the function
-	   * will create and return a new math.type.Unit object.
-	   * When a matrix is provided, all elements will be converted to units.
-	   *
-	   * Syntax:
-	   *
-	   *     math.unit(unit : string)
-	   *     math.unit(value : number, unit : string)
-	   *
-	   * Examples:
-	   *
-	   *    var a = math.unit(5, 'cm');    // returns Unit 50 mm
-	   *    var b = math.unit('23 kg');    // returns Unit 23 kg
-	   *    a.to('m');                     // returns Unit 0.05 m
-	   *
-	   * See also:
-	   *
-	   *    bignumber, boolean, complex, index, matrix, number, string
-	   *
-	   * @param {* | Array | Matrix} args   A number and unit.
-	   * @return {Unit | Array | Matrix}    The created unit
-	   */
-	  math.unit = function unit(args) {
-	    switch(arguments.length) {
-	      case 1:
-	        // parse a string
-	        var arg = arguments[0];
-
-	        if (arg instanceof Unit) {
-	          // create a clone of the unit
-	          return arg.clone();
-	        }
-
-	        if (isString(arg)) {
-	          if (Unit.isValuelessUnit(arg)) {
-	            return new Unit(null, arg); // a pure unit
-	          }
-
-	          var u = Unit.parse(arg);        // a unit with value, like '5cm'
-	          if (u) {
-	            return u;
-	          }
-
-	          throw new SyntaxError('String "' + arg + '" is no valid unit');
-	        }
-
-	        if (isCollection(args)) {
-	          return collection.deepMap(args, unit);
-	        }
-
-	        throw new TypeError('A string or a number and string expected in function unit');
-
-	      case 2:
-	        // a number and a unit
-
-	        if (arguments[0] instanceof BigNumber) {
-	          // convert value to number
-	          return new Unit(arguments[0].toNumber(), arguments[1]);
-	        }
-	        else {
-	          return new Unit(arguments[0], arguments[1]);
-	        }
-
-	      default:
-	        throw new math.error.ArgumentsError('unit', arguments.length, 1, 2);
-	    }
-	  };
-	};
-
-
-/***/ },
-/* 44 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math, config) {
-	  var util = __webpack_require__(175),
-	      _parse = math.expression.parse,
-
-	      collection = math.collection,
-
-	      isString = util.string.isString,
-	      isCollection = collection.isCollection;
-
-	  /**
-	   * Parse and compile an expression.
-	   * Returns a an object with a function `eval([scope])` to evaluate the
-	   * compiled expression.
-	   *
-	   * Syntax:
-	   *
-	   *     math.compile(expr)                       // returns one node
-	   *     math.compile([expr1, expr2, expr3, ...]) // returns an array with nodes
-	   *
-	   * Examples:
-	   *
-	   *     var code = math.compile('sqrt(3^2 + 4^2)');
-	   *     code.eval(); // 5
-	   *
-	   *     var scope = {a: 3, b: 4}
-	   *     var code = math.compile('a * b'); // 12
-	   *     code.eval(scope); // 12
-	   *     scope.a = 5;
-	   *     code.eval(scope); // 20
-	   *
-	   *     var nodes = math.compile(['a = 3', 'b = 4', 'a * b']);
-	   *     nodes[2].eval(); // 12
-	   *
-	   * See also:
-	   *
-	   *    parse, eval
-	   *
-	   * @param {String | String[] | Matrix} expr
-	   *            The expression to be compiled
-	   * @return {{eval: Function} | Array.<{eval: Function}>} code
-	   *            An object with the compiled expression
-	   * @throws {Error}
-	   */
-	  math.compile = function compile (expr) {
-	    if (arguments.length != 1) {
-	      throw new math.error.ArgumentsError('compile', arguments.length, 1);
-	    }
-
-	    if (isString(expr)) {
-	      // evaluate a single expression
-	      return _parse(expr).compile(math);
-	    }
-	    else if (isCollection(expr)) {
-	      // evaluate an array or matrix with expressions
-	      return collection.deepMap(expr, function (elem) {
-	        return _parse(elem).compile(math);
-	      });
-	    }
-	    else {
-	      // oops
-	      throw new TypeError('String, array, or matrix expected');
-	    }
-	  }
-	};
-
-
-/***/ },
-/* 45 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175),
-	      _parse = math.expression.parse,
-
-	      collection = math.collection,
-
-	      isString = util.string.isString,
-	      isCollection = collection.isCollection;
-
-	  /**
-	   * Evaluate an expression.
-	   *
-	   * Syntax:
-	   *
-	   *     math.eval(expr)
-	   *     math.eval(expr, scope)
-	   *     math.eval([expr1, expr2, expr3, ...])
-	   *     math.eval([expr1, expr2, expr3, ...], scope)
-	   *
-	   * Example:
-	   *
-	   *     math.eval('(2+3)/4');                // 1.25
-	   *     math.eval('sqrt(3^2 + 4^2)');        // 5
-	   *     math.eval('sqrt(-4)');               // 2i
-	   *     math.eval(['a=3', 'b=4', 'a*b']);,   // [3, 4, 12]
-	   *
-	   *     var scope = {a:3, b:4};
-	   *     math.eval('a * b', scope);           // 12
-	   *
-	   * See also:
-	   *
-	   *    parse, compile
-	   *
-	   * @param {String | String[] | Matrix} expr   The expression to be evaluated
-	   * @param {Object} [scope]                    Scope to read/write variables
-	   * @return {*} The result of the expression
-	   * @throws {Error}
-	   */
-	  math.eval = function _eval (expr, scope) {
-	    if (arguments.length != 1 && arguments.length != 2) {
-	      throw new math.error.ArgumentsError('eval', arguments.length, 1, 2);
-	    }
-
-	    // instantiate a scope
-	    scope = scope || {};
-
-	    if (isString(expr)) {
-	      // evaluate a single expression
-	      return _parse(expr)
-	          .compile(math)
-	          .eval(scope);
-	    }
-	    else if (isCollection(expr)) {
-	      // evaluate an array or matrix with expressions
-	      return collection.deepMap(expr, function (elem) {
-	        return _parse(elem)
-	            .compile(math).eval(scope);
-	      });
-	    }
-	    else {
-	      // oops
-	      throw new TypeError('String, array, or matrix expected');
-	    }
-	  };
-	};
-
-
-/***/ },
-/* 46 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var Help = __webpack_require__(12);
-
-	  /**
-	   * Retrieve help on a function or data type.
-	   * Help files are retrieved from the documentation in math.expression.docs.
-	   *
-	   * Syntax:
-	   *
-	   *    math.help(search)
-	   *
-	   * Examples:
-	   *
-	   *    console.log(math.help('sin').toString());
-	   *    console.log(math.help(math.add).toString());
-	   *    console.log(math.help(math.add).toJSON());
-	   *
-	   * @param {function | string | Object} search   A function or function name
-	   *                                              for which to get help
-	   * @return {Help} A help object
-	   */
-	  math.help = function help(search) {
-	    if (arguments.length != 1) {
-	      throw new SyntaxError('Wrong number of arguments in function help ' +
-	          '(' + arguments.length + ' provided, 1 expected)');
-	    }
-
-	    var text = null;
-	    if ((search instanceof String) || (typeof(search) === 'string')) {
-	      text = search;
-	    }
-	    else {
-	      var prop;
-	      for (prop in math) {
-	        // search in functions and constants
-	        if (math.hasOwnProperty(prop) && (search === math[prop])) {
-	          text = prop;
-	          break;
-	        }
-	      }
-
-	      /* TODO: implement help for data types
-	      if (!text) {
-	        // search data type
-	        for (prop in math.type) {
-	          if (math.type.hasOwnProperty(prop)) {
-	            if (search === math.type[prop]) {
-	              text = prop;
-	              break;
-	            }
-	          }
-	        }
-	      }
-	      */
-	    }
-
-	    var doc = math.expression.docs[text];
-	    if (!text) {
-	      throw new Error('Cannot find "' + search + '" in math.js');
-	    } else if (!doc) {
-	      throw new Error('No documentation found on "' + text + '"');
-	    }
-	    return new Help(doc);
-	  };
-	};
-
-
-/***/ },
-/* 47 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math, config) {
-	  var _parse = math.expression.parse;
-
-	  /**
-	   * Parse an expression. Returns a node tree, which can be evaluated by
-	   * invoking node.eval();
-	   *
-	   * Syntax:
-	   *
-	   *     parse(expr)
-	   *     parse(expr, options)
-	   *     parse([expr1, expr2, expr3, ...])
-	   *     parse([expr1, expr2, expr3, ...], options)
-	   *
-	   * Example:
-	   *
-	   *     var node = parse('sqrt(3^2 + 4^2)');
-	   *     node.compile(math).eval(); // 5
-	   *
-	   *     var scope = {a:3, b:4}
-	   *     var node = parse('a * b'); // 12
-	   *     var code = node.compile(math);
-	   *     code.eval(scope); // 12
-	   *     scope.a = 5;
-	   *     code.eval(scope); // 20
-	   *
-	   *     var nodes = math.parse(['a = 3', 'b = 4', 'a * b']);
-	   *     nodes[2].compile(math).eval(); // 12
-	   *
-	   * @param {String | String[] | Matrix} expr          Expression to be parsed
-	   * @param {{nodes: Object<String, Node>}} [options]  Available options:
-	   *                                                   - `nodes` a set of custom nodes
-	   * @return {Node | Node[]} node
-	   * @throws {Error}
-	   */
-	  math.parse = function parse (expr, options) {
-	    return _parse.apply(_parse, arguments);
-	  }
-
-	};
-
-
-/***/ },
-/* 48 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175),
-
-	      BigNumber = math.type.BigNumber,
-	      Complex = __webpack_require__(7),
-	      collection = math.collection,
-
-	      isNumber = util.number.isNumber,
-	      isBoolean = util.boolean.isBoolean,
-	      isComplex = Complex.isComplex,
-	      isCollection = collection.isCollection;
-
-	  /**
-	   * Calculate the absolute value of a number. For matrices, the function is
-	   * evaluated element wise.
-	   *
-	   * Syntax:
-	   *
-	   *    math.abs(x)
-	   *
-	   * Examples:
-	   *
-	   *    math.abs(3.5);                // returns Number 3.5
-	   *    math.abs(-4.2);               // returns Number 4.2
-	   *
-	   *    math.abs([3, -5, -1, 0, 2]);  // returns Array [3, 5, 1, 0, 2]
-	   *
-	   * See also:
-	   *
-	   *    sign
-	   *
-	   * @param  {Number | BigNumber | Boolean | Complex | Array | Matrix | null} x
-	   *            A number or matrix for which to get the absolute value
-	   * @return {Number | BigNumber | Complex | Array | Matrix}
-	   *            Absolute value of `x`
-	   */
-	  math.abs = function abs(x) {
-	    if (arguments.length != 1) {
-	      throw new math.error.ArgumentsError('abs', arguments.length, 1);
-	    }
-
-	    if (isNumber(x)) {
-	      return Math.abs(x);
-	    }
-
-	    if (isComplex(x)) {
-	      // do not compute sqrt(re * re + im * im) since it will overflow with big numbers!
-	      var re = Math.abs(x.re);
-	      var im = Math.abs(x.im);
-	      if (re >= im) {
-	        var i = im / re;
-	        return re * Math.sqrt(1 + i * i);
-	      }
-	      var j = re / im;
-	      return im * Math.sqrt(1 + j * j);
-	    }
-
-	    if (x instanceof BigNumber) {
-	      return x.abs();
-	    }
-
-	    if (isCollection(x)) {
-	      // deep map collection, skip zeros since abs(0) = 0
-	      return collection.deepMap(x, abs, true);
-	    }
-
-	    if (isBoolean(x) || x === null) {
-	      return Math.abs(x);
-	    }
-
-	    throw new math.error.UnsupportedTypeError('abs', math['typeof'](x));
-	  };
-	};
-
-
-/***/ },
-/* 49 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175),
-
-	      BigNumber = math.type.BigNumber,
-	      Complex = __webpack_require__(7),
-	      Unit = __webpack_require__(11),
-	      collection = math.collection,
-
-	      isBoolean = util['boolean'].isBoolean,
-	      isNumber = util.number.isNumber,
-	      isString = util.string.isString,
-	      isComplex = Complex.isComplex,
-	      isUnit = Unit.isUnit,
-	      isCollection = collection.isCollection;
-
-	  /**
-	   * Add two values, `x + y`.
-	   * For matrices, the function is evaluated element wise.
-	   *
-	   * Syntax:
-	   *
-	   *    math.add(x, y)
-	   *
-	   * Examples:
-	   *
-	   *    math.add(2, 3);               // returns Number 5
-	   *
-	   *    var a = math.complex(2, 3);
-	   *    var b = math.complex(-4, 1);
-	   *    math.add(a, b);               // returns Complex -2 + 4i
-	   *
-	   *    math.add([1, 2, 3], 4);       // returns Array [5, 6, 7]
-	   *
-	   *    var c = math.unit('5 cm');
-	   *    var d = math.unit('2.1 mm');
-	   *    math.add(c, d);               // returns Unit 52.1 mm
-	   *
-	   * See also:
-	   *
-	   *    subtract
-	   *
-	   * @param  {Number | BigNumber | Boolean | Complex | Unit | String | Array | Matrix | null} x First value to add
-	   * @param  {Number | BigNumber | Boolean | Complex | Unit | String | Array | Matrix | null} y Second value to add
-	   * @return {Number | BigNumber | Complex | Unit | String | Array | Matrix} Sum of `x` and `y`
-	   */
-	  math.add = function add(x, y) {
-	    if (arguments.length != 2) {
-	      throw new math.error.ArgumentsError('add', arguments.length, 2);
-	    }
-
-	    if (isNumber(x)) {
-	      if (isNumber(y)) {
-	        // number + number
-	        return x + y;
-	      }
-	      else if (isComplex(y)) {
-	        // number + complex
-	        return new Complex(
-	            x + y.re,
-	            y.im
-	        );
-	      }
-	    }
-
-	    if (isComplex(x)) {
-	      if (isComplex(y)) {
-	        // complex + complex
-	        return new Complex(
-	            x.re + y.re,
-	            x.im + y.im
-	        );
-	      }
-	      else if (isNumber(y)) {
-	        // complex + number
-	        return new Complex(
-	            x.re + y,
-	            x.im
-	        );
-	      }
-	    }
-
-	    if (isUnit(x)) {
-	      if (isUnit(y)) {
-	        if (x.value == null) {
-	          throw new Error('Parameter x contains a unit with undefined value');
-	        }
-
-	        if (y.value == null) {
-	          throw new Error('Parameter y contains a unit with undefined value');
-	        }
-
-	        if (!x.equalBase(y)) {
-	          throw new Error('Units do not match');
-	        }
-
-	        var res = x.clone();
-	        res.value += y.value;
-	        res.fixPrefix = false;
-	        return res;
-	      }
-	    }
-
-	    if (x instanceof BigNumber) {
-	      // try to convert to big number
-	      if (isNumber(y)) {
-	        y = BigNumber.convert(y);
-	      }
-	      else if (isBoolean(y) || y === null) {
-	        y = new BigNumber(y ? 1 : 0);
-	      }
-
-	      if (y instanceof BigNumber) {
-	        return x.plus(y);
-	      }
-
-	      // downgrade to Number
-	      return add(x.toNumber(), y);
-	    }
-	    if (y instanceof BigNumber) {
-	      // try to convert to big number
-	      if (isNumber(x)) {
-	        x = BigNumber.convert(x);
-	      }
-	      else if (isBoolean(x) || x === null) {
-	        x = new BigNumber(x ? 1 : 0);
-	      }
-
-	      if (x instanceof BigNumber) {
-	        return x.plus(y);
-	      }
-
-	      // downgrade to Number
-	      return add(x, y.toNumber());
-	    }
-
-	    if (isCollection(x) || isCollection(y)) {
-	      return collection.deepMap2(x, y, add);
-	    }
-
-	    if (isString(x) || isString(y)) {
-	      return x + y;
-	    }
-
-	    if (isBoolean(x) || x === null) {
-	      return add(+x, y);
-	    }
-	    if (isBoolean(y) || y === null) {
-	      return add(x, +y);
-	    }
-
-	    throw new math.error.UnsupportedTypeError('add', math['typeof'](x), math['typeof'](y));
-	  };
-	};
-
-
-/***/ },
-/* 50 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175),
-
-	      BigNumber = math.type.BigNumber,
-	      Complex = __webpack_require__(7),
-	      collection = math.collection,
-
-	      isNumber = util.number.isNumber,
-	      isBoolean = util['boolean'].isBoolean,
-	      isCollection =collection.isCollection,
-	      isComplex = Complex.isComplex;
-
-	  /**
-	   * Round a value towards plus infinity
-	   * If `x` is complex, both real and imaginary part are rounded towards plus infinity.
-	   * For matrices, the function is evaluated element wise.
-	   *
-	   * Syntax:
-	   *
-	   *    math.ceil(x)
-	   *
-	   * Examples:
-	   *
-	   *    math.ceil(3.2);               // returns Number 4
-	   *    math.ceil(3.8);               // returns Number 4
-	   *    math.ceil(-4.2);              // returns Number -4
-	   *    math.ceil(-4.7);              // returns Number -4
-	   *
-	   *    var c = math.complex(3.2, -2.7);
-	   *    math.ceil(c);                 // returns Complex 4 - 2i
-	   *
-	   *    math.ceil([3.2, 3.8, -4.7]);  // returns Array [4, 4, -4]
-	   *
-	   * See also:
-	   *
-	   *    floor, fix, round
-	   *
-	   * @param  {Number | BigNumber | Boolean | Complex | Array | Matrix | null} x  Number to be rounded
-	   * @return {Number | BigNumber | Complex | Array | Matrix} Rounded value
-	   */
-	  math.ceil = function ceil(x) {
-	    if (arguments.length != 1) {
-	      throw new math.error.ArgumentsError('ceil', arguments.length, 1);
-	    }
-
-	    if (isNumber(x)) {
-	      return Math.ceil(x);
-	    }
-
-	    if (isComplex(x)) {
-	      return new Complex (
-	          Math.ceil(x.re),
-	          Math.ceil(x.im)
-	      );
-	    }
-
-	    if (x instanceof BigNumber) {
-	      return x.ceil();
-	    }
-
-	    if (isCollection(x)) {
-	      // deep map collection, skip zeros since ceil(0) = 0
-	      return collection.deepMap(x, ceil, true);
-	    }
-
-	    if (isBoolean(x) || x === null) {
-	      return Math.ceil(x);
-	    }
-
-	    throw new math.error.UnsupportedTypeError('ceil', math['typeof'](x));
-	  };
-	};
-
-
-/***/ },
-/* 51 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175),
-
-	      BigNumber = math.type.BigNumber,
-	      Complex = __webpack_require__(7),
-	      collection = math.collection,
-
-	      isNumber = util.number.isNumber,
-	      isBoolean = util['boolean'].isBoolean,
-	      isComplex = Complex.isComplex,
-	      isCollection = collection.isCollection;
-
-	  /**
-	   * Compute the cube of a value, `x * x * x`.
-	   * For matrices, the function is evaluated element wise.
-	   *
-	   * Syntax:
-	   *
-	   *    math.cube(x)
-	   *
-	   * Examples:
-	   *
-	   *    math.cube(2);            // returns Number 8
-	   *    math.pow(2, 3);          // returns Number 8
-	   *    math.cube(4);            // returns Number 64
-	   *    4 * 4 * 4;               // returns Number 64
-	   *
-	   *    math.cube([1, 2, 3, 4]); // returns Array [1, 8, 27, 64]
-	   *
-	   * See also:
-	   *
-	   *    multiply, square, pow
-	   *
-	   * @param  {Number | BigNumber | Boolean | Complex | Array | Matrix | null} x  Number for which to calculate the cube
-	   * @return {Number | BigNumber | Complex | Array | Matrix} Cube of x
-	   */
-	  math.cube = function cube(x) {
-	    if (arguments.length != 1) {
-	      throw new math.error.ArgumentsError('cube', arguments.length, 1);
-	    }
-
-	    if (isNumber(x)) {
-	      return x * x * x;
-	    }
-
-	    if (isComplex(x)) {
-	      return math.multiply(math.multiply(x, x), x);
-	    }
-
-	    if (x instanceof BigNumber) {
-	      return x.times(x).times(x);
-	    }
-
-	    if (isCollection(x)) {
-	      return collection.deepMap(x, cube);
-	    }
-
-	    if (isBoolean(x) || x === null) {
-	      return cube(+x);
-	    }
-
-	    throw new math.error.UnsupportedTypeError('cube', math['typeof'](x));
-	  };
-	};
-
-
-/***/ },
-/* 52 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function(math) {
-	  var util = __webpack_require__(175);
-
-	  var BigNumber = math.type.BigNumber;
-	  var Complex = __webpack_require__(7);
-	  var Matrix = math.type.Matrix;
-	  var Unit = __webpack_require__(11);
-
-	  var isNumber = util.number.isNumber;
-	  var isBoolean = util['boolean'].isBoolean;
-	  var isComplex = Complex.isComplex;
-	  var isUnit = Unit.isUnit;
-
-	  /**
-	   * Divide two scalar values, `x / y`.
-	   * This function is meant for internal use: it is used by the public functions
-	   * `divide` and `inv`.
-	   *
-	   * This function does not support collections (Array or Matrix), and does
-	   * not validate the number of of inputs.
-	   *
-	   * @param  {Number | BigNumber | Boolean | Complex | Unit | null} x   Numerator
-	   * @param  {Number | BigNumber | Boolean | Complex | null} y          Denominator
-	   * @return {Number | BigNumber | Complex | Unit}                      Quotient, `x / y`
-	   * @private
-	   */
-	  math._divide = function _divide(x, y) {
-	    // TODO: this is a temporary function, to be removed as soon as the library is modularized (i.e. no dependencies on math from the individual functions)
-	    if (isNumber(x)) {
-	      if (isNumber(y)) {
-	        // number / number
-	        return x / y;
-	      }
-	      else if (isComplex(y)) {
-	        // number / complex
-	        return _divideComplex(new Complex(x, 0), y);
-	      }
-	    }
-
-	    if (isComplex(x)) {
-	      if (isComplex(y)) {
-	        // complex / complex
-	        return _divideComplex(x, y);
-	      }
-	      else if (isNumber(y)) {
-	        // complex / number
-	        return _divideComplex(x, new Complex(y, 0));
-	      }
-	    }
-
-	    if (x instanceof BigNumber) {
-	      // try to convert to big number
-	      if (isNumber(y)) {
-	        y = BigNumber.convert(y);
-	      }
-	      else if (isBoolean(y) || y === null) {
-	        y = new BigNumber(y ? 1 : 0);
-	      }
-
-	      if (y instanceof BigNumber) {
-	        return x.div(y);
-	      }
-
-	      // downgrade to Number
-	      return _divide(x.toNumber(), y);
-	    }
-	    if (y instanceof BigNumber) {
-	      // try to convert to big number
-	      if (isNumber(x)) {
-	        x = BigNumber.convert(x);
-	      }
-	      else if (isBoolean(x) || x === null) {
-	        x = new BigNumber(x ? 1 : 0);
-	      }
-
-	      if (x instanceof BigNumber) {
-	        return x.div(y)
-	      }
-
-	      // downgrade to Number
-	      return _divide(x, y.toNumber());
-	    }
-
-	    if (isUnit(x)) {
-	      if (isNumber(y)) {
-	        var res = x.clone();
-	        res.value = ((res.value === null) ? res._normalize(1) : res.value) / y;
-	        return res;
-	      }
-	    }
-
-	    if (isBoolean(x) || x === null) {
-	      return _divide(+x, y);
-	    }
-	    if (isBoolean(y) || y === null) {
-	      return _divide(x, +y);
-	    }
-
-	    throw new math.error.UnsupportedTypeError('divide', math['typeof'](x), math['typeof'](y));
-	  };
-
-	  /**
-	   * Divide two complex numbers. x / y or divide(x, y)
-	   * @param {Complex} x
-	   * @param {Complex} y
-	   * @return {Complex} res
-	   * @private
-	   */
-	  function _divideComplex (x, y) {
-	    var den = y.re * y.re + y.im * y.im;
-	    if (den != 0) {
-	      return new Complex(
-	          (x.re * y.re + x.im * y.im) / den,
-	          (x.im * y.re - x.re * y.im) / den
-	      );
-	    }
-	    else {
-	      // both y.re and y.im are zero
-	      return new Complex(
-	          (x.re != 0) ? (x.re / 0) : 0,
-	          (x.im != 0) ? (x.im / 0) : 0
-	      );
-	    }
-	  }
-	};
-
-
-/***/ },
-/* 53 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function(math) {
-	  var collection = math.collection;
-	  var isCollection = collection.isCollection;
-
-	  /**
-	   * Divide two values, `x / y`.
-	   * To divide matrices, `x` is multiplied with the inverse of `y`: `x * inv(y)`.
-	   *
-	   * Syntax:
-	   *
-	   *    math.divide(x, y)
-	   *
-	   * Examples:
-	   *
-	   *    math.divide(2, 3);            // returns Number 0.6666666666666666
-	   *
-	   *    var a = math.complex(5, 14);
-	   *    var b = math.complex(4, 1);
-	   *    math.divide(a, b);            // returns Complex 2 + 3i
-	   *
-	   *    var c = [[7, -6], [13, -4]];
-	   *    var d = [[1, 2], [4, 3]];
-	   *    math.divide(c, d);            // returns Array [[-9, 4], [-11, 6]]
-	   *
-	   *    var e = math.unit('18 km');
-	   *    math.divide(e, 4.5);          // returns Unit 4 km
-	   *
-	   * See also:
-	   *
-	   *    multiply
-	   *
-	   * @param  {Number | BigNumber | Boolean | Complex | Unit | Array | Matrix | null} x   Numerator
-	   * @param  {Number | BigNumber | Boolean | Complex | Array | Matrix | null} y          Denominator
-	   * @return {Number | BigNumber | Complex | Unit | Array | Matrix}                      Quotient, `x / y`
-	   */
-	  math.divide = function(x, y) {
-	    if (arguments.length != 2) {
-	      throw new math.error.ArgumentsError('divide', arguments.length, 2);
-	    }
-
-	    if (isCollection(x)) {
-	      if (isCollection(y)) {
-	        // TODO: implement matrix right division using pseudo inverse
-	        // http://www.mathworks.nl/help/matlab/ref/mrdivide.html
-	        // http://www.gnu.org/software/octave/doc/interpreter/Arithmetic-Ops.html
-	        // http://stackoverflow.com/questions/12263932/how-does-gnu-octave-matrix-division-work-getting-unexpected-behaviour
-	        return math.multiply(x, math.inv(y));
-	      }
-	      else {
-	        // matrix / scalar
-	        return collection.deepMap2(x, y, math._divide);
-	      }
-	    }
-
-	    if (isCollection(y)) {
-	      // TODO: implement matrix right division using pseudo inverse
-	      return math.multiply(x, math.inv(y));
-	    }
-
-	    // divide two scalars
-	    return math._divide(x, y);
-	  };
-	};
-
-
-/***/ },
-/* 54 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var collection = math.collection;
-
-	  /**
-	   * Divide two matrices element wise. The function accepts both matrices and
-	   * scalar values.
-	   *
-	   * Syntax:
-	   *
-	   *    math.dotDivide(x, y)
-	   *
-	   * Examples:
-	   *
-	   *    math.dotDivide(2, 4);   // returns 0.5
-	   *
-	   *    a = [[9, 5], [6, 1]];
-	   *    b = [[3, 2], [5, 2]];
-	   *
-	   *    math.dotDivide(a, b);   // returns [[3, 2.5], [1.2, 0.5]]
-	   *    math.divide(a, b);      // returns [[1.75, 0.75], [-1.75, 2.25]]
-	   *
-	   * See also:
-	   *
-	   *    divide, multiply, dotMultiply
-	   *
-	   * @param  {Number | BigNumber | Boolean | Complex | Unit | Array | Matrix | null} x Numerator
-	   * @param  {Number | BigNumber | Boolean | Complex | Unit | Array | Matrix | null} y Denominator
-	   * @return {Number | BigNumber | Complex | Unit | Array | Matrix}                    Quotient, `x ./ y`
-	   */
-	  math.dotDivide = function dotDivide(x, y) {
-	    if (arguments.length != 2) {
-	      throw new math.error.ArgumentsError('dotDivide', arguments.length, 2);
-	    }
-
-	    return collection.deepMap2(x, y, math.divide);
-	  };
-
-	  // TODO: deprecated since version 0.23.0, clean up some day
-	  math.edivide = function () {
-	    throw new Error('Function edivide is renamed to dotDivide');
-	  }
-	};
-
-
-/***/ },
-/* 55 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175),
-	      collection = math.collection;
-
-	  /**
-	   * Multiply two matrices element wise. The function accepts both matrices and
-	   * scalar values.
-	   *
-	   * Syntax:
-	   *
-	   *    math.dotMultiply(x, y)
-	   *
-	   * Examples:
-	   *
-	   *    math.dotMultiply(2, 4); // returns 8
-	   *
-	   *    a = [[9, 5], [6, 1]];
-	   *    b = [[3, 2], [5, 2]];
-	   *
-	   *    math.dotMultiply(a, b); // returns [[27, 10], [30, 2]]
-	   *    math.multiply(a, b);    // returns [[52, 28], [23, 14]]
-	   *
-	   * See also:
-	   *
-	   *    multiply, divide, dotDivide
-	   *
-	   * @param  {Number | BigNumber | Boolean | Complex | Unit | Array | Matrix | null} x Left hand value
-	   * @param  {Number | BigNumber | Boolean | Complex | Unit | Array | Matrix | null} y Right hand value
-	   * @return {Number | BigNumber | Complex | Unit | Array | Matrix}                    Multiplication of `x` and `y`
-	   */
-	  math.dotMultiply = function dotMultiply(x, y) {
-	    if (arguments.length != 2) {
-	      throw new math.error.ArgumentsError('dotMultiply', arguments.length, 2);
-	    }
-
-	    return collection.deepMap2(x, y, math.multiply);
-	  };
-
-	  // TODO: deprecated since version 0.23.0, clean up some day
-	  math.emultiply = function () {
-	    throw new Error('Function emultiply is renamed to dotMultiply');
-	  }
-	};
-
-
-/***/ },
-/* 56 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175),
-	      collection = math.collection;
-
-	  /**
-	   * Calculates the power of x to y element wise.
-	   *
-	   * Syntax:
-	   *
-	   *    math.dotPow(x, y)
-	   *
-	   * Examples:
-	   *
-	   *    math.dotPow(2, 3);            // returns Number 8
-	   *
-	   *    var a = [[1, 2], [4, 3]];
-	   *    math.dotPow(a, 2);            // returns Array [[1, 4], [16, 9]]
-	   *    math.pow(a, 2);               // returns Array [[9, 8], [16, 17]]
-	   *
-	   * See also:
-	   *
-	   *    pow, sqrt, multiply
-	   *
-	   * @param  {Number | BigNumber | Boolean | Complex | Unit | Array | Matrix | null} x  The base
-	   * @param  {Number | BigNumber | Boolean | Complex | Unit | Array | Matrix | null} y  The exponent
-	   * @return {Number | BigNumber | Complex | Unit | Array | Matrix}                     The value of `x` to the power `y`
-	   */
-	  math.dotPow = function dotPow(x, y) {
-	    if (arguments.length != 2) {
-	      throw new math.error.ArgumentsError('dotPow', arguments.length, 2);
-	    }
-
-	    return collection.deepMap2(x, y, math.pow);
-	  };
-
-	  // TODO: deprecated since version 0.23.0, clean up some day
-	  math.epow = function () {
-	    throw new Error('Function epow is renamed to dotPow');
-	  }
-	};
-
-
-/***/ },
-/* 57 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175),
-
-	      BigNumber = math.type.BigNumber,
-	      Complex = __webpack_require__(7),
-	      Matrix = math.type.Matrix,
-	      collection = math.collection,
-
-	      isNumber = util.number.isNumber,
-	      isBoolean = util['boolean'].isBoolean,
-	      isComplex = Complex.isComplex,
-	      isCollection = collection.isCollection;
-
-	  /**
-	   * Calculate the exponent of a value.
-	   * For matrices, the function is evaluated element wise.
-	   *
-	   * Syntax:
-	   *
-	   *    math.exp(x)
-	   *
-	   * Examples:
-	   *
-	   *    math.exp(2);                  // returns Number 7.3890560989306495
-	   *    math.pow(math.e, 2);          // returns Number 7.3890560989306495
-	   *    math.log(math.exp(2));        // returns Number 2
-	   *
-	   *    math.exp([1, 2, 3]);
-	   *    // returns Array [
-	   *    //   2.718281828459045,
-	   *    //   7.3890560989306495,
-	   *    //   20.085536923187668
-	   *    // ]
-	   *
-	   * See also:
-	   *
-	   *    log, pow
-	   *
-	   * @param {Number | BigNumber | Boolean | Complex | Array | Matrix | null} x  A number or matrix to exponentiate
-	   * @return {Number | BigNumber | Complex | Array | Matrix} Exponent of `x`
-	   */
-	  math.exp = function exp (x) {
-	    if (arguments.length != 1) {
-	      throw new math.error.ArgumentsError('exp', arguments.length, 1);
-	    }
-
-	    if (isNumber(x)) {
-	      return Math.exp(x);
-	    }
-
-	    if (isComplex(x)) {
-	      var r = Math.exp(x.re);
-	      return new Complex(
-	          r * Math.cos(x.im),
-	          r * Math.sin(x.im)
-	      );
-	    }
-
-	    if (x instanceof BigNumber) {
-	      return x.exp();
-	    }
-
-	    if (isCollection(x)) {
-	      return collection.deepMap(x, exp);
-	    }
-
-	    if (isBoolean(x) || x === null) {
-	      return Math.exp(x);
-	    }
-
-	    throw new math.error.UnsupportedTypeError('exp', math['typeof'](x));
-	  };
-	};
-
-
-/***/ },
-/* 58 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175),
-
-	      BigNumber = math.type.BigNumber,
-	      Complex = __webpack_require__(7),
-	      collection = math.collection,
-
-	      isNumber = util.number.isNumber,
-	      isBoolean = util['boolean'].isBoolean,
-	      isComplex = Complex.isComplex,
-	      isCollection = collection.isCollection;
-
-	  /**
-	   * Round a value towards zero.
-	   * For matrices, the function is evaluated element wise.
-	   *
-	   * Syntax:
-	   *
-	   *    math.fix(x)
-	   *
-	   * Examples:
-	   *
-	   *    math.fix(3.2);                // returns Number 3
-	   *    math.fix(3.8);                // returns Number 3
-	   *    math.fix(-4.2);               // returns Number -4
-	   *    math.fix(-4.7);               // returns Number -4
-	   *
-	   *    var c = math.complex(3.2, -2.7);
-	   *    math.fix(c);                  // returns Complex 3 - 2i
-	   *
-	   *    math.fix([3.2, 3.8, -4.7]);   // returns Array [3, 3, -4]
-	   *
-	   * See also:
-	   *
-	   *    ceil, floor, round
-	   *
-	   * @param {Number | BigNumber | Boolean | Complex | Array | Matrix | null} x Number to be rounded
-	   * @return {Number | BigNumber | Complex | Array | Matrix}            Rounded value
-	   */
-	  math.fix = function fix(x) {
-	    if (arguments.length != 1) {
-	      throw new math.error.ArgumentsError('fix', arguments.length, 1);
-	    }
-
-	    if (isNumber(x)) {
-	      return (x > 0) ? Math.floor(x) : Math.ceil(x);
-	    }
-
-	    if (isComplex(x)) {
-	      return new Complex(
-	          (x.re > 0) ? Math.floor(x.re) : Math.ceil(x.re),
-	          (x.im > 0) ? Math.floor(x.im) : Math.ceil(x.im)
-	      );
-	    }
-
-	    if (x instanceof BigNumber) {
-	      return x.isNegative() ? x.ceil() : x.floor();
-	    }
-
-	    if (isCollection(x)) {
-	      // deep map collection, skip zeros since fix(0) = 0
-	      return collection.deepMap(x, fix, true);
-	    }
-
-	    if (isBoolean(x) || x === null) {
-	      return fix(+x);
-	    }
-
-	    throw new math.error.UnsupportedTypeError('fix', math['typeof'](x));
-	  };
-	};
-
-
-/***/ },
-/* 59 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175),
-
-	      BigNumber = math.type.BigNumber,
-	      Complex = __webpack_require__(7),
-	      collection = math.collection,
-
-	      isNumber = util.number.isNumber,
-	      isBoolean = util['boolean'].isBoolean,
-	      isComplex = Complex.isComplex,
-	      isCollection = collection.isCollection;
-
-	  /**
-	   * Round a value towards minus infinity.
-	   * For matrices, the function is evaluated element wise.
-	   *
-	   * Syntax:
-	   *
-	   *    math.floor(x)
-	   *
-	   * Examples:
-	   *
-	   *    math.floor(3.2);              // returns Number 3
-	   *    math.floor(3.8);              // returns Number 3
-	   *    math.floor(-4.2);             // returns Number -5
-	   *    math.floor(-4.7);             // returns Number -5
-	   *
-	   *    var c = math.complex(3.2, -2.7);
-	   *    math.floor(c);                // returns Complex 3 - 3i
-	   *
-	   *    math.floor([3.2, 3.8, -4.7]); // returns Array [3, 3, -5]
-	   *
-	   * See also:
-	   *
-	   *    ceil, fix, round
-	   *
-	   * @param  {Number | BigNumber | Boolean | Complex | Array | Matrix | null} x  Number to be rounded
-	   * @return {Number | BigNumber | Complex | Array | Matrix} Rounded value
-	   */
-	  math.floor = function floor(x) {
-	    if (arguments.length != 1) {
-	      throw new math.error.ArgumentsError('floor', arguments.length, 1);
-	    }
-
-	    if (isNumber(x)) {
-	      return Math.floor(x);
-	    }
-
-	    if (isComplex(x)) {
-	      return new Complex (
-	          Math.floor(x.re),
-	          Math.floor(x.im)
-	      );
-	    }
-
-	    if (x instanceof BigNumber) {
-	      return x.floor();
-	    }
-
-	    if (isCollection(x)) {
-	      // deep map collection, skip zeros since floor(0) = 0
-	      return collection.deepMap(x, floor, true);
-	    }
-
-	    if (isBoolean(x) || x === null) {
-	      return floor(+x);
-	    }
-
-	    throw new math.error.UnsupportedTypeError('floor', math['typeof'](x));
-	  };
-	};
-
-
-/***/ },
-/* 60 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175),
-
-	      BigNumber = math.type.BigNumber,
-	      collection = math.collection,
-
-	      isNumber = util.number.isNumber,
-	      isBoolean = util['boolean'].isBoolean,
-	      isInteger = util.number.isInteger,
-	      isCollection = collection.isCollection;
-
-	  /**
-	   * Calculate the greatest common divisor for two or more values or arrays.
-	   *
-	   * For matrices, the function is evaluated element wise.
-	   *
-	   * Syntax:
-	   *
-	   *    math.gcd(a, b)
-	   *    math.gcd(a, b, c, ...)
-	   *
-	   * Examples:
-	   *
-	   *    math.gcd(8, 12);              // returns 4
-	   *    math.gcd(-4, 6);              // returns 2
-	   *    math.gcd(25, 15, -10);        // returns 5
-	   *
-	   *    math.gcd([8, -4], [12, 6]);   // returns [4, 2]
-	   *
-	   * See also:
-	   *
-	   *    lcm, xgcd
-	   *
-	   * @param {... Number | BigNumber | Boolean | Array | Matrix | null} args  Two or more integer numbers
-	   * @return {Number | BigNumber | Array | Matrix}                           The greatest common divisor
-	   */
-	  math.gcd = function gcd(args) {
-	    var a = arguments[0],
-	        b = arguments[1],
-	        r; // remainder
-
-	    if (arguments.length == 2) {
-	      // two arguments
-	      if (isNumber(a) && isNumber(b)) {
-	        if (!isInteger(a) || !isInteger(b)) {
-	          throw new Error('Parameters in function gcd must be integer numbers');
-	        }
-
-	        // http://en.wikipedia.org/wiki/Euclidean_algorithm
-	        while (b != 0) {
-	          r = a % b;
-	          a = b;
-	          b = r;
-	        }
-	        return (a < 0) ? -a : a;
-	      }
-
-	      // evaluate gcd element wise
-	      if (isCollection(a) || isCollection(b)) {
-	        return collection.deepMap2(a, b, gcd);
-	      }
-
-	      if (a instanceof BigNumber) {
-	        // try to convert to big number
-	        if (isNumber(b)) {
-	          b = BigNumber.convert(b);
-	        }
-	        else if (isBoolean(b) || b === null) {
-	          b = new BigNumber(b ? 1 : 0);
-	        }
-
-	        if (b instanceof BigNumber) {
-	          return _bigGcd(a, b);
-	        }
-
-	        // downgrade to Number
-	        return gcd(a.toNumber(), b);
-	      }
-	      if (b instanceof BigNumber) {
-	        // try to convert to big number
-	        if (isNumber(a)) {
-	          a = BigNumber.convert(a);
-	        }
-	        else if (isBoolean(a) || a === null) {
-	          a = new BigNumber(a ? 1 : 0);
-	        }
-
-	        if (a instanceof BigNumber) {
-	          return _bigGcd(a, b);
-	        }
-
-	        // downgrade to Number
-	        return gcd(a.toNumber(), b);
-	      }
-
-	      if (isBoolean(a) || a === null) {
-	        return gcd(+a, b);
-	      }
-	      if (isBoolean(b) || b === null) {
-	        return gcd(a, +b);
-	      }
-
-	      throw new math.error.UnsupportedTypeError('gcd', math['typeof'](a), math['typeof'](b));
-	    }
-
-	    if (arguments.length > 2) {
-	      // multiple arguments. Evaluate them iteratively
-	      for (var i = 1; i < arguments.length; i++) {
-	        a = gcd(a, arguments[i]);
-	      }
-	      return a;
-	    }
-
-	    // zero or one argument
-	    throw new SyntaxError('Function gcd expects two or more arguments');
-	  };
-
-	  /**
-	   * Calculate gcd for BigNumbers
-	   * @param {BigNumber} a
-	   * @param {BigNumber} b
-	   * @returns {BigNumber} greatest common denominator of a and b
-	   * @private
-	   */
-	  function _bigGcd(a, b) {
-	    if (!a.isInt() || !b.isInt()) {
-	      throw new Error('Parameters in function gcd must be integer numbers');
-	    }
-
-	    // http://en.wikipedia.org/wiki/Euclidean_algorithm
-	    var zero = new BigNumber(0);
-	    while (!b.isZero()) {
-	      var r = a.mod(b);
-	      a = b;
-	      b = r;
-	    }
-	    return a.lt(zero) ? a.neg() : a;
-	  }
-	};
-
-
-/***/ },
-/* 61 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175),
-
-	      BigNumber = math.type.BigNumber,
-	      collection = math.collection,
-
-	      isNumber = util.number.isNumber,
-	      isBoolean = util['boolean'].isBoolean,
-	      isInteger = util.number.isInteger,
-	      isCollection = collection.isCollection;
-
-	  /**
-	   * Calculate the least common multiple for two or more values or arrays.
-	   *
-	   * lcm is defined as:
-	   *
-	   *     lcm(a, b) = abs(a * b) / gcd(a, b)
-	   *
-	   * For matrices, the function is evaluated element wise.
-	   *
-	   * Syntax:
-	   *
-	   *    math.lcm(a, b)
-	   *    math.lcm(a, b, c, ...)
-	   *
-	   * Examples:
-	   *
-	   *    math.lcm(4, 6);               // returns 12
-	   *    math.lcm(6, 21);              // returns 42
-	   *    math.lcm(6, 21, 5);           // returns 210
-	   *
-	   *    math.lcm([4, 6], [6, 21]);    // returns [12, 42]
-	   *
-	   * See also:
-	   *
-	   *    gcd, xgcd
-	   *
-	   * @param {... Number | BigNumber | Boolean | Array | Matrix | null} args  Two or more integer numbers
-	   * @return {Number | BigNumber | Array | Matrix}                           The least common multiple
-	   */
-	  math.lcm = function lcm(args) {
-	    var a = arguments[0],
-	        b = arguments[1],
-	        t;
-
-	    if (arguments.length == 2) {
-	      // two arguments
-	      if (isNumber(a) && isNumber(b)) {
-	        if (!isInteger(a) || !isInteger(b)) {
-	          throw new Error('Parameters in function lcm must be integer numbers');
-	        }
-
-	        if (a == 0 || b == 0) {
-	          return 0;
-	        }
-
-	        // http://en.wikipedia.org/wiki/Euclidean_algorithm
-	        // evaluate lcm here inline to reduce overhead
-	        var prod = a * b;
-	        while (b != 0) {
-	          t = b;
-	          b = a % t;
-	          a = t;
-	        }
-	        return Math.abs(prod / a);
-	      }
-
-	      // evaluate lcm element wise
-	      if (isCollection(a) || isCollection(b)) {
-	        return collection.deepMap2(a, b, lcm);
-	      }
-
-	      if (a instanceof BigNumber) {
-	        // try to convert to big number
-	        if (isNumber(b)) {
-	          b = BigNumber.convert(b);
-	        }
-	        else if (isBoolean(b) || b === null) {
-	          b = new BigNumber(b ? 1 : 0);
-	        }
-
-	        if (b instanceof BigNumber) {
-	          return _bigLcm(a, b);
-	        }
-
-	        // downgrade to Number
-	        return lcm(a.toNumber(), b);
-	      }
-	      if (b instanceof BigNumber) {
-	        // try to convert to big number
-	        if (isNumber(a)) {
-	          a = BigNumber.convert(a);
-	        }
-	        else if (isBoolean(a) || a === null) {
-	          a = new BigNumber(a ? 1 : 0);
-	        }
-
-	        if (a instanceof BigNumber) {
-	          return _bigLcm(a, b);
-	        }
-
-	        // downgrade to Number
-	        return lcm(a.toNumber(), b);
-	      }
-
-	      if (isBoolean(a) || a === null) {
-	        return lcm(+a, b);
-	      }
-	      if (isBoolean(b) || b === null) {
-	        return lcm(a, +b);
-	      }
-
-	      throw new math.error.UnsupportedTypeError('lcm', math['typeof'](a), math['typeof'](b));
-	    }
-
-	    if (arguments.length > 2) {
-	      // multiple arguments. Evaluate them iteratively
-	      for (var i = 1; i < arguments.length; i++) {
-	        a = lcm(a, arguments[i]);
-	      }
-	      return a;
-	    }
-
-	    // zero or one argument
-	    throw new SyntaxError('Function lcm expects two or more arguments');
-	  };
-
-	  /**
-	   * Calculate lcm for BigNumbers
-	   * @param {BigNumber} a
-	   * @param {BigNumber} b
-	   * @returns {BigNumber} the least common multiple of a and b
-	   * @private
-	   */
-	  function _bigLcm(a, b) {
-	    if (!a.isInt() || !b.isInt()) {
-	      throw new Error('Parameters in function lcm must be integer numbers');
-	    }
-
-	    if (a.isZero() || b.isZero()) {
-	      return new BigNumber(0);
-	    }
-
-	    // http://en.wikipedia.org/wiki/Euclidean_algorithm
-	    // evaluate lcm here inline to reduce overhead
-	    var prod = a.times(b);
-	    while (!b.isZero()) {
-	      var t = b;
-	      b = a.mod(t);
-	      a = t;
-	    }
-	    return prod.div(a).abs();
-	  }
-	};
-
-
-/***/ },
-/* 62 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175),
-
-	      BigNumber = math.type.BigNumber,
-	      Complex = __webpack_require__(7),
-	      collection = math.collection,
-
-	      isNumber = util.number.isNumber,
-	      isBoolean = util['boolean'].isBoolean,
-	      isComplex = Complex.isComplex,
-	      isCollection = collection.isCollection;
-
-	  /**
-	   * Calculate the logarithm of a value.
-	   *
-	   * For matrices, the function is evaluated element wise.
-	   *
-	   * Syntax:
-	   *
-	   *    math.log(x)
-	   *    math.log(x, base)
-	   *
-	   * Examples:
-	   *
-	   *    math.log(3.5);                  // returns 1.252762968495368
-	   *    math.exp(math.log(2.4));        // returns 2.4
-	   *
-	   *    math.pow(10, 4);                // returns 10000
-	   *    math.log(10000, 10);            // returns 4
-	   *    math.log(10000) / math.log(10); // returns 4
-	   *
-	   *    math.log(1024, 2);              // returns 10
-	   *    math.pow(2, 10);                // returns 1024
-	   *
-	   * See also:
-	   *
-	   *    exp, log10
-	   *
-	   * @param {Number | BigNumber | Boolean | Complex | Array | Matrix | null} x
-	   *            Value for which to calculate the logarithm.
-	   * @param {Number | BigNumber | Boolean | Complex | null} [base=e]
-	   *            Optional base for the logarithm. If not provided, the natural
-	   *            logarithm of `x` is calculated.
-	   * @return {Number | BigNumber | Complex | Array | Matrix}
-	   *            Returns the logarithm of `x`
-	   */
-	  math.log = function log(x, base) {
-	    if (arguments.length == 1) {
-	      // calculate natural logarithm, log(x)
-	      if (isNumber(x)) {
-	        if (x >= 0) {
-	          return Math.log(x);
-	        }
-	        else {
-	          // negative value -> complex value computation
-	          return log(new Complex(x, 0));
-	        }
-	      }
-
-	      if (isComplex(x)) {
-	        return new Complex (
-	            Math.log(Math.sqrt(x.re * x.re + x.im * x.im)),
-	            Math.atan2(x.im, x.re)
-	        );
-	      }
-
-	      if (x instanceof BigNumber) {
-	        if (x.isNegative()) {
-	          // negative value -> downgrade to number to do complex value computation
-	          return log(x.toNumber());
-	        }
-	        else {
-	          return x.ln();
-	        }
-	      }
-
-	      if (isCollection(x)) {
-	        return collection.deepMap(x, log);
-	      }
-
-	      if (isBoolean(x) || x === null) {
-	        return log(+x);
-	      }
-
-	      throw new math.error.UnsupportedTypeError('log', math['typeof'](x));
-	    }
-	    else if (arguments.length == 2) {
-	      // calculate logarithm for a specified base, log(x, base)
-	      return math.divide(log(x), log(base));
-	    }
-	    else {
-	      throw new math.error.ArgumentsError('log', arguments.length, 1, 2);
-	    }
-	  };
-	};
-
-
-/***/ },
-/* 63 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175),
-
-	      BigNumber = math.type.BigNumber,
-	      Complex = __webpack_require__(7),
-	      collection = math.collection,
-
-	      isNumber = util.number.isNumber,
-	      isBoolean = util['boolean'].isBoolean,
-	      isComplex = Complex.isComplex,
-	      isCollection = collection.isCollection;
-
-	  /**
-	   * Calculate the 10-base of a value. This is the same as calculating `log(x, 10)`.
-	   *
-	   * For matrices, the function is evaluated element wise.
-	   *
-	   * Syntax:
-	   *
-	   *    math.log10(x)
-	   *
-	   * Examples:
-	   *
-	   *    math.log10(0.00001);            // returns -5
-	   *    math.log10(10000);              // returns 4
-	   *    math.log(10000) / math.log(10); // returns 4
-	   *    math.pow(10, 4);                // returns 10000
-	   *
-	   * See also:
-	   *
-	   *    exp, log
-	   *
-	   * @param {Number | BigNumber | Boolean | Complex | Array | Matrix | null} x
-	   *            Value for which to calculate the logarithm.
-	   * @return {Number | BigNumber | Complex | Array | Matrix}
-	   *            Returns the 10-base logarithm of `x`
-	   */
-	  math.log10 = function log10(x) {
-	    if (arguments.length != 1) {
-	      throw new math.error.ArgumentsError('log10', arguments.length, 1);
-	    }
-
-	    if (isNumber(x)) {
-	      if (x >= 0) {
-	        return Math.log(x) / Math.LN10;
-	      }
-	      else {
-	        // negative value -> complex value computation
-	        return log10(new Complex(x, 0));
-	      }
-	    }
-
-	    if (x instanceof BigNumber) {
-	      if (x.isNegative()) {
-	        // negative value -> downgrade to number to do complex value computation
-	        return log10(x.toNumber());
-	      }
-	      else {
-	        return x.log();
-	      }
-	    }
-
-	    if (isComplex(x)) {
-	      return new Complex (
-	          Math.log(Math.sqrt(x.re * x.re + x.im * x.im)) / Math.LN10,
-	          Math.atan2(x.im, x.re) / Math.LN10
-	      );
-	    }
-
-	    if (isCollection(x)) {
-	      return collection.deepMap(x, log10);
-	    }
-
-	    if (isBoolean(x) || x === null) {
-	      return log10(+x);
-	    }
-
-	    throw new math.error.UnsupportedTypeError('log10', math['typeof'](x));
-	  };
-	};
-
-
-/***/ },
-/* 64 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175),
-
-	      BigNumber = math.type.BigNumber,
-	      collection = math.collection,
-
-	      isNumber = util.number.isNumber,
-	      isBoolean = util['boolean'].isBoolean,
-	      isCollection = collection.isCollection;
-
-	  /**
-	   * Calculates the modulus, the remainder of an integer division.
-	   *
-	   * For matrices, the function is evaluated element wise.
-	   *
-	   * The modulus is defined as:
-	   *
-	   *     x - y * floor(x / y)
-	   *
-	   * See http://en.wikipedia.org/wiki/Modulo_operation.
-	   *
-	   * Syntax:
-	   *
-	   *    math.mod(x, y)
-	   *
-	   * Examples:
-	   *
-	   *    math.mod(8, 3);                // returns 2
-	   *    math.mod(11, 2);               // returns 1
-	   *
-	   *    function isOdd(x) {
-	   *      return math.mod(x, 2) != 0;
-	   *    }
-	   *
-	   *    isOdd(2);                      // returns false
-	   *    isOdd(3);                      // returns true
-	   *
-	   * See also:
-	   *
-	   *    divide
-	   *
-	   * @param  {Number | BigNumber | Boolean | Array | Matrix | null} x Dividend
-	   * @param  {Number | BigNumber | Boolean | Array | Matrix | null} y Divisor
-	   * @return {Number | BigNumber | Array | Matrix} Returns the remainder of `x` divided by `y`.
-	   */
-	  math.mod = function mod(x, y) {
-	    if (arguments.length != 2) {
-	      throw new math.error.ArgumentsError('mod', arguments.length, 2);
-	    }
-
-	    // see http://functions.wolfram.com/IntegerFunctions/Mod/
-
-	    if (isNumber(x)) {
-	      if (isNumber(y)) {
-	        // number % number
-	        return _mod(x, y);
-	      }
-	    }
-
-	    if (x instanceof BigNumber) {
-	      // try to convert to big number
-	      if (isNumber(y)) {
-	        y = BigNumber.convert(y);
-	      }
-	      else if (isBoolean(y) || y === null) {
-	        y = new BigNumber(y ? 1 : 0);
-	      }
-
-	      if (y instanceof BigNumber) {
-	        return y.isZero() ? x : x.mod(y);
-	      }
-
-	      // downgrade x to Number
-	      return mod(x.toNumber(), y);
-	    }
-	    if (y instanceof BigNumber) {
-	      // try to convert to big number
-	      if (isNumber(x)) {
-	        x = BigNumber.convert(x);
-	      }
-	      else if (isBoolean(x) || x === null) {
-	        x = new BigNumber(x ? 1 : 0);
-	      }
-
-	      if (x instanceof BigNumber) {
-	        return y.isZero() ? x : x.mod(y);
-	      }
-
-	      // downgrade y to Number
-	      return mod(x, y.toNumber());
-	    }
-
-	    // TODO: implement mod for complex values
-
-	    if (isCollection(x) || isCollection(y)) {
-	      return collection.deepMap2(x, y, mod);
-	    }
-
-	    if (isBoolean(x) || x === null) {
-	      return mod(+x, y);
-	    }
-	    if (isBoolean(y) || y === null) {
-	      return mod(x, +y);
-	    }
-
-	    throw new math.error.UnsupportedTypeError('mod', math['typeof'](x), math['typeof'](y));
-	  };
-
-	  /**
-	   * Calculate the modulus of two numbers
-	   * @param {Number} x
-	   * @param {Number} y
-	   * @returns {number} res
-	   * @private
-	   */
-	  function _mod(x, y) {
-	    if (y > 0) {
-	      // We don't use JavaScript's % operator here as this doesn't work
-	      // correctly for x < 0 and x == 0
-	      // see http://en.wikipedia.org/wiki/Modulo_operation
-	      return x - y * Math.floor(x / y);
-	    }
-	    else if (y == 0) {
-	      return x;
-	    }
-	    else { // y < 0
-	      // TODO: implement mod for a negative divisor
-	      throw new Error('Cannot calculate mod for a negative divisor');
-	    }
-	  }
-	};
-
-
-/***/ },
-/* 65 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function(math) {
-	  var util = __webpack_require__(175),
-
-	      BigNumber = math.type.BigNumber,
-	      Complex = __webpack_require__(7),
-	      Matrix = math.type.Matrix,
-	      Unit = __webpack_require__(11),
-	      collection = math.collection,
-
-	      isNumber = util.number.isNumber,
-	      isBoolean = util['boolean'].isBoolean,
-	      isComplex = Complex.isComplex,
-	      isArray = Array.isArray,
-	      isUnit = Unit.isUnit;
-
-	  /**
-	   * Multiply two values, `x * y`. The result is squeezed.
-	   * For matrices, the matrix product is calculated.
-	   *
-	   * Syntax:
-	   *
-	   *    math.multiply(x, y)
-	   *
-	   * Examples:
-	   *
-	   *    math.multiply(4, 5.2);        // returns Number 20.8
-	   *
-	   *    var a = math.complex(2, 3);
-	   *    var b = math.complex(4, 1);
-	   *    math.multiply(a, b);          // returns Complex 5 + 14i
-	   *
-	   *    var c = [[1, 2], [4, 3]];
-	   *    var d = [[1, 2, 3], [3, -4, 7]];
-	   *    math.multiply(c, d);          // returns Array [[7, -6, 17], [13, -4, 33]]
-	   *
-	   *    var e = math.unit('2.1 km');
-	   *    math.multiply(3, e);          // returns Unit 6.3 km
-	   *
-	   * See also:
-	   *
-	   *    divide
-	   *
-	   * @param  {Number | BigNumber | Boolean | Complex | Unit | Array | Matrix | null} x First value to multiply
-	   * @param  {Number | BigNumber | Boolean | Complex | Unit | Array | Matrix | null} y Second value to multiply
-	   * @return {Number | BigNumber | Complex | Unit | Array | Matrix} Multiplication of `x` and `y`
-	   */
-	  math.multiply = function multiply(x, y) {
-	    var res;
-
-	    if (arguments.length != 2) {
-	      throw new math.error.ArgumentsError('multiply', arguments.length, 2);
-	    }
-
-	    if (isNumber(x)) {
-	      if (isNumber(y)) {
-	        // number * number
-	        return x * y;
-	      }
-	      else if (isComplex(y)) {
-	        // number * complex
-	        return _multiplyComplex(new Complex(x, 0), y);
-	      }
-	      else if (isUnit(y)) {
-	        res = y.clone();
-	        res.value = (res.value === null) ? res._normalize(x) : (res.value * x);
-	        return res;
-	      }
-	    }
-
-	    if (isComplex(x)) {
-	      if (isNumber(y)) {
-	        // complex * number
-	        return _multiplyComplex(x, new Complex(y, 0));
-	      }
-	      else if (isComplex(y)) {
-	        // complex * complex
-	        return _multiplyComplex(x, y);
-	      }
-	    }
-
-	    if (x instanceof BigNumber) {
-	      // try to convert to big number
-	      if (isNumber(y)) {
-	        y = BigNumber.convert(y);
-	      }
-	      else if (isBoolean(y) || y === null) {
-	        y = new BigNumber(y ? 1 : 0);
-	      }
-
-	      if (y instanceof BigNumber) {
-	        return x.times(y);
-	      }
-
-	      // downgrade to Number
-	      return multiply(x.toNumber(), y);
-	    }
-	    if (y instanceof BigNumber) {
-	      // try to convert to big number
-	      if (isNumber(x)) {
-	        x = BigNumber.convert(x);
-	      }
-	      else if (isBoolean(x) || x === null) {
-	        x = new BigNumber(x ? 1 : 0);
-	      }
-
-	      if (x instanceof BigNumber) {
-	        return x.times(y);
-	      }
-
-	      // downgrade to Number
-	      return multiply(x, y.toNumber());
-	    }
-
-	    if (isUnit(x)) {
-	      if (isNumber(y)) {
-	        res = x.clone();
-	        res.value = (res.value === null) ? res._normalize(y) : (res.value * y);
-	        return res;
-	      }
-	    }
-
-	    if (isArray(x)) {
-	      // create dense matrix from array
-	      var m = math.matrix(x);
-	      // use optimized operations in matrix
-	      var r = m.multiply(y);
-	      // check result
-	      if (r instanceof Matrix) {
-	        // check we need to return a matrix
-	        if (y instanceof Matrix)
-	          return r;
-	        // output should be an array
-	        return r.valueOf();
-	      }
-	      // scalar
-	      return r;
-	    }
-
-	    if (x instanceof Matrix) {
-	      // use optimized matrix implementation
-	      return x.multiply(y);
-	    }
-
-	    if (isArray(y)) {
-	      // scalar * array
-	      return collection.deepMap2(x, y, multiply);
-	    }
-	    else if (y instanceof Matrix) {
-	      // adapter function
-	      var mf = function (v) {
-	        return multiply(x, v);
-	      };
-	      // scalar * matrix
-	      return collection.deepMap(y, mf, true);
-	    }
-
-	    if (isBoolean(x) || x === null) {
-	      return multiply(+x, y);
-	    }
-	    if (isBoolean(y) || y === null) {
-	      return multiply(x, +y);
-	    }
-
-	    throw new math.error.UnsupportedTypeError('multiply', math['typeof'](x), math['typeof'](y));
-	  };
-
-	  /**
-	   * Multiply two complex numbers. x * y or multiply(x, y)
-	   * @param {Complex} x
-	   * @param {Complex} y
-	   * @return {Complex | Number} res
-	   * @private
-	   */
-	  function _multiplyComplex (x, y) {
-	    // Note: we test whether x or y are pure real or pure complex,
-	    // to prevent unnecessary NaN values. For example, Infinity*i should
-	    // result in Infinity*i, and not in NaN+Infinity*i
-
-	    if (x.im == 0) {
-	      // x is pure real
-	      if (y.im == 0) {
-	        // y is pure real
-	        return new Complex(x.re * y.re, 0);
-	      }
-	      else if (y.re == 0) {
-	        // y is pure complex
-	        return new Complex(
-	            0,
-	            x.re * y.im
-	        );
-	      }
-	      else {
-	        // y has a real and complex part
-	        return new Complex(
-	            x.re * y.re,
-	            x.re * y.im
-	        );
-	      }
-	    }
-	    else if (x.re == 0) {
-	      // x is pure complex
-	      if (y.im == 0) {
-	        // y is pure real
-	        return new Complex(
-	            0,
-	            x.im * y.re
-	        );
-	      }
-	      else if (y.re == 0) {
-	        // y is pure complex
-	        return new Complex(-x.im * y.im, 0);
-	      }
-	      else {
-	        // y has a real and complex part
-	        return new Complex(
-	            -x.im * y.im,
-	            x.im * y.re
-	        );
-	      }
-	    }
-	    else {
-	      // x has a real and complex part
-	      if (y.im == 0) {
-	        // y is pure real
-	        return new Complex(
-	            x.re * y.re,
-	            x.im * y.re
-	        );
-	      }
-	      else if (y.re == 0) {
-	        // y is pure complex
-	        return new Complex(
-	            -x.im * y.im,
-	            x.re * y.im
-	        );
-	      }
-	      else {
-	        // y has a real and complex part
-	        return new Complex(
-	            x.re * y.re - x.im * y.im,
-	            x.re * y.im + x.im * y.re
-	        );
-	      }
-	    }
-	  }
-	};
-
-
-/***/ },
-/* 66 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175),
-
-	    BigNumber = math.type.BigNumber,
-	    Complex = __webpack_require__(7),
-	    Matrix = math.type.Matrix,
-
-	    isNumber = util.number.isNumber,
-	    isBoolean = util['boolean'].isBoolean,
-	    isComplex = Complex.isComplex,
-	    isArray = Array.isArray;
-
-	  /**
-	   * Calculate the norm of a number, vector or matrix.
-	   *
-	   * The second parameter p is optional. If not provided, it defaults to 2.
-	   *
-	   * Syntax:
-	   *
-	   *    math.norm(x)
-	   *    math.norm(x, p)
-	   *
-	   * Examples:
-	   *
-	   *    math.abs(-3.5);                         // returns 3.5
-	   *    math.norm(-3.5);                        // returns 3.5
-	   *
-	   *    math.norm(math.complex(3, -4));         // returns 5
-	   *
-	   *    math.norm([1, 2, -3], Infinity);        // returns 3
-	   *    math.norm([1, 2, -3], -Infinity);       // returns 1
-	   *
-	   *    math.norm([3, 4], 2);                   // returns 5
-	   *
-	   *    math.norm([[1, 2], [3, 4]], 1)          // returns 6
-	   *    math.norm([[1, 2], [3, 4]], 'inf');     // returns 7
-	   *    math.norm([[1, 2], [3, 4]], 'fro');     // returns 5.477225575051661
-	   *
-	   * See also:
-	   *
-	   *    abs
-	   *
-	   * @param  {Number | BigNumber | Complex | Boolean | Array | Matrix | null} x
-	   *            Value for which to calculate the norm
-	   * @param  {Number | String} [p=2]
-	   *            Vector space.
-	   *            Supported numbers include Infinity and -Infinity.
-	   *            Supported strings are: 'inf', '-inf', and 'fro' (The Frobenius norm)
-	   * @return {Number} the p-norm
-	   */
-	  math.norm = function norm(x, p) {
-	    if (arguments.length < 1 || arguments.length > 2) {
-	      throw new math.error.ArgumentsError('abs', arguments.length, 1, 2);
-	    }
-
-	    if (isNumber(x)) {
-	      // norm(x) = abs(x)
-	      return Math.abs(x);
-	    }
-
-	    if (isComplex(x)) {
-	      // do not compute sqrt(re * re + im * im) since it will overflow with big numbers!
-	      var re = Math.abs(x.re);
-	      var im = Math.abs(x.im);
-	      if (re >= im) {
-	        var i = im / re;
-	        return re * Math.sqrt(1 + i * i);
-	      }
-	      var j = re / im;
-	      return im * Math.sqrt(1 + j * j);
-	    }
-
-	    if (x instanceof BigNumber) {
-	      // norm(x) = abs(x)
-	      return x.abs();
-	    }
-
-	    if (isBoolean(x) || x === null) {
-	      // norm(x) = abs(x)
-	      return Math.abs(x);
-	    }
-
-	    if (isArray(x)) {
-	      // use matrix optimized operations
-	      return norm(math.matrix(x), p);
-	    }
-	    
-	    if (x instanceof Matrix) {
-	      // size
-	      var sizeX = x.size();
-	      // missing p
-	      if (p == null)
-	        p = 2;
-	      // check it is a Vector
-	      if (sizeX.length == 1) {
-	        // check p
-	        if (p === Number.POSITIVE_INFINITY || p === 'inf') {
-	          // norm(x, Infinity) = max(abs(x))
-	          var n;
-	          x.forEach(
-	            function (value) {
-	              var v = math.abs(value);
-	              if (!n || math.larger(v, n))
-	                n = v;
-	            },
-	            true);
-	          return n;
-	        }
-	        if (p === Number.NEGATIVE_INFINITY || p === '-inf') {
-	          // norm(x, -Infinity) = min(abs(x))
-	          var n;
-	          x.forEach(
-	            function (value) {
-	              var v = math.abs(value);
-	              if (!n || math.smaller(v, n))
-	                n = v;
-	            },
-	            true);
-	          return n;
-	        }
-	        if (p === 'fro')
-	            return norm(x);
-	        if (isNumber(p) && !isNaN(p)) {
-	          // check p != 0
-	          if (!math.equal(p, 0)) {
-	            // norm(x, p) = sum(abs(xi) ^ p) ^ 1/p
-	            var n = 0;
-	            x.forEach(
-	              function (value) {
-	                n = math.add(math.pow(math.abs(value), p), n);
-	              },
-	              true);
-	            return math.pow(n, 1 / p);
-	          }
-	          return Number.POSITIVE_INFINITY;
-	        }
-	        // invalid parameter value
-	        throw new Error('Unsupported parameter value');
-	      }
-	      else if (sizeX.length == 2) {
-	        // check p
-	        if (p == 1) {
-	          // norm(x) = the largest column sum
-	          var c = [];
-	          x.forEach(
-	            function (value, index) {
-	              var j = index[1];
-	              c[j] = math.add(c[j] || 0, math.abs(value));
-	            },
-	            true);
-	          return math.max(c);
-	        }
-	        if (p == Number.POSITIVE_INFINITY || p === 'inf') {
-	          // norm(x) = the largest row sum
-	          var r = [];
-	          x.forEach(
-	            function (value, index) {
-	              var i = index[0];
-	              r[i] = math.add(r[i] || 0, math.abs(value));
-	            },
-	            true);
-	          return math.max(r);
-	        }
-	        if (p === 'fro') {
-	          // norm(x) = sqrt(sum(diag(x'x)))
-	          return math.sqrt(x.transpose().multiply(x).trace());
-	        }
-	        if (p == 2) {
-	          // not implemented
-	          throw new Error('Unsupported parameter value, missing implementation of matrix singular value decomposition');
-	        }
-	        // invalid parameter value
-	        throw new Error('Unsupported parameter value');
-	      }
-	    }
-
-	    throw new math.error.UnsupportedTypeError('norm', x);
-	  };
-	};
-
-
-/***/ },
-/* 67 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175);
-
-	  var BigNumber = math.type.BigNumber;
-	  var collection = math.collection;
-
-	  var isNumber = util.number.isNumber;
-	  var isBoolean = util['boolean'].isBoolean;
-	  var isCollection = collection.isCollection;
-
-	  /**
-	   * Calculate the nth root of a value.
-	   * The principal nth root of a positive real number A, is the positive real
-	   * solution of the equation
-	   *
-	   *     x^root = A
-	   *
-	   * For matrices, the function is evaluated element wise.
-	   *
-	   * Syntax:
-	   *
-	   *     math.nthRoot(a, root)
-	   *
-	   * Examples:
-	   *
-	   *     math.nthRoot(9, 2);    // returns 3, as 3^2 == 9
-	   *     math.sqrt(9);          // returns 3, as 3^2 == 9
-	   *     math.nthRoot(64, 3);   // returns 4, as 4^3 == 64
-	   *
-	   * See also:
-	   *
-	   *     sqrt, pow
-	   *
-	   * @param {Number | BigNumber | Boolean | Array | Matrix | null} a
-	   *              Value for which to calculate the nth root
-	   * @param {Number | BigNumber | Boolean | null} [root=2]    The root.
-	   * @return {Number | Complex | Array | Matrix} Returns the nth root of `a`
-	   */
-	  math.nthRoot = function nthRoot (a, root) {
-	    if (arguments.length != 1 && arguments.length != 2) {
-	      throw new math.error.ArgumentsError('nthRoot', arguments.length, 1, 2);
-	    }
-
-	    switch(arguments.length) {
-	      case 1:
-	        if (isNumber(a)) {
-	          return _nthRoot(a);
-	        }
-	        else if (a instanceof BigNumber) {
-	          return _nthRootBig(a);
-	        }
-	        else if (isCollection(a)) {
-	          return collection.deepMap(x, nthRoot);
-	        }
-
-	        if (isBoolean(a) || a === null) {
-	          return nthRoot(+a);
-	        }
-
-	        break;
-
-	      case 2:
-	        if (isNumber(a)) {
-	          if (isNumber(root)) {
-	            return _nthRoot(a, root);
-	          }
-	          else if (root instanceof BigNumber) {
-	            // try to convert to bignumber
-	            a = BigNumber.convert(a);
-
-	            if (a instanceof BigNumber) {
-	              return _nthRootBig(a, root);
-	            }
-	            else {
-	              // downgrade to number
-	              return _nthRoot(a, root.toNumber());
-	            }
-	          }
-	        }
-	        else if (a instanceof BigNumber) {
-	          // try to convert to bignumber
-	          if (isNumber(root)) {
-	            root = BigNumber.convert(root);
-	          }
-
-	          if (root instanceof BigNumber) {
-	            return _nthRootBig(a, root);
-	          }
-	          else {
-	            // downgrade to number
-	            return _nthRoot(a.toNumber(), root);
-	          }
-	        }
-	        else if (isCollection(a) && !isCollection(root)) {
-	          return collection.deepMap2(a, root, nthRoot);
-	        }
-
-	        if (isBoolean(a) || a === null) {
-	          return nthRoot(+a, root);
-	        }
-	        if (isBoolean(root) || root === null) {
-	          return nthRoot(a, +root);
-	        }
-
-	        break;
-
-	      default:
-	        throw new math.error.ArgumentsError('nthRoot', arguments.length, 1, 2);
-	    }
-
-	    if (isBoolean(x) || x === null) {
-	      return arguments.length == 2 ? nthRoot(+x, n) : nthRoot(+x);
-	    }
-
-
-	    throw new math.error.UnsupportedTypeError('nthRoot', math['typeof'](a), math['typeof'](root));
-	  };
-
-	  /**
-	   * Calculate the nth root of a, solve x^root == a
-	   * http://rosettacode.org/wiki/Nth_root#JavaScript
-	   * @param {number} a
-	   * @param {number} [root=2]
-	   * @private
-	   */
-	  function _nthRoot(a, root) {
-	    var _root = (root != undefined) ? root : 2;
-	    var inv = _root < 0;
-	    if (inv) _root = -_root;
-
-	    if (_root == 0) throw new Error('Root must be non-zero');
-	    if (a < 0 && (Math.abs(_root) % 2 != 1)) throw new Error('Root must be odd when a is negative.');
-
-	    // edge cases zero and infinity
-	    if (a == 0) return 0;
-	    if (!Number.isFinite(a)) {
-	      return inv ? 0 : a;
-	    }
-
-	    var epsilon = 1e-16;
-	    var x = 1; // Initial guess
-	    var i = 0;
-	    var iMax = 100;
-	    do {
-	      var delta = (a / Math.pow(x, _root - 1) - x) / _root;
-	      x = x + delta;
-	      i++;
-	    }
-	    while (Math.abs(delta) > epsilon && i < iMax);
-
-	    return inv ? 1 / x : x;
-	  }
-
-	  /**
-	   * Calculate the nth root of a for BigNumbers, solve x^root == a
-	   * http://rosettacode.org/wiki/Nth_root#JavaScript
-	   * @param {BigNumber} a
-	   * @param {BigNumber} [root=2]
-	   * @private
-	   */
-	  function _nthRootBig(a, root) {
-	    var _root = (root != undefined) ? root : new BigNumber(2);
-	    var zero = new BigNumber(0);
-	    var one = new BigNumber(1);
-	    var inv = _root.isNegative();
-	    if (inv) _root = _root.negated();
-
-	    if (_root.isZero()) throw new Error('Root must be non-zero');
-	    if (a.isNegative() && !_root.abs().mod(2).equals(1)) throw new Error('Root must be odd when a is negative.');
-
-	    // edge cases zero and infinity
-	    if (a.isZero()) return zero;
-	    if (!a.isFinite())
-	    {
-	      return inv ? zero : a;
-	    }
-
-	    var x = one; // Initial guess
-	    var i = 0;
-	    var iMax = 100;
-	    do {
-	      var xPrev = x;
-	      var delta = a.div(x.pow(_root.minus(1))).minus(x).div(_root);
-	      x = x.plus(delta);
-	      i++;
-	    }
-	    while (!x.equals(xPrev) && i < iMax);
-
-	    return inv ? one.div(x) : x;
-	  }
-	};
-
-
-/***/ },
-/* 68 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175),
-
-	      BigNumber = math.type.BigNumber,
-	      Complex = __webpack_require__(7),
-	      Matrix = math.type.Matrix,
-	      
-	      array = util.array,
-	      isNumber = util.number.isNumber,
-	      isBoolean = util.boolean.isBoolean,
-	      isArray = Array.isArray,
-	      isInteger = util.number.isInteger,
-	      isComplex = Complex.isComplex;
-
-	  /**
-	   * Calculates the power of x to y, `x ^ y`.
-	   * Matrix exponentiation is supported for square matrices `x`, and positive
-	   * integer exponents `y`.
-	   *
-	   * Syntax:
-	   *
-	   *    math.pow(x, y)
-	   *
-	   * Examples:
-	   *
-	   *    math.pow(2, 3);               // returns Number 8
-	   *
-	   *    var a = math.complex(2, 3);
-	   *    math.pow(a, 2)                // returns Complex -5 + 12i
-	   *
-	   *    var b = [[1, 2], [4, 3]];
-	   *    math.pow(b, 2);               // returns Array [[9, 8], [16, 17]]
-	   *
-	   * See also:
-	   *
-	   *    multiply, sqrt
-	   *
-	   * @param  {Number | BigNumber | Boolean | Complex | Array | Matrix | null} x  The base
-	   * @param  {Number | BigNumber | Boolean | Complex | null} y                   The exponent
-	   * @return {Number | BigNumber | Complex | Array | Matrix} The value of `x` to the power `y`
-	   */
-	  math.pow = function pow(x, y) {
-	    if (arguments.length != 2) {
-	      throw new math.error.ArgumentsError('pow', arguments.length, 2);
-	    }
-
-	    if (isNumber(x)) {
-	      if (isNumber(y)) {
-	        if (isInteger(y) || x >= 0) {
-	          // real value computation
-	          return Math.pow(x, y);
-	        }
-	        else {
-	          return powComplex(new Complex(x, 0), new Complex(y, 0));
-	        }
-	      }
-	      else if (isComplex(y)) {
-	        return powComplex(new Complex(x, 0), y);
-	      }
-	    }
-
-	    if (isComplex(x)) {
-	      if (isNumber(y)) {
-	        return powComplex(x, new Complex(y, 0));
-	      }
-	      else if (isComplex(y)) {
-	        return powComplex(x, y);
-	      }
-	    }
-
-	    if (x instanceof BigNumber) {
-	      // try to upgrade y to to bignumber
-	      if (isNumber(y)) {
-	        y = BigNumber.convert(y);
-	      }
-	      else if (isBoolean(y) || y === null) {
-	        y = new BigNumber(y ? 1 : 0);
-	      }
-
-	      if (y instanceof BigNumber) {
-	        if (y.isInteger() || !x.isNegative()) {
-	          return x.pow(y);
-	        }
-	        else {
-	          // downgrade to number to do complex valued computation
-	          return pow(x.toNumber(), y.toNumber());
-	        }
-	      }
-	      else {
-	        // failed to upgrade y to bignumber, lets downgrade x to number
-	        return pow(x.toNumber(), y);
-	      }
-	    }
-
-	    if (y instanceof BigNumber) {
-	      // try to convert x to bignumber
-	      if (isNumber(x)) {
-	        x = BigNumber.convert(x);
-	      }
-	      else if (isBoolean(x) || x === null) {
-	        x = new BigNumber(x ? 1 : 0);
-	      }
-
-	      if (x instanceof BigNumber) {
-	        if (y.isInteger() && !x.isNegative()) {
-	          return x.pow(y);
-	        }
-	        else {
-	          // downgrade to number to do complex valued computation
-	          return pow(x.toNumber(), y.toNumber());
-	        }
-	      }
-	      else {
-	        // failed to upgrade x to bignumber, lets downgrade y to number
-	        return pow(x, y.toNumber());
-	      }
-	    }
-
-	    if (isArray(x)) {
-	      if (!isNumber(y) || !isInteger(y) || y < 0) {
-	        throw new TypeError('For A^b, b must be a positive integer ' +
-	            '(value is ' + y + ')');
-	      }
-	      // verify that A is a 2 dimensional square matrix
-	      var s = array.size(x);
-	      if (s.length != 2) {
-	        throw new Error('For A^b, A must be 2 dimensional ' +
-	            '(A has ' + s.length + ' dimensions)');
-	      }
-	      if (s[0] != s[1]) {
-	        throw new Error('For A^b, A must be square ' +
-	            '(size is ' + s[0] + 'x' + s[1] + ')');
-	      }
-
-	      // compute power of matrix
-	      var res = math.eye(s[0]).valueOf();
-	      var px = x;
-	      while (y >= 1) {
-	        if ((y & 1) == 1) {
-	          res = math.multiply(px, res);
-	        }
-	        y >>= 1;
-	        px = math.multiply(px, px);
-	      }
-	      return res;
-	    }
-	    else if (x instanceof Matrix) {
-	      return math.matrix(pow(x.valueOf(), y));
-	    }
-
-	    if (isBoolean(x) || x === null) {
-	      return pow(+x, y);
-	    }
-	    if (isBoolean(y) || y === null) {
-	      return pow(x, +y);
-	    }
-
-	    throw new math.error.UnsupportedTypeError('pow', math['typeof'](x), math['typeof'](y));
-	  };
-
-	  /**
-	   * Calculates the power of x to y, x^y, for two complex numbers.
-	   * @param {Complex} x
-	   * @param {Complex} y
-	   * @return {Complex} res
-	   * @private
-	   */
-	  function powComplex (x, y) {
-	    // complex computation
-	    // x^y = exp(log(x)*y) = exp((abs(x)+i*arg(x))*y)
-	    var temp1 = math.log(x);
-	    var temp2 = math.multiply(temp1, y);
-	    return math.exp(temp2);
-	  }
-	};
-
-
-/***/ },
-/* 69 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175),
-
-	      BigNumber = math.type.BigNumber,
-	      Complex = __webpack_require__(7),
-	      collection = math.collection,
-
-	      isNumber = util.number.isNumber,
-	      isInteger = util.number.isInteger,
-	      isBoolean = util['boolean'].isBoolean,
-	      isComplex = Complex.isComplex,
-	      isCollection = collection.isCollection,
-	      toFixed = util.number.toFixed;
-
-	  /**
-	   * Round a value towards the nearest integer.
-	   * For matrices, the function is evaluated element wise.
-	   *
-	   * Syntax:
-	   *
-	   *    math.round(x)
-	   *    math.round(x, n)
-	   *
-	   * Examples:
-	   *
-	   *    math.round(3.2);              // returns Number 3
-	   *    math.round(3.8);              // returns Number 4
-	   *    math.round(-4.2);             // returns Number -4
-	   *    math.round(-4.7);             // returns Number -5
-	   *    math.round(math.pi, 3);       // returns Number 3.142
-	   *    math.round(123.45678, 2);     // returns Number 123.46
-	   *
-	   *    var c = math.complex(3.2, -2.7);
-	   *    math.round(c);                // returns Complex 3 - 3i
-	   *
-	   *    math.round([3.2, 3.8, -4.7]); // returns Array [3, 4, -5]
-	   *
-	   * See also:
-	   *
-	   *    ceil, fix, floor
-	   *
-	   * @param  {Number | BigNumber | Boolean | Complex | Array | Matrix | null} x   Number to be rounded
-	   * @param  {Number | BigNumber | Boolean | Array | null} [n=0]                 Number of decimals
-	   * @return {Number | BigNumber | Complex | Array | Matrix} Rounded value
-	   */
-	  math.round = function round(x, n) {
-	    if (arguments.length != 1 && arguments.length != 2) {
-	      throw new math.error.ArgumentsError('round', arguments.length, 1, 2);
-	    }
-
-	    if (n == undefined) {
-	      // round (x)
-	      if (isNumber(x)) {
-	        return Math.round(x);
-	      }
-
-	      if (isComplex(x)) {
-	        return new Complex (
-	            Math.round(x.re),
-	            Math.round(x.im)
-	        );
-	      }
-
-	      if (x instanceof BigNumber) {
-	        return x.toDecimalPlaces(0);
-	      }
-
-	      if (isCollection(x)) {
-	        return collection.deepMap(x, round);
-	      }
-
-	      if (isBoolean(x) || x === null) {
-	        return Math.round(x);
-	      }
-
-	      throw new math.error.UnsupportedTypeError('round', math['typeof'](x));
-	    }
-	    else {
-	      // round (x, n)
-	      if (!isNumber(n) || !isInteger(n)) {
-	        if (n instanceof BigNumber) {
-	          n = parseFloat(n.valueOf());
-	        }
-	        else if (isBoolean(n) || x === null) {
-	          return round(x, +n);
-	        }
-	        else {
-	          throw new TypeError('Number of decimals in function round must be an integer');
-	        }
-	      }
-	      if (n < 0 || n > 15) {
-	        throw new Error ('Number of decimals in function round must be in te range of 0-15');
-	      }
-
-	      if (isNumber(x)) {
-	        return roundNumber(x, n);
-	      }
-
-	      if (isComplex(x)) {
-	        return new Complex (
-	            roundNumber(x.re, n),
-	            roundNumber(x.im, n)
-	        );
-	      }
-
-	      if (x instanceof BigNumber) {
-	        return x.toDecimalPlaces(n);
-	      }
-
-	      if (isCollection(x) || isCollection(n)) {
-	        return collection.deepMap2(x, n, round);
-	      }
-
-	      if (isBoolean(x) || x === null) {
-	        return round(+x, n);
-	      }
-
-	      throw new math.error.UnsupportedTypeError('round', math['typeof'](x), math['typeof'](n));
-	    }
-	  };
-
-	  /**
-	   * round a number to the given number of decimals, or to zero if decimals is
-	   * not provided
-	   * @param {Number} value
-	   * @param {Number} decimals       number of decimals, between 0 and 15 (0 by default)
-	   * @return {Number} roundedValue
-	   */
-	  function roundNumber (value, decimals) {
-	    return parseFloat(toFixed(value, decimals));
-	  }
-	};
-
-
-/***/ },
-/* 70 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175),
-
-	      BigNumber = math.type.BigNumber,
-	      Complex = __webpack_require__(7),
-	      collection = math.collection,
-
-	      number = util.number,
-	      isNumber = util.number.isNumber,
-	      isBoolean = util['boolean'].isBoolean,
-	      isComplex = Complex.isComplex,
-	      isCollection = collection.isCollection;
-
-	  /**
-	   * Compute the sign of a value. The sign of a value x is:
-	   *
-	   * -  1 when x > 1
-	   * - -1 when x < 0
-	   * -  0 when x == 0
-	   *
-	   * For matrices, the function is evaluated element wise.
-	   *
-	   * Syntax:
-	   *
-	   *    math.sign(x)
-	   *
-	   * Examples:
-	   *
-	   *    math.sign(3.5);               // returns 1
-	   *    math.sign(-4.2);              // returns -1
-	   *    math.sign(0);                 // returns 0
-	   *
-	   *    math.sign([3, 5, -2, 0, 2]);  // returns [1, 1, -1, 0, 1]
-	   *
-	   * See also:
-	   *
-	   *    abs
-	   *
-	   * @param  {Number | BigNumber | Boolean | Complex | Array | Matrix | null} x
-	   *            The number for which to determine the sign
-	   * @return {Number | BigNumber | Complex | Array | Matrix}e
-	   *            The sign of `x`
-	   */
-	  math.sign = function sign(x) {
-	    if (arguments.length != 1) {
-	      throw new math.error.ArgumentsError('sign', arguments.length, 1);
-	    }
-
-	    if (isNumber(x)) {
-	      return number.sign(x);
-	    }
-
-	    if (isComplex(x)) {
-	      var abs = Math.sqrt(x.re * x.re + x.im * x.im);
-	      return new Complex(x.re / abs, x.im / abs);
-	    }
-
-	    if (x instanceof BigNumber) {
-	      return new BigNumber(x.cmp(0));
-	    }
-
-	    if (isCollection(x)) {
-	      // deep map collection, skip zeros since sign(0) = 0
-	      return collection.deepMap(x, sign, true);
-	    }
-
-	    if (isBoolean(x) || x === null) {
-	      return number.sign(x);
-	    }
-
-	    throw new math.error.UnsupportedTypeError('sign', math['typeof'](x));
-	  };
-	};
-
-
-/***/ },
-/* 71 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175),
-
-	      BigNumber = math.type.BigNumber,
-	      Complex = __webpack_require__(7),
-	      collection = math.collection,
-
-	      isNumber = util.number.isNumber,
-	      isBoolean = util['boolean'].isBoolean,
-	      isComplex = Complex.isComplex,
-	      isCollection = collection.isCollection;
-
-	  /**
-	   * Calculate the square root of a value.
-	   *
-	   * For matrices, the function is evaluated element wise.
-	   *
-	   * Syntax:
-	   *
-	   *    math.sqrt(x)
-	   *
-	   * Examples:
-	   *
-	   *    math.sqrt(25);                // returns 5
-	   *    math.square(5);               // returns 25
-	   *    math.sqrt(-4);                // returns Complex -2i
-	   *
-	   * See also:
-	   *
-	   *    square, multiply
-	   *
-	   * @param {Number | BigNumber | Boolean | Complex | Array | Matrix | null} x
-	   *            Value for which to calculate the square root.
-	   * @return {Number | BigNumber | Complex | Array | Matrix}
-	   *            Returns the square root of `x`
-	   */
-	  math.sqrt = function sqrt (x) {
-	    if (arguments.length != 1) {
-	      throw new math.error.ArgumentsError('sqrt', arguments.length, 1);
-	    }
-
-	    if (isNumber(x)) {
-	      if (x >= 0) {
-	        return Math.sqrt(x);
-	      }
-	      else {
-	        return sqrt(new Complex(x, 0));
-	      }
-	    }
-
-	    if (isComplex(x)) {
-	      var r = Math.sqrt(x.re * x.re + x.im * x.im);
-
-	      var re, im;
-
-	      if (x.re >= 0) {
-	        re = 0.5 * Math.sqrt(2.0 * (r + x.re));
-	      }
-	      else {
-	        re = Math.abs(x.im) / Math.sqrt(2 * (r - x.re));
-	      }
-
-	      if (x.re <= 0) {
-	        im = 0.5 * Math.sqrt(2.0 * (r - x.re));
-	      }
-	      else {
-	        im = Math.abs(x.im) / Math.sqrt(2 * (r + x.re));
-	      }
-
-	      if (x.im >= 0) {
-	        return new Complex(re, im);
-	      }
-	      else {
-	        return new Complex(re, -im);
-	      }
-	    }
-
-	    if (x instanceof BigNumber) {
-	      if (x.isNegative()) {
-	        // negative value -> downgrade to number to do complex value computation
-	        return sqrt(x.toNumber());
-	      }
-	      else {
-	        return x.sqrt();
-	      }
-	    }
-
-	    if (isCollection(x)) {
-	      // deep map collection, skip zeros since sqrt(0) = 0
-	      return collection.deepMap(x, sqrt, true);
-	    }
-
-	    if (isBoolean(x) || x === null) {
-	      return sqrt(+x);
-	    }
-
-	    throw new math.error.UnsupportedTypeError('sqrt', math['typeof'](x));
-	  };
-	};
-
-
-/***/ },
-/* 72 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175),
-
-	      BigNumber = math.type.BigNumber,
-	      Complex = __webpack_require__(7),
-	      collection = math.collection,
-
-	      isNumber = util.number.isNumber,
-	      isBoolean = util['boolean'].isBoolean,
-	      isComplex = Complex.isComplex,
-	      isCollection = collection.isCollection;
-
-	  /**
-	   * Compute the square of a value, `x * x`.
-	   * For matrices, the function is evaluated element wise.
-	   *
-	   * Syntax:
-	   *
-	   *    math.square(x)
-	   *
-	   * Examples:
-	   *
-	   *    math.square(2);           // returns Number 4
-	   *    math.square(3);           // returns Number 9
-	   *    math.pow(3, 2);           // returns Number 9
-	   *    math.multiply(3, 3);      // returns Number 9
-	   *
-	   *    math.square([1, 2, 3, 4]);  // returns Array [1, 4, 9, 16]
-	   *
-	   * See also:
-	   *
-	   *    multiply, cube, sqrt, pow
-	   *
-	   * @param  {Number | BigNumber | Boolean | Complex | Array | Matrix | null} x
-	   *            Number for which to calculate the square
-	   * @return {Number | BigNumber | Complex | Array | Matrix}
-	   *            Squared value
-	   */
-	  math.square = function square(x) {
-	    if (arguments.length != 1) {
-	      throw new math.error.ArgumentsError('square', arguments.length, 1);
-	    }
-
-	    if (isNumber(x)) {
-	      return x * x;
-	    }
-
-	    if (isComplex(x)) {
-	      return math.multiply(x, x);
-	    }
-
-	    if (x instanceof BigNumber) {
-	      return x.times(x);
-	    }
-
-	    if (isCollection(x)) {
-	      // deep map collection, skip zeros since square(0) = 0
-	      return collection.deepMap(x, square, true);
-	    }
-
-	    if (isBoolean(x) || x === null) {
-	      return x * x;
-	    }
-
-	    throw new math.error.UnsupportedTypeError('square', math['typeof'](x));
-	  };
-	};
-
-
-/***/ },
-/* 73 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math) {
-	  var util = __webpack_require__(175),
-
-	      BigNumber = math.type.BigNumber,
-	      Complex = __webpack_require__(7),
-	      Matrix = math.type.Matrix,
-	      Unit = __webpack_require__(11),
-	      collection = math.collection,
-
-	      isBoolean = util['boolean'].isBoolean,
-	      isNumber = util.number.isNumber,
-	      isComplex = Complex.isComplex,
-	      isUnit = Unit.isUnit,
-	      isCollection = collection.isCollection;
+	    return new M(data, datatype);
+	  }
+	}
+
+	exports.name = 'matrix';
+	exports.factory = factory;
+
+
+/***/ },
+/* 24 */
+/***/ function(module, exports, __webpack_require__) {
+
+	'use strict';
+
+	var size = __webpack_require__(18).size;
+
+	function factory (type, config, load, typed) {
+	  var matrix   = load(__webpack_require__(23));
+	  var subtract = load(__webpack_require__(25));
+	  var multiply = load(__webpack_require__(40));
+
+	  /**
+	   * Calculate the cross product for two vectors in three dimensional space.
+	   * The cross product of `A = [a1, a2, a3]` and `B =[b1, b2, b3]` is defined
+	   * as:
+	   *
+	   *    cross(A, B) = [
+	   *      a2 * b3 - a3 * b2,
+	   *      a3 * b1 - a1 * b3,
+	   *      a1 * b2 - a2 * b1
+	   *    ]
+	   *
+	   * Syntax:
+	   *
+	   *    math.cross(x, y)
+	   *
+	   * Examples:
+	   *
+	   *    math.cross([1, 1, 0],  [0, 1, 1]);  // Returns [1, -1, 1]
+	   *    math.cross([3, -3, 1], [4, 9, 2]);  // Returns [-15, -2, 39]
+	   *    math.cross([2, 3, 4],  [5, 6, 7]);  // Returns [-3, 6, -3]
+	   *
+	   * See also:
+	   *
+	   *    dot, multiply
+	   *
+	   * @param  {Array | Matrix} x   First vector
+	   * @param  {Array | Matrix} y   Second vector
+	   * @return {Array | Matrix}     Returns the cross product of `x` and `y`
+	   */
+	  var cross = typed('cross', {
+	    'Matrix, Matrix': function (x, y) {
+	      return matrix(_cross(x.toArray(), y.toArray()));
+	    },
+
+	    'Matrix, Array': function (x, y) {
+	      return matrix(_cross(x.toArray(), y));
+	    },
+
+	    'Array, Matrix': function (x, y) {
+	      return matrix(_cross(x, y.toArray()));
+	    },
+
+	    'Array, Array': _cross
+	  });
+
+	  cross.toTex = '\\left(${args[0]}\\right)\\times\\left(${args[1]}\\right)';
+
+	  return cross;
+
+	  /**
+	   * Calculate the cross product for two arrays
+	   * @param {Array} x  First vector
+	   * @param {Array} y  Second vector
+	   * @returns {Array} Returns the cross product of x and y
+	   * @private
+	   */
+	  function _cross(x, y) {
+	    var xSize= size(x);
+	    var ySize = size(y);
+
+	    if (xSize.length != 1 || ySize.length != 1 || xSize[0] != 3 || ySize[0] != 3) {
+	      throw new RangeError('Vectors with length 3 expected ' +
+	      '(Size A = [' + xSize.join(', ') + '], B = [' + ySize.join(', ') + '])');
+	    }
+
+	    return [
+	      subtract(multiply(x[1], y[2]), multiply(x[2], y[1])),
+	      subtract(multiply(x[2], y[0]), multiply(x[0], y[2])),
+	      subtract(multiply(x[0], y[1]), multiply(x[1], y[0]))
+	    ];
+	  }
+	}
+
+	exports.name = 'cross';
+	exports.factory = factory;
+
+
+/***/ },
+/* 25 */
+/***/ function(module, exports, __webpack_require__) {
+
+	'use strict';
+
+	var DimensionError = __webpack_require__(22);
+
+	function factory (type, config, load, typed) {
+	  var latex = __webpack_require__(26);
+
+	  var matrix = load(__webpack_require__(23));
+	  var addScalar = load(__webpack_require__(27));
+	  var unaryMinus = load(__webpack_require__(28));
+
+	  var algorithm01 = load(__webpack_require__(30));
+	  var algorithm03 = load(__webpack_require__(31));
+	  var algorithm05 = load(__webpack_require__(32));
+	  var algorithm10 = load(__webpack_require__(34));
+	  var algorithm13 = load(__webpack_require__(35));
+	  var algorithm14 = load(__webpack_require__(39));
 
 	  /**
 	   * Subtract two values, `x - y`.
@@ -13589,7 +4150,7 @@
 	   *
 	   * Examples:
 	   *
-	   *    math.subtract(5.3, 2);        // returns Number 3.3
+	   *    math.subtract(5.3, 2);        // returns number 3.3
 	   *
 	   *    var a = math.complex(2, 3);
 	   *    var b = math.complex(4, 1);
@@ -13605,139 +4166,340 @@
 	   *
 	   *    add
 	   *
-	   * @param  {Number | BigNumber | Boolean | Complex | Unit | Array | Matrix | null} x
+	   * @param  {number | BigNumber | Fraction | Complex | Unit | Array | Matrix} x
 	   *            Initial value
-	   * @param  {Number | BigNumber | Boolean | Complex | Unit | Array | Matrix | null} y
+	   * @param  {number | BigNumber | Fraction | Complex | Unit | Array | Matrix} y
 	   *            Value to subtract from `x`
-	   * @return {Number | BigNumber | Complex | Unit | Array | Matrix}
+	   * @return {number | BigNumber | Fraction | Complex | Unit | Array | Matrix}
 	   *            Subtraction of `x` and `y`
 	   */
-	  math.subtract = function subtract(x, y) {
-	    if (arguments.length != 2) {
-	      throw new math.error.ArgumentsError('subtract', arguments.length, 2);
-	    }
-
-	    if (isNumber(x)) {
-	      if (isNumber(y)) {
-	        // number - number
-	        return x - y;
-	      }
-	      else if (isComplex(y)) {
-	        // number - complex
-	        return new Complex (
-	            x - y.re,
-	            - y.im
-	        );
-	      }
-	    }
-	    else if (isComplex(x)) {
-	      if (isNumber(y)) {
-	        // complex - number
-	        return new Complex (
-	            x.re - y,
-	            x.im
-	        )
-	      }
-	      else if (isComplex(y)) {
-	        // complex - complex
-	        return new Complex (
-	            x.re - y.re,
-	            x.im - y.im
-	        )
-	      }
-	    }
-
-	    if (x instanceof BigNumber) {
-	      // try to convert to big number
-	      if (isNumber(y)) {
-	        y = BigNumber.convert(y);
-	      }
-	      else if (isBoolean(y) || y === null) {
-	        y = new BigNumber(y ? 1 : 0);
-	      }
-
-	      if (y instanceof BigNumber) {
-	        return x.minus(y);
-	      }
-
-	      // downgrade to Number
-	      return subtract(x.toNumber(), y);
-	    }
-	    if (y instanceof BigNumber) {
-	      // try to convert to big number
-	      if (isNumber(x)) {
-	        x = BigNumber.convert(x);
-	      }
-	      else if (isBoolean(x) || x === null) {
-	        x = new BigNumber(x ? 1 : 0);
-	      }
-
-	      if (x instanceof BigNumber) {
-	        return x.minus(y)
-	      }
-
-	      // downgrade to Number
-	      return subtract(x, y.toNumber());
-	    }
-
-	    if (isUnit(x)) {
-	      if (isUnit(y)) {
-	        if (x.value == null) {
-	          throw new Error('Parameter x contains a unit with undefined value');
-	        }
-
-	        if (y.value == null) {
-	          throw new Error('Parameter y contains a unit with undefined value');
-	        }
-
-	        if (!x.equalBase(y)) {
-	          throw new Error('Units do not match');
-	        }
-
-	        var res = x.clone();
-	        res.value -= y.value;
-	        res.fixPrefix = false;
-
-	        return res;
-	      }
-	    }
-
-	    if (isCollection(x) || isCollection(y)) {
-	      return collection.deepMap2(x, y, subtract);
-	    }
-
-	    if (isBoolean(x) || x === null) {
-	      return subtract(+x, y);
-	    }
-	    if (isBoolean(y) || y === null) {
-	      return subtract(x, +y);
-	    }
-
-	    throw new math.error.UnsupportedTypeError('subtract', math['typeof'](x), math['typeof'](y));
-	  };
-	};
-
-
-/***/ },
-/* 74 */
+	  var subtract = typed('subtract', {
+
+	    'number, number': function (x, y) {
+	      return x - y;
+	    },
+
+	    'Complex, Complex': function (x, y) {
+	      return new type.Complex (
+	          x.re - y.re,
+	          x.im - y.im
+	      );
+	    },
+
+	    'BigNumber, BigNumber': function (x, y) {
+	      return x.minus(y);
+	    },
+
+	    'Fraction, Fraction': function (x, y) {
+	      return x.sub(y);
+	    },
+
+	    'Unit, Unit': function (x, y) {
+	      if (x.value == null) {
+	        throw new Error('Parameter x contains a unit with undefined value');
+	      }
+
+	      if (y.value == null) {
+	        throw new Error('Parameter y contains a unit with undefined value');
+	      }
+
+	      if (!x.equalBase(y)) {
+	        throw new Error('Units do not match');
+	      }
+
+	      var res = x.clone();
+	      res.value -= y.value;
+	      res.fixPrefix = false;
+
+	      return res;
+	    },
+	    
+	    'Matrix, Matrix': function (x, y) {
+	      // matrix sizes
+	      var xsize = x.size();
+	      var ysize = y.size();
+
+	      // check dimensions
+	      if (xsize.length !== ysize.length)
+	        throw new DimensionError(xsize.length, ysize.length);
+
+	      // result
+	      var c;
+
+	      // process matrix storage
+	      switch (x.storage()) {
+	        case 'sparse':
+	          switch (y.storage()) {
+	            case 'sparse':
+	              // sparse - sparse
+	              c = algorithm05(x, y, subtract);
+	              break;
+	            default:
+	              // sparse - dense
+	              c = algorithm03(y, x, subtract, true);
+	              break;
+	          }
+	          break;
+	        default:
+	          switch (y.storage()) {
+	            case 'sparse':
+	              // dense - sparse
+	              c = algorithm01(x, y, subtract, false);
+	              break;
+	            default:
+	              // dense - dense
+	              c = algorithm13(x, y, subtract);
+	              break;
+	          }
+	          break;
+	      }
+	      return c;
+	    },
+	    
+	    'Array, Array': function (x, y) {
+	      // use matrix implementation
+	      return subtract(matrix(x), matrix(y)).valueOf();
+	    },
+
+	    'Array, Matrix': function (x, y) {
+	      // use matrix implementation
+	      return subtract(matrix(x), y);
+	    },
+
+	    'Matrix, Array': function (x, y) {
+	      // use matrix implementation
+	      return subtract(x, matrix(y));
+	    },
+	    
+	    'Matrix, any': function (x, y) {
+	      // result
+	      var c;
+	      // check storage format
+	      switch (x.storage()) {
+	        case 'sparse':
+	          // algorithm 7 is faster than 9 since it calls f() for nonzero items only!
+	          c = algorithm10(x, unaryMinus(y), addScalar);
+	          break;
+	        default:
+	          c = algorithm14(x, y, subtract);
+	          break;
+	      }
+	      return c;
+	    },
+
+	    'any, Matrix': function (x, y) {
+	      // result
+	      var c;
+	      // check storage format
+	      switch (y.storage()) {
+	        case 'sparse':
+	          c = algorithm10(y, x, subtract, true);
+	          break;
+	        default:
+	          c = algorithm14(y, x, subtract, true);
+	          break;
+	      }
+	      return c;
+	    },
+
+	    'Array, any': function (x, y) {
+	      // use matrix implementation
+	      return algorithm14(matrix(x), y, subtract, false).valueOf();
+	    },
+
+	    'any, Array': function (x, y) {
+	      // use matrix implementation
+	      return algorithm14(matrix(y), x, subtract, true).valueOf();
+	    }
+	  });
+
+	  subtract.toTex = '\\left(${args[0]}' + latex.operators['subtract'] + '${args[1]}\\right)';
+
+	  return subtract;
+	}
+
+	exports.name = 'subtract';
+	exports.factory = factory;
+
+
+/***/ },
+/* 26 */
+/***/ function(module, exports) {
+
+	'use strict';
+
+	exports.symbols = {
+	  // GREEK LETTERS
+	  Alpha: 'A',     alpha: '\\alpha',
+	  Beta: 'B',      beta: '\\beta',
+	  Gamma: '\\Gamma',    gamma: '\\gamma',
+	  Delta: '\\Delta',    delta: '\\delta',
+	  Epsilon: 'E',   epsilon: '\\epsilon',  varepsilon: '\\varepsilon',
+	  Zeta: 'Z',      zeta: '\\zeta',
+	  Eta: 'H',       eta: '\\eta',
+	  Theta: '\\Theta',    theta: '\\theta',    vartheta: '\\vartheta',
+	  Iota: 'I',      iota: '\\iota',
+	  Kappa: 'K',     kappa: '\\kappa',    varkappa: '\\varkappa',
+	  Lambda: '\\Lambda',   lambda: '\\lambda',
+	  Mu: 'M',        mu: '\\mu',
+	  Nu: 'N',        nu: '\\nu',
+	  Xi: '\\Xi',       xi: '\\xi',
+	  Omicron: 'O',   omicron: 'o',
+	  Pi: '\\Pi',       pi: '\\pi',       varpi: '\\varpi',
+	  Rho: 'P',       rho: '\\rho',      varrho: '\\varrho',
+	  Sigma: '\\Sigma',    sigma: '\\sigma',    varsigma: '\\varsigma',
+	  Tau: 'T',       tau: '\\tau',
+	  Upsilon: '\\Upsilon',  upsilon: '\\upsilon',
+	  Phi: '\\Phi',      phi: '\\phi',      varphi: '\\varphi',
+	  Chi: 'X',       chi: '\\chi',
+	  Psi: '\\Psi',      psi: '\\psi',
+	  Omega: '\\Omega',    omega: '\\omega',
+	  //logic
+	  'true': '\\mathrm{True}',
+	  'false': '\\mathrm{False}',
+	  //other
+	  i: 'i', //TODO use \i ??
+	  inf: '\\infty',
+	  Inf: '\\infty',
+	  infinity: '\\infty',
+	  Infinity: '\\infty',
+	  oo: '\\infty',
+	  lim: '\\lim',
+	  'undefined': '\\mathbf{?}'
+	};
+
+	exports.operators = {
+	  'transpose': '^\\top',
+	  'factorial': '!',
+	  'pow': '^',
+	  'dotPow': '.^\\wedge', //TODO find ideal solution
+	  'unaryPlus': '+',
+	  'unaryMinus': '-',
+	  'bitNot': '~', //TODO find ideal solution
+	  'not': '\\neg',
+	  'multiply': '\\cdot',
+	  'divide': '\\frac', //TODO how to handle that properly?
+	  'dotMultiply': '.\\cdot', //TODO find ideal solution
+	  'dotDivide': '.:', //TODO find ideal solution
+	  'mod': '\\mod',
+	  'add': '+',
+	  'subtract': '-',
+	  'to': '\\rightarrow',
+	  'leftShift': '<<',
+	  'rightArithShift': '>>',
+	  'rightLogShift': '>>>',
+	  'equal': '=',
+	  'unequal': '\\neq',
+	  'smaller': '<',
+	  'larger': '>',
+	  'smallerEq': '\\leq',
+	  'largerEq': '\\geq',
+	  'bitAnd': '\\&',
+	  'bitXor': '\\underline{|}',
+	  'bitOr': '|',
+	  'and': '\\wedge',
+	  'xor': '\\veebar',
+	  'or': '\\vee'
+	};
+
+	exports.defaultTemplate = '\\mathrm{${name}}\\left(${args}\\right)';
+
+	var units = {
+	  deg: '^\\circ'
+	};
+
+	//@param {string} name
+	//@param {boolean} isUnit
+	exports.toSymbol = function (name, isUnit) {
+	  isUnit = typeof isUnit === 'undefined' ? false : isUnit;
+	  if (isUnit) {
+	    if (units.hasOwnProperty(name)) {
+	      return units[name];
+	    }
+	    return '\\mathrm{' + name + '}';
+	  }
+
+	  if (exports.symbols.hasOwnProperty(name)) {
+	    return exports.symbols[name];
+	  }
+	  else if (name.indexOf('_') !== -1) {
+	    //symbol with index (eg. alpha_1)
+	    var index = name.indexOf('_');
+	    return exports.toSymbol(name.substring(0, index)) + '_{'
+	      + exports.toSymbol(name.substring(index + 1)) + '}';
+	  }
+	  return name;
+	};
+
+
+/***/ },
+/* 27 */
+/***/ function(module, exports) {
+
+	'use strict';
+
+	function factory(type, config, load, typed) {
+
+	  /**
+	   * Add two scalar values, `x + y`.
+	   * This function is meant for internal use: it is used by the public function
+	   * `add`
+	   *
+	   * This function does not support collections (Array or Matrix), and does
+	   * not validate the number of of inputs.
+	   *
+	   * @param  {number | BigNumber | Fraction | Complex | Unit} x   First value to add
+	   * @param  {number | BigNumber | Fraction | Complex} y          Second value to add
+	   * @return {number | BigNumber | Fraction | Complex | Unit}                      Sum of `x` and `y`
+	   * @private
+	   */
+	  return typed('add', {
+
+	    'number, number': function (x, y) {
+	      return x + y;
+	    },
+
+	    'Complex, Complex': function (x, y) {
+	      return new type.Complex(
+	        x.re + y.re,
+	        x.im + y.im
+	      );
+	    },
+
+	    'BigNumber, BigNumber': function (x, y) {
+	      return x.plus(y);
+	    },
+
+	    'Fraction, Fraction': function (x, y) {
+	      return x.add(y);
+	    },
+
+	    'Unit, Unit': function (x, y) {
+	      if (x.value == null) throw new Error('Parameter x contains a unit with undefined value');
+	      if (y.value == null) throw new Error('Parameter y contains a unit with undefined value');
+	      if (!x.equalBase(y)) throw new Error('Units do not match');
+
+	      var res = x.clone();
+	      res.value += y.value;
+	      res.fixPrefix = false;
+	      return res;
+	    }
+	  });
+	}
+
+	exports.factory = factory;
+
+
+/***/ },
+/* 28 */
 /***/ function(module, exports, __webpack_require__) {
 
 	'use strict';
 
-	module.exports = function (math, config) {
-	  var util = __webpack_require__(175),
-
-	      BigNumber = math.type.BigNumber,
-	      Complex = __webpack_require__(7),
-	      Unit = __webpack_require__(11),
-	      collection = math.collection,
-
-	      isNumber = util.number.isNumber,
-	      isBoolean = util['boolean'].isBoolean,
-	      isString = util.string.isString,
-	      isComplex = Complex.isComplex,
-	      isUnit = Unit.isUnit,
-	      isCollection = collection.isCollection;
+	var deepMap = __webpack_require__(29);
+
+	function factory (type, config, load, typed) {
+	  var latex = __webpack_require__(26);
 
 	  /**
 	   * Inverse the sign of a value, apply a unary minus operation.
@@ -13759,1931 +4521,2140 @@
 	   *
 	   *    add, subtract, unaryPlus
 	   *
-	   * @param  {Number | BigNumber | Boolean | String | Complex | Unit | Array | Matrix | null} x Number to be inverted.
-	   * @return {Number | BigNumber | Complex | Unit | Array | Matrix} Returns the value with inverted sign.
+	   * @param  {number | BigNumber | Fraction | Complex | Unit | Array | Matrix} x Number to be inverted.
+	   * @return {number | BigNumber | Fraction | Complex | Unit | Array | Matrix} Returns the value with inverted sign.
 	   */
-	  math.unaryMinus = function unaryMinus(x) {
-	    if (arguments.length != 1) {
-	      throw new math.error.ArgumentsError('unaryMinus', arguments.length, 1);
-	    }
-
-	    if (isNumber(x)) {
+	  var unaryMinus = typed('unaryMinus', {
+	    'number': function (x) {
 	      return -x;
-	    }
-
-	    if (isComplex(x)) {
-	      return new Complex(
-	          -x.re,
-	          -x.im
-	      );
-	    }
-
-	    if (x instanceof BigNumber) {
+	    },
+
+	    'Complex': function (x) {
+	      return new type.Complex(-x.re, -x.im);
+	    },
+
+	    'BigNumber': function (x) {
 	      return x.neg();
-	    }
-
-	    if (isUnit(x)) {
+	    },
+
+	    'Fraction': function (x) {
+	      var tmp = x.clone();
+	      tmp.s = -tmp.s;
+	      return tmp;
+	    },
+
+	    'Unit': function (x) {
 	      var res = x.clone();
 	      res.value = -x.value;
 	      return res;
-	    }
+	    },
 
-	    if (isCollection(x)) {
+	    'Array | Matrix': function (x) {
 	      // deep map collection, skip zeros since unaryMinus(0) = 0
-	      return collection.deepMap(x, unaryMinus, true);
-	    }
-
-	    if (isBoolean(x) || isString(x) || x === null) {
-	      // convert to a number or bignumber
-	      return (config.number == 'bignumber') ? new BigNumber(-x): -x;
-	    }
-
-	    throw new math.error.UnsupportedTypeError('unaryMinus', math['typeof'](x));
-	  };
-
-	  // TODO: function unary is renamed to unaryMinus since version 0.23.0. Cleanup some day
-	  math.unary = function unary() {
-	    throw new Error('Function unary is deprecated. Use unaryMinus instead.');
-	  };
-	};
-
-
-/***/ },
-/* 75 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math, config) {
-	  var util = __webpack_require__(175),
-
-	      BigNumber = math.type.BigNumber,
-	      Complex = __webpack_require__(7),
-	      Unit = __webpack_require__(11),
-	      collection = math.collection,
-
-	      isNumber = util.number.isNumber,
-	      isBoolean = util['boolean'].isBoolean,
-	      isString = util.string.isString,
-	      isComplex = Complex.isComplex,
-	      isUnit = Unit.isUnit,
-	      isCollection = collection.isCollection;
-
-	  /**
-	   * Unary plus operation.
-	   * Boolean values and strings will be converted to a number, numeric values will be returned as is.
-	   *
-	   * For matrices, the function is evaluated element wise.
-	   *
-	   * Syntax:
-	   *
-	   *    math.unaryPlus(x)
-	   *
-	   * Examples:
-	   *
-	   *    math.unaryPlus(3.5);      // returns 3.5
-	   *    math.unaryPlus(1);     // returns 1
-	   *
-	   * See also:
-	   *
-	   *    unaryMinus, add, subtract
-	   *
-	   * @param  {Number | BigNumber | Boolean | String | Complex | Unit | Array | Matrix | null} x
-	   *            Input value
-	   * @return {Number | BigNumber | Complex | Unit | Array | Matrix}
-	   *            Returns the input value when numeric, converts to a number when input is non-numeric.
-	   */
-	  math.unaryPlus = function unaryPlus(x) {
-	    if (arguments.length != 1) {
-	      throw new math.error.ArgumentsError('unaryPlus', arguments.length, 1);
-	    }
-
-	    if (isNumber(x)) {
-	      return x;
-	    }
-
-	    if (isComplex(x)) {
-	      return x.clone();
-	    }
-
-	    if (x instanceof BigNumber) {
-	      return x;
-	    }
-
-	    if (isUnit(x)) {
-	      return x.clone();
-	    }
-
-	    if (isCollection(x)) {
-	      // deep map collection, skip zeros since unaryPlus(0) = 0
-	      return collection.deepMap(x, unaryPlus, true);
-	    }
-
-	    if (isBoolean(x) || isString(x) || x === null) {
-	      // convert to a number or bignumber
-	      return (config.number == 'bignumber') ? new BigNumber(+x): +x;
-	    }
-
-	    throw new math.error.UnsupportedTypeError('unaryPlus', math['typeof'](x));
-	  };
-	};
-
-
-/***/ },
-/* 76 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	module.exports = function (math, config) {
-	  var util = __webpack_require__(175),
-
-	      Matrix = math.type.Matrix,
-	      BigNumber = math.type.BigNumber,
-
-	      isNumber = util.number.isNumber,
-	      isBoolean = util['boolean'].isBoolean,
-	      isInteger = util.number.isInteger;
-
-	  /**
-	   * Calculate the extended greatest common divisor for two values.
-	   * See http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm.
-	   *
-	   * Syntax:
-	   *
-	   *    math.xgcd(a, b)
-	   *
-	   * Examples:
-	   *
-	   *    math.xgcd(8, 12);             // returns [4, -1, 1]
-	   *    math.gcd(8, 12);              // returns 4
-	   *    math.xgcd(36163, 21199);      // returns [1247, -7, 12]
-	   *
-	   * See also:
-	   *
-	   *    gcd, lcm
-	   *
-	   * @param {Number | BigNumber | Boolean} a  An integer number
-	   * @param {Number | BigNumber | Boolean} b  An integer number
-	   * @return {Array}              Returns an array containing 3 integers `[div, m, n]`
-	   *                              where `div = gcd(a, b)` and `a*m + b*n = div`
-	   */
-	  math.xgcd = function xgcd(a, b) {
-	    if (arguments.length == 2) {
-	      // two arguments
-	      if (isNumber(a) && isNumber(b)) {
-	        if (!isInteger(a) || !isInteger(b)) {
-	          throw new Error('Parameters in function xgcd must be integer numbers');
-	        }
-
-	        return _xgcd(a, b);
-	      }
-
-	      if (a instanceof BigNumber) {
-	        // try to convert to big number
-	        if (isNumber(b)) {
-	          b = BigNumber.convert(b);
-	        }
-	        else if (isBoolean(b) || b === null) {
-	          b = new BigNumber(b ? 1 : 0);
-	        }
-
-	        if (b instanceof BigNumber) {
-	          return _bigXgcd(a, b);
-	        }
-
-	        // downgrade to Number
-	        return xgcd(a.toNumber(), b);
-	      }
-	      if (b instanceof BigNumber) {
-	        // try to convert to big number
-	        if (i

Follow ups