← Back to team overview

ubuntu-touch-coreapps-reviewers team mailing list archive

[Merge] lp:~ubuntu-calculator-dev/ubuntu-calculator-app/ubuntu-calculator-app-performance-optimization into lp:ubuntu-calculator-app

 

Bartosz Kosiorek has proposed merging lp:~ubuntu-calculator-dev/ubuntu-calculator-app/ubuntu-calculator-app-performance-optimization into lp:ubuntu-calculator-app.

Commit message:
Improve performance of first calculation about 20% by compile math.js
with Google Closure (LP: #1520594)

Requested reviews:
  Ubuntu Calculator Developers (ubuntu-calculator-dev)
Related bugs:
  Bug #1520594 in Ubuntu Calculator App: "Calculating the first division takes too much time"
  https://bugs.launchpad.net/ubuntu-calculator-app/+bug/1520594

For more details, see:
https://code.launchpad.net/~ubuntu-calculator-dev/ubuntu-calculator-app/ubuntu-calculator-app-performance-optimization/+merge/278868

Improve performance of first calculation about 20% by compile math.js
with Google Closure (LP: #1520594)
-- 
The attached diff has been truncated due to its size.
Your team Ubuntu Calculator Developers is requested to review the proposed merge of lp:~ubuntu-calculator-dev/ubuntu-calculator-app/ubuntu-calculator-app-performance-optimization into lp:ubuntu-calculator-app.
=== modified file 'app/engine/math.js'
--- app/engine/math.js	2015-11-15 00:18:19 +0000
+++ app/engine/math.js	2015-11-27 20:56:55 +0000
@@ -1,50856 +1,804 @@
-// All edits done for the Ubuntu Calculator App are preceded by a comment that
-// starts with 'UCA:' and describes the edit
-
-// UCA: add a var to which we will refer to when we include the code in qml
-// in app/ubuntu-calculator-app.qml with import "engine/math.js" as MathJs and
-// then property var mathJs: MathJs.mathJs;
+/*
+
+ Copyright (C) 2013-2015 Jos de Jong <wjosdejong@xxxxxxxxx>
+
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ use this file except in compliance with the License. You may obtain a copy
+ of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ License for the specific language governing permissions and limitations under
+ the License.
+ Fraction.js v3.0.0 09/09/2015
+ http://www.xarg.org/2014/03/precise-calculations-in-javascript/
+
+ Copyright (c) 2015, Robert Eisele (robert@xxxxxxxx)
+ Dual licensed under the MIT or GPL Version 2 licenses.
+*/
 var mathJs;
-
-/**
- * math.js
- * https://github.com/josdejong/mathjs
- *
- * Math.js is an extensive math library for JavaScript and Node.js,
- * It features real and complex numbers, units, matrices, a large set of
- * mathematical functions, and a flexible expression parser.
- *
- * @version 2.4.2
- * @date    2015-11-14
- *
- * @license
- * Copyright (C) 2013-2015 Jos de Jong <wjosdejong@xxxxxxxxx>
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy
- * of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-(function webpackUniversalModuleDefinition(root, factory) {
-    // UCA: we delete all exports, we don't need them, and we keep only our var
-    mathJs = factory();})(this, function() {
-return /******/ (function(modules) { // webpackBootstrap
-/******/ 	// The module cache
-/******/ 	var installedModules = {};
-
-/******/ 	// The require function
-/******/ 	function __webpack_require__(moduleId) {
-
-/******/ 		// Check if module is in cache
-/******/ 		if(installedModules[moduleId])
-/******/ 			return installedModules[moduleId].exports;
-
-/******/ 		// Create a new module (and put it into the cache)
-/******/ 		var module = installedModules[moduleId] = {
-/******/ 			exports: {},
-/******/ 			id: moduleId,
-/******/ 			loaded: false
-/******/ 		};
-
-/******/ 		// Execute the module function
-/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
-
-/******/ 		// Flag the module as loaded
-/******/ 		module.loaded = true;
-
-/******/ 		// Return the exports of the module
-/******/ 		return module.exports;
-/******/ 	}
-
-
-/******/ 	// expose the modules object (__webpack_modules__)
-/******/ 	__webpack_require__.m = modules;
-
-/******/ 	// expose the module cache
-/******/ 	__webpack_require__.c = installedModules;
-
-/******/ 	// __webpack_public_path__
-/******/ 	__webpack_require__.p = "";
-
-/******/ 	// Load entry module and return exports
-/******/ 	return __webpack_require__(0);
-/******/ })
-/************************************************************************/
-/******/ ([
-/* 0 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var core = __webpack_require__(1);
-
-	/**
-	 * math.js factory function. Creates a new instance of math.js
-	 *
-	 * @param {Object} [config] Available configuration 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.
-	 */
-	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__(3).isFactory;
-	var deepExtend = __webpack_require__(3).deepExtend;
-	var typedFactory = __webpack_require__(4);
-	var emitter = __webpack_require__(8);
-
-	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.');
-	  }
-
-	  // 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',
-
-	    // type of default number output. Choose 'number' (default) or 'bignumber'
-	    number: 'number',
-
-	    // number of significant digits in BigNumbers
-	    precision: 64,
-
-	    // 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);
-	  }
-
-	  /**
-	   * 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 {*}
-	   */
-	  function load (factory) {
-	    if (!isFactory(factory)) {
-	      throw new Error('Factory object with properties `type`, `name`, and `factory` expected');
-	    }
-
-	    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 {
-	        instance = factory.factory(math.type, _config, load, math.typed);
-	      }
-
-	      // 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;
-	};
-
-
-/***/ },
-/* 3 */
-/***/ function(module, exports) {
-
-	'use strict';
-
-	/**
-	 * Clone an object
-	 *
-	 *     clone(x)
-	 *
-	 * Can clone any primitive type, array, and object.
-	 * If x has a function clone, this function will be invoked to clone the object.
-	 *
-	 * @param {*} x
-	 * @return {*} clone
-	 */
-	exports.clone = function clone(x) {
-	  var type = typeof x;
-
-	  // immutable primitive types
-	  if (type === 'number' || type === 'string' || type === 'boolean' ||
-	      x === null || x === undefined) {
-	    return x;
-	  }
-
-	  // use clone function of the object when available
-	  if (typeof x.clone === 'function') {
-	    return x.clone();
-	  }
-
-	  // array
-	  if (Array.isArray(x)) {
-	    return x.map(function (value) {
-	      return clone(value);
-	    });
-	  }
-
-	  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
-	  var m = {};
-	  for (var key in x) {
-	    if (x.hasOwnProperty(key)) {
-	      m[key] = clone(x[key]);
-	    }
-	  }
-	  return m;
-	};
-
-	/**
-	 * Extend object a with the properties of object b
-	 * @param {Object} a
-	 * @param {Object} b
-	 * @return {Object} a
-	 */
-	exports.extend = function(a, b) {
-	  for (var prop in b) {
-	    if (b.hasOwnProperty(prop)) {
-	      a[prop] = b[prop];
-	    }
-	  }
-	  return a;
-	};
-
-	/**
-	 * Deep extend an object a with the properties of object b
-	 * @param {Object} a
-	 * @param {Object} b
-	 * @returns {Object}
-	 */
-	exports.deepExtend = function deepExtend (a, b) {
-	  // TODO: add support for Arrays to deepExtend
-	  if (Array.isArray(b)) {
-	    throw new TypeError('Arrays are not supported by deepExtend');
-	  }
-
-	  for (var prop in b) {
-	    if (b.hasOwnProperty(prop)) {
-	      if (b[prop] && b[prop].constructor === Object) {
-	        if (a[prop] === undefined) {
-	          a[prop] = {};
-	        }
-	        if (a[prop].constructor === Object) {
-	          deepExtend(a[prop], b[prop]);
-	        }
-	        else {
-	          a[prop] = b[prop];
-	        }
-	      } else if (Array.isArray(b[prop])) {
-	        throw new TypeError('Arrays are not supported by deepExtend');
-	      } else {
-	        a[prop] = b[prop];
-	      }
-	    }
-	  }
-	  return a;
-	};
-
-	/**
-	 * Deep test equality of all fields in two pairs of arrays or objects.
-	 * @param {Array | Object} a
-	 * @param {Array | Object} b
-	 * @returns {boolean}
-	 */
-	exports.deepEqual = function deepEqual (a, b) {
-	  var prop, i, len;
-	  if (Array.isArray(a)) {
-	    if (!Array.isArray(b)) {
-	      return false;
-	    }
-
-	    if (a.length != b.length) {
-	      return false;
-	    }
-
-	    for (i = 0, len = a.length; i < len; i++) {
-	      if (!exports.deepEqual(a[i], b[i])) {
-	        return false;
-	      }
-	    }
-	    return true;
-	  }
-	  else if (a instanceof Object) {
-	    if (Array.isArray(b) || !(b instanceof Object)) {
-	      return false;
-	    }
-
-	    for (prop in a) {
-	      //noinspection JSUnfilteredForInLoop
-	      if (!exports.deepEqual(a[prop], b[prop])) {
-	        return false;
-	      }
-	    }
-	    for (prop in b) {
-	      //noinspection JSUnfilteredForInLoop
-	      if (!exports.deepEqual(a[prop], b[prop])) {
-	        return false;
-	      }
-	    }
-	    return true;
-	  }
-	  else {
-	    return (typeof a === typeof b) && (a == b);
-	  }
-	};
-
-	/**
-	 * Test whether the current JavaScript engine supports Object.defineProperty
-	 * @returns {boolean} returns true if supported
-	 */
-	exports.canDefineProperty = function () {
-	  // test needed for broken IE8 implementation
-	  try {
-	    if (Object.defineProperty) {
-	      Object.defineProperty({}, 'x', { get: function () {} });
-	      return true;
-	    }
-	  } catch (e) {}
-
-	  return false;
-	};
-
-	/**
-	 * Attach a lazy loading property to a constant.
-	 * The given function `fn` is called once when the property is first requested.
-	 * On older browsers (<IE8), the function will fall back to direct evaluation
-	 * 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
-	 *                          without arguments.
-	 */
-	exports.lazy = function (object, prop, fn) {
-	  if (exports.canDefineProperty()) {
-	    var _uninitialized = true;
-	    var _value;
-	    Object.defineProperty(object, prop, {
-	      get: function () {
-	        if (_uninitialized) {
-	          _value = fn();
-	          _uninitialized = false;
-	        }
-	        return _value;
-	      },
-
-	      set: function (value) {
-	        _value = value;
-	        _uninitialized = false;
-	      },
-
-	      configurable: true,
-	      enumerable: true
-	    });
-	  }
-	  else {
-	    // fall back to immediate evaluation
-	    object[prop] = fn();
-	  }
-	};
-
-	/**
-	 * 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';
-	};
-
-
-/***/ },
-/* 4 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var typedFunction = __webpack_require__(5);
-	var digits = __webpack_require__(6).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;
-	};
-
-
-/***/ },
-/* 5 */
-/***/ 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();
-	}));
-
-
-/***/ },
-/* 6 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var NumberFormatter = __webpack_require__(7);
-
-	/**
-	 * Test whether value is a number
-	 * @param {*} value
-	 * @return {boolean} isNumber
-	 */
-	exports.isNumber = function(value) {
-	  return typeof value === 'number';
-	};
-
-	/**
-	 * Check if a number is integer
-	 * @param {number | boolean} value
-	 * @return {boolean} isInteger
-	 */
-	exports.isInteger = function(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
-	 * @returns {*}
-	 */
-	exports.sign = function(x) {
-	  if (x > 0) {
-	    return 1;
-	  }
-	  else if (x < 0) {
-	    return -1;
-	  }
-	  else {
-	    return 0;
-	  }
-	};
-
-	/**
-	 * Convert a number 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 {number} 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 === Infinity) {
-	    return 'Infinity';
-	  }
-	  else if (value === -Infinity) {
-	    return '-Infinity';
-	  }
-	  else if (isNaN(value)) {
-	    return 'NaN';
-	  }
-
-	  // default values for options
-	  var notation = 'auto';
-	  var precision = undefined;
-
-	  if (options) {
-	    // determine notation from options
-	    if (options.notation) {
-	      notation = options.notation;
-	    }
-
-	    // determine precision from options
-	    if (exports.isNumber(options)) {
-	      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':
-	      return exports
-	          .toPrecision(value, precision, options && options.exponential)
-
-	          // remove trailing zeros after the decimal point
-	          .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 {number} 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) {
-	  return new NumberFormatter(value).toExponential(precision);
-	};
-
-	/**
-	 * Format a number with fixed notation.
-	 * @param {number} value
-	 * @param {number} [precision=0]        Optional number of decimals after the
-	 *                                      decimal point. Zero by default.
-	 */
-	exports.toFixed = function(value, precision) {
-	  return new NumberFormatter(value).toFixed(precision);
-	};
-
-	/**
-	 * Format a number with a certain precision
-	 * @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)
-	 * @return {string}
-	 */
-	exports.toPrecision = function(value, precision, options) {
-	  return new NumberFormatter(value).toPrecision(precision, options);
-	};
-
-	/**
-	 * Count the number of significant digits of a number.
-	 *
-	 * For example:
-	 *   2.34 returns 3
-	 *   0.0034 returns 2
-	 *   120.5e+30 returns 4
-	 *
-	 * @param {number} value
-	 * @return {number} digits   Number of significant digits
-	 */
-	exports.digits = function(value) {
-	  return value
-	      .toExponential()
-	      .replace(/e.*$/, '')          // remove exponential notation
-	      .replace( /^0\.?0*|\./, '')   // remove decimal point and leading zeros
-	      .length
-	};
-
-	/**
-	 * Minimum number added to one that makes the result different than one
-	 */
-	exports.DBL_EPSILON = Number.EPSILON || 2.2204460492503130808472633361816E-16;
-
-	/**
-	 * 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
-	 *                            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
-	*/
-	exports.nearlyEqual = function(x, y, epsilon) {
-	  // if epsilon is null or undefined, test whether x and y are exactly equal
-	  if (epsilon == null) return x == y;
-
-	  // use "==" operator, handles infinities
-	  if (x == y) return true;
-
-	  // NaN
-	  if (isNaN(x) || isNaN(y)) return false;
-
-	  // at this point x and y should be finite
-	  if(isFinite(x) && isFinite(y)) {
-	    // check numbers are very close, needed when comparing numbers near zero
-	    var diff = Math.abs(x - y);
-	    if (diff < exports.DBL_EPSILON) {
-	      return true;
-	    }
-	    else {
-	      // use relative error
-	      return diff <= Math.max(Math.abs(x), Math.abs(y)) * epsilon;
-	    }
-	  }
-
-	  // Infinite and Number or negative Infinite and positive Infinite cases
-	  return false;
-	};
-
-
-/***/ },
-/* 7 */
-/***/ function(module, exports) {
-
-	'use strict';
-
-	/**
-	 * 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, c.length - 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;
-
-
-/***/ },
-/* 8 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var Emitter = __webpack_require__(9);
-
-	/**
-	 * 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;
-	};
-
-
-/***/ },
-/* 9 */
-/***/ 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;
-
-
-/***/ },
-/* 10 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var lazy = __webpack_require__(3).lazy;
-	var isFactory = __webpack_require__(3).isFactory;
-	var traverse = __webpack_require__(3).traverse;
-	var extend = __webpack_require__(3).extend;
-	var ArgumentsError = __webpack_require__(11);
-
-	function factory (type, config, load, typed, math) {
-	  /**
-	   * 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 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);
-	    }
-	    // TODO: allow a typed-function with name too
-	    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');
-	      }
-	    }
-	  }
-
-	  /**
-	   * Add a property to the math namespace and create a chain proxy for it.
-	   * @param {string} name
-	   * @param {*} value
-	   * @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)) {
-	      if (options.override) {
-	        // give the typed function the right name
-	        value = typed(name, value.signatures);
-	      }
-	      else {
-	        // merge the existing and typed function
-	        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)) {
-	          if (options.override) {
-	            // replace the existing typed function (nothing to do)
-	          }
-	          else {
-	            // merge the existing and new typed function
-	            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) {
-
-	'use strict';
-
-	/**
-	 * 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;
-
-
-/***/ },
-/* 12 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var object = __webpack_require__(3);
-
-	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);
-	    }
-	  };
-	}
-
-	exports.name = 'config';
-	exports.math = true; // request the math namespace as fifth argument
-	exports.factory = factory;
-
-
-/***/ },
-/* 13 */
-/***/ function(module, exports, __webpack_require__) {
-
-	module.exports = [
-	  __webpack_require__(14),        // data types (Matrix, Complex, Unit, ...)
-	  __webpack_require__(76),   // constants
-	  __webpack_require__(80),  // expression parsing
-	  __webpack_require__(312),    // functions
-	  __webpack_require__(495),        // serialization utility (math.json.reviver)
-	  __webpack_require__(497)        // errors
-	];
-
-
-/***/ },
-/* 14 */
-/***/ function(module, exports, __webpack_require__) {
-
-	module.exports = [
-	  __webpack_require__(15),
-	  __webpack_require__(20),
-	  __webpack_require__(21),
-	  __webpack_require__(26),
-	  __webpack_require__(31),
-	  __webpack_require__(37),
-	  __webpack_require__(69),
-	  __webpack_require__(70),
-	  __webpack_require__(72),
-	  __webpack_require__(73)
-	];
-
-
-/***/ },
-/* 15 */
-/***/ function(module, exports, __webpack_require__) {
-
-	module.exports = [
-	  // type
-	  __webpack_require__(16),
-
-	  // construction function
-	  __webpack_require__(18)
-	];
-
-
-/***/ },
-/* 16 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var Decimal = __webpack_require__(17);
-	var digits = __webpack_require__(6).digits;
-
-	function factory (type, config, load, typed, math) {
-	  var BigNumber = Decimal.constructor(config);
-
-	  /**
-	   * Attach type information
-	   */
-	  BigNumber.prototype.type = 'BigNumber';
-	  BigNumber.prototype.isBigNumber = true;
-
-	  /**
-	   * 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);
-	  };
-
-	  // listen for changed in the configuration, automatically apply changed precision
-	  math.on('config', function (curr, prev) {
-	    if (curr.precision !== prev.precision) {
-	      BigNumber.config({ precision: curr.precision });
-	    }
-	  });
-
-	  return BigNumber;
-	}
-
-	exports.name = 'BigNumber';
-	exports.path = 'type';
-	exports.factory = factory;
-	exports.math = true; // request access to the math namespace
-
-/***/ },
-/* 17 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var __WEBPACK_AMD_DEFINE_RESULT__;/*! decimal.js v4.0.3 https://github.com/MikeMcl/decimal.js/LICENCE */
-	;(function (global) {
-	    'use strict';
-
-
-	    /*
-	     *  decimal.js v4.0.3
-	     *  An arbitrary-precision Decimal type for JavaScript.
-	     *  https://github.com/MikeMcl/decimal.js
-	     *  Copyright (c) 2014 Michael Mclaughlin <M8ch88l@xxxxxxxxx>
-	     *  MIT Expat Licence
-	     */
-
-
-	    var convertBase, decimal, noConflict,
-	        crypto = global['crypto'],
-	        external = true,
-	        id = 0,
-	        mathfloor = Math.floor,
-	        mathpow = Math.pow,
-	        outOfRange,
-	        toString = Object.prototype.toString,
-	        BASE = 1e7,
-	        LOGBASE = 7,
-	        NUMERALS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_',
-	        P = {},
-
-	        /*
-	         The maximum exponent magnitude.
-	         The limit on the value of toExpNeg, toExpPos, minE and maxE.
-	         */
-	        EXP_LIMIT = 9e15,                      // 0 to 9e15
-
-	        /*
-	         The limit on the value of precision, and on the argument to toDecimalPlaces,
-	         toExponential, toFixed, toFormat, toPrecision and toSignificantDigits.
-	         */
-	        MAX_DIGITS = 1E9,                      // 0 to 1e+9
-
-	        /*
-	         To decide whether or not to calculate x.pow(integer y) using the 'exponentiation by
-	         squaring' algorithm or by exp(y*ln(x)), the number of significant digits of x is multiplied
-	         by y. If this number is less than INT_POW_LIMIT then the former algorithm is used.
-	         */
-	        INT_POW_LIMIT = 3000,                  // 0 to 5000
-
-	        // The natural logarithm of 10 (1025 digits).
-	        LN10 = '2.3025850929940456840179914546843642076011014886287729760333279009675726096773524802359972050895982983419677840422862486334095254650828067566662873690987816894829072083255546808437998948262331985283935053089653777326288461633662222876982198867465436674744042432743651550489343149393914796194044002221051017141748003688084012647080685567743216228355220114804663715659121373450747856947683463616792101806445070648000277502684916746550586856935673420670581136429224554405758925724208241314695689016758940256776311356919292033376587141660230105703089634572075440370847469940168269282808481184289314848524948644871927809676271275775397027668605952496716674183485704422507197965004714951050492214776567636938662976979522110718264549734772662425709429322582798502585509785265383207606726317164309505995087807523710333101197857547331541421808427543863591778117054309827482385045648019095610299291824318237525357709750539565187697510374970888692180205189339507238539205144634197265287286965110862571492198849978748873771345686209167058';
-
-
-	    // Decimal prototype methods
-
-
-	    /*
-	     * Return a new Decimal whose value is the absolute value of this Decimal.
-	     *
-	     */
-	    P['absoluteValue'] = P['abs'] = function () {
-	        var x = new this['constructor'](this);
-
-	        if ( x['s'] < 0 ) {
-	            x['s'] = 1;
-	        }
-
-	        return rnd(x);
-	    };
-
-
-	    /*
-	     * Return a new Decimal whose value is the value of this Decimal rounded to a whole number in
-	     * the direction of positive Infinity.
-	     *
-	     */
-	    P['ceil'] = function () {
-
-	        return rnd( new this['constructor'](this), this['e'] + 1, 2 );
-	    };
-
-
-	    /*
-	     * Return
-	     *   1    if the value of this Decimal is greater than the value of Decimal(y, b),
-	     *  -1    if the value of this Decimal is less than the value of Decimal(y, b),
-	     *   0    if they have the same value,
-	     *  null  if the value of either Decimal is NaN.
-	     *
-	     */
-	    P['comparedTo'] = P['cmp'] = function ( y, b ) {
-	        var a,
-	            x = this,
-	            xc = x['c'],
-	            yc = ( id = -id, y = new x['constructor']( y, b ), y['c'] ),
-	            i = x['s'],
-	            j = y['s'],
-	            k = x['e'],
-	            l = y['e'];
-
-	        // Either NaN?
-	        if ( !i || !j ) {
-	            return null;
-	        }
-
-	        a = xc && !xc[0];
-	        b = yc && !yc[0];
-
-	        // Either zero?
-	        if ( a || b ) {
-	            return a ? b ? 0 : -j : i;
-	        }
-
-	        // Signs differ?
-	        if ( i != j ) {
-	            return i;
-	        }
-
-	        a = i < 0;
-
-	        // Either Infinity?
-	        if ( !xc || !yc ) {
-	            return k == l ? 0 : !xc ^ a ? 1 : -1;
-	        }
-
-	        // Compare exponents.
-	        if ( k != l ) {
-	            return k > l ^ a ? 1 : -1;
-	        }
-
-	        // Compare digit by digit.
-	        for ( i = -1,
-	              j = ( k = xc.length ) < ( l = yc.length ) ? k : l;
-	              ++i < j; ) {
-
-	            if ( xc[i] != yc[i] ) {
-	                return xc[i] > yc[i] ^ a ? 1 : -1;
-	            }
-	        }
-
-	        // Compare lengths.
-	        return k == l ? 0 : k > l ^ a ? 1 : -1;
-	    };
-
-
-	    /*
-	     * Return the number of decimal places of the value of this Decimal.
-	     *
-	     */
-	     P['decimalPlaces'] = P['dp'] = function () {
-	        var c, v,
-	            n = null;
-
-	        if ( c = this['c'] ) {
-	            n = ( ( v = c.length - 1 ) - mathfloor( this['e'] / LOGBASE ) ) * LOGBASE;
-
-	            if ( v = c[v] ) {
-
-	                // Subtract the number of trailing zeros of the last number.
-	                for ( ; v % 10 == 0; v /= 10, n-- );
-	            }
-
-	            if ( n < 0 ) {
-	                n = 0;
-	            }
-	        }
-
-	        return n;
-	    };
-
-
-	    /*
-	     *  n / 0 = I
-	     *  n / N = N
-	     *  n / I = 0
-	     *  0 / n = 0
-	     *  0 / 0 = N
-	     *  0 / N = N
-	     *  0 / I = 0
-	     *  N / n = N
-	     *  N / 0 = N
-	     *  N / N = N
-	     *  N / I = N
-	     *  I / n = I
-	     *  I / 0 = I
-	     *  I / N = N
-	     *  I / I = N
-	     *
-	     * Return a new Decimal whose value is the value of this Decimal divided by Decimal(y, b),
-	     * rounded to precision significant digits using rounding mode rounding.
-	     *
-	     */
-	    P['dividedBy'] = P['div'] = function ( y, b ) {
-	        id = 2;
-
-	        return div( this, new this['constructor']( y, b ) );
-	    };
-
-
-	    /*
-	     * Return a new Decimal whose value is the integer part of dividing the value of this Decimal by
-	     * the value of Decimal(y, b), rounded to precision significant digits using rounding mode
-	     * rounding.
-	     *
-	     */
-	    P['dividedToIntegerBy'] = P['divToInt'] = function ( y, b ) {
-	        var x = this,
-	            Decimal = x['constructor'];
-	        id = 18;
-
-	        return rnd(
-	          div( x, new Decimal( y, b ), 0, 1, 1 ), Decimal['precision'], Decimal['rounding']
-	        );
-	    };
-
-
-	    /*
-	     * Return true if the value of this Decimal is equal to the value of Decimal(n, b), otherwise
-	     * return false.
-	     *
-	     */
-	    P['equals'] = P['eq'] = function ( n, b ) {
-	        id = 3;
-
-	        return this['cmp']( n, b ) === 0;
-	    };
-
-
-	    /*
-	     * Return a new Decimal whose value is the exponential of the value of this Decimal, i.e. the
-	     * base e raised to the power the value of this Decimal, rounded to precision significant digits
-	     * using rounding mode rounding.
-	     *
-	     */
-	    P['exponential'] = P['exp'] = function () {
-
-	        return exp(this);
-	    };
-
-
-	    /*
-	     * Return a new Decimal whose value is the value of this Decimal rounded to a whole number in
-	     * the direction of negative Infinity.
-	     *
-	     */
-	    P['floor'] = function () {
-
-	        return rnd( new this['constructor'](this), this['e'] + 1, 3 );
-	    };
-
-
-	    /*
-	     * Return true if the value of this Decimal is greater than the value of Decimal(n, b), otherwise
-	     * return false.
-	     *
-	     */
-	    P['greaterThan'] = P['gt'] = function ( n, b ) {
-	        id = 4;
-
-	        return this['cmp']( n, b ) > 0;
-	    };
-
-
-	    /*
-	     * Return true if the value of this Decimal is greater than or equal to the value of
-	     * Decimal(n, b), otherwise return false.
-	     *
-	     */
-	    P['greaterThanOrEqualTo'] = P['gte'] = function ( n, b ) {
-	        id = 5;
-	        b = this['cmp']( n, b );
-
-	        return b == 1 || b === 0;
-	    };
-
-
-	    /*
-	     * Return true if the value of this Decimal is a finite number, otherwise return false.
-	     *
-	     */
-	    P['isFinite'] = function () {
-
-	        return !!this['c'];
-	    };
-
-
-	    /*
-	     * Return true if the value of this Decimal is an integer, otherwise return false.
-	     *
-	     */
-	    P['isInteger'] = P['isInt'] = function () {
-
-	        return !!this['c'] && mathfloor( this['e'] / LOGBASE ) > this['c'].length - 2;
-	    };
-
-
-	    /*
-	     * Return true if the value of this Decimal is NaN, otherwise return false.
-	     *
-	     */
-	    P['isNaN'] = function () {
-
-	        return !this['s'];
-	    };
-
-
-	    /*
-	     * Return true if the value of this Decimal is negative, otherwise return false.
-	     *
-	     */
-	    P['isNegative'] = P['isNeg'] = function () {
-
-	        return this['s'] < 0;
-	    };
-
-
-	    /*
-	     * Return true if the value of this Decimal is 0 or -0, otherwise return false.
-	     *
-	     */
-	    P['isZero'] = function () {
-
-	        return !!this['c'] && this['c'][0] == 0;
-	    };
-
-
-	    /*
-	     * Return true if the value of this Decimal is less than Decimal(n, b), otherwise return false.
-	     *
-	     */
-	    P['lessThan'] = P['lt'] = function ( n, b ) {
-	        id = 6;
-
-	        return this['cmp']( n, b ) < 0;
-	    };
-
-
-	    /*
-	     * Return true if the value of this Decimal is less than or equal to Decimal(n, b), otherwise
-	     * return false.
-	     *
-	     */
-	    P['lessThanOrEqualTo'] = P['lte'] = function ( n, b ) {
-	        id = 7;
-	        b = this['cmp']( n, b );
-
-	        return b == -1 || b === 0;
-	    };
-
-
-	    /*
-	     * Return the logarithm of the value of this Decimal to the specified base, rounded
-	     * to precision significant digits using rounding mode rounding.
-	     *
-	     * If no base is specified, return log[10](arg).
-	     *
-	     * log[base](arg) = ln(arg) / ln(base)
-	     *
-	     * The result will always be correctly rounded if the base of the log is 2 or 10, and
-	     * 'almost always' if not:
-	     *
-	     * Depending on the rounding mode, the result may be incorrectly rounded if the first fifteen
-	     * rounding digits are [49]99999999999999 or [50]00000000000000. In that case, the maximum error
-	     * between the result and the correctly rounded result will be one ulp (unit in the last place).
-	     *
-	     * log[-b](a)       = NaN
-	     * log[0](a)        = NaN
-	     * log[1](a)        = NaN
-	     * log[NaN](a)      = NaN
-	     * log[Infinity](a) = NaN
-	     * log[b](0)        = -Infinity
-	     * log[b](-0)       = -Infinity
-	     * log[b](-a)       = NaN
-	     * log[b](1)        = 0
-	     * log[b](Infinity) = Infinity
-	     * log[b](NaN)      = NaN
-	     *
-	     * [base] {number|string|Decimal} The base of the logarithm.
-	     * [b] {number} The base of base.
-	     *
-	     */
-	    P['logarithm'] = P['log'] = function ( base, b ) {
-	        var base10, c, denom, i, inf, num, sd, sd10, r,
-	            arg = this,
-	            Decimal = arg['constructor'],
-	            pr = Decimal['precision'],
-	            rm = Decimal['rounding'],
-	            guard = 5;
-
-	        // Default base is 10.
-	        if ( base == null ) {
-	            base = new Decimal(10);
-	            base10 = true;
-	        } else {
-	            id = 15;
-	            base = new Decimal( base, b );
-	            c = base['c'];
-
-	            // If base < 0 or +-Infinity/NaN or 0 or 1.
-	            if ( base['s'] < 0 || !c || !c[0] || !base['e'] && c[0] == 1 && c.length == 1 ) {
-
-	                return new Decimal(NaN);
-	            }
-	            base10 = base['eq'](10);
-	        }
-	        c = arg['c'];
-
-	        // If arg < 0 or +-Infinity/NaN or 0 or 1.
-	        if ( arg['s'] < 0 || !c || !c[0] || !arg['e'] && c[0] == 1 && c.length == 1 ) {
-
-	            return new Decimal( c && !c[0] ? -1 / 0 : arg['s'] != 1 ? NaN : c ? 0 : 1 / 0 );
-	        }
-
-	        /*
-	          The result will have an infinite decimal expansion if base is 10 and arg is not an
-	          integer power of 10...
-	         */
-	        inf = base10 && ( i = c[0], c.length > 1 || i != 1 && i != 10 &&
-	          i != 1e2 && i != 1e3 && i != 1e4 && i != 1e5 && i != 1e6 );
-	            /*
-	            // or if base last digit's evenness is not the same as arg last digit's evenness...
-	            // (FAILS when e.g. base.c[0] = 10 and c[0] = 1)
-	            || ( base['c'][ base['c'].length - 1 ] & 1 ) != ( c[ c.length - 1 ] & 1 )
-	              // or if base is 2 and there is more than one 1 in arg in base 2.
-	              // (SLOWS the method down significantly)
-	              || base['eq'](2) && arg.toString(2).replace( /[^1]+/g, '' ) != '1';
-	             */
-
-	        external = false;
-	        sd = pr + guard;
-	        sd10 = sd + 10;
-
-	        num = ln( arg, sd );
-
-	        if (base10) {
-
-	            if ( sd10 > LN10.length ) {
-	                ifExceptionsThrow( Decimal, 1, sd10, 'log' );
-	            }
-	            denom = new Decimal( LN10.slice( 0, sd10 ) );
-	        } else {
-	            denom = ln( base, sd );
-	        }
-
-	        // The result will have 5 rounding digits.
-	        r = div( num, denom, sd, 1 );
-
-	        /*
-	         If at a rounding boundary, i.e. the result's rounding digits are [49]9999 or [50]0000,
-	         calculate 10 further digits.
-
-	         If the result is known to have an infinite decimal expansion, repeat this until it is
-	         clear that the result is above or below the boundary. Otherwise, if after calculating
-	         the 10 further digits, the last 14 are nines, round up and assume the result is exact.
-	         Also assume the result is exact if the last 14 are zero.
-
-	         Example of a result that will be incorrectly rounded:
-	         log[1048576](4503599627370502) = 2.60000000000000009610279511444746...
-	         The above result correctly rounded using ROUND_CEIL to 1 decimal place should be 2.7,
-	         but it will be given as 2.6 as there are 15 zeros immediately after the requested
-	         decimal place, so the exact result would be assumed to be 2.6, which rounded using
-	         ROUND_CEIL to 1 decimal place is still 2.6.
-	         */
-	        if ( checkRoundingDigits( r['c'], i = pr, rm ) ) {
-
-	            do {
-	                sd += 10;
-	                num = ln( arg, sd );
-
-	                if (base10) {
-	                    sd10 = sd + 10;
-
-	                    if ( sd10 > LN10.length ) {
-	                        ifExceptionsThrow( Decimal, 1, sd10, 'log' );
-	                    }
-	                    denom = new Decimal( LN10.slice( 0, sd10 ) );
-	                } else {
-	                    denom = ln( base, sd );
-	                }
-
-	                r = div( num, denom, sd, 1 );
-
-	                if ( !inf ) {
-
-	                    // Check for 14 nines from the 2nd rounding digit, as the first may be 4.
-	                    if ( +coefficientToString( r['c'] ).slice( i + 1, i + 15 ) + 1 == 1e14 ) {
-	                        r = rnd( r, pr + 1, 0 );
-	                    }
-
-	                    break;
-	                }
-	            } while ( checkRoundingDigits( r['c'], i += 10, rm ) );
-	        }
-	        external = true;
-
-	        return rnd( r, pr, rm );
-	    };
-
-
-	    /*
-	     *  n - 0 = n
-	     *  n - N = N
-	     *  n - I = -I
-	     *  0 - n = -n
-	     *  0 - 0 = 0
-	     *  0 - N = N
-	     *  0 - I = -I
-	     *  N - n = N
-	     *  N - 0 = N
-	     *  N - N = N
-	     *  N - I = N
-	     *  I - n = I
-	     *  I - 0 = I
-	     *  I - N = N
-	     *  I - I = N
-	     *
-	     * Return a new Decimal whose value is the value of this Decimal minus Decimal(y, b), rounded
-	     * to precision significant digits using rounding mode rounding.
-	     *
-	     */
-	    P['minus'] = function ( y, b ) {
-	        var t, i, j, xLTy,
-	            x = this,
-	            Decimal = x['constructor'],
-	            a = x['s'];
-
-	        id = 8;
-	        y = new Decimal( y, b );
-	        b = y['s'];
-
-	        // Either NaN?
-	        if ( !a || !b ) {
-
-	            return new Decimal(NaN);
-	        }
-
-	        // Signs differ?
-	        if ( a != b ) {
-	            y['s'] = -b;
-
-	            return x['plus'](y);
-	        }
-
-	        var xc = x['c'],
-	            yc = y['c'],
-	            e = mathfloor( y['e'] / LOGBASE ),
-	            k = mathfloor( x['e'] / LOGBASE ),
-	            pr = Decimal['precision'],
-	            rm = Decimal['rounding'];
-
-	        if ( !k || !e ) {
-
-	            // Either Infinity?
-	            if ( !xc || !yc ) {
-
-	                return xc ? ( y['s'] = -b, y ) : new Decimal( yc ? x : NaN );
-	            }
-
-	            // Either zero?
-	            if ( !xc[0] || !yc[0] ) {
-
-	                // Return y if y is non-zero, x if x is non-zero, or zero if both are zero.
-	                x = yc[0] ? ( y['s'] = -b, y ) : new Decimal( xc[0] ? x :
-
-	                  // IEEE 754 (2008) 6.3: n - n = -0 when rounding to -Infinity
-	                  rm == 3 ? -0 : 0 );
-
-	                return external ? rnd( x, pr, rm ) : x;
-	            }
-	        }
-
-	        xc = xc.slice();
-	        i = xc.length;
-
-	        // Determine which is the bigger number. Prepend zeros to equalise exponents.
-	        if ( a = k - e ) {
-
-	            if ( xLTy = a < 0 ) {
-	                a = -a;
-	                t = xc;
-	                i = yc.length;
-	            } else {
-	                e = k;
-	                t = yc;
-	            }
-
-	            if ( ( k = Math.ceil( pr / LOGBASE ) ) > i ) {
-	                i = k;
-	            }
-
-	            /*
-	             Numbers with massively different exponents would result in a massive number of
-	             zeros needing to be prepended, but this can be avoided while still ensuring correct
-	             rounding by limiting the number of zeros to max( pr, i ) + 2, where pr is precision and
-	             i is the length of the coefficient of whichever is greater, x or y.
-	             */
-	            if ( a > ( i += 2 ) ) {
-	                a = i;
-	                t.length = 1;
-	            }
-
-	            t.reverse();
-	            for ( b = a; b--; t.push(0) );
-	            t.reverse();
-	        } else {
-	            // Exponents equal. Check digits.
-
-	            if ( xLTy = i < ( j = yc.length ) ) {
-	                j = i;
-	            }
-
-	            for ( a = b = 0; b < j; b++ ) {
-
-	                if ( xc[b] != yc[b] ) {
-	                    xLTy = xc[b] < yc[b];
-
-	                    break;
-	                }
-	            }
-	        }
-
-	        // x < y? Point xc to the array of the bigger number.
-	        if ( xLTy ) {
-	            t = xc, xc = yc, yc = t;
-	            y['s'] = -y['s'];
-	        }
-
-	        /*
-	         Append zeros to xc if shorter. No need to add zeros to yc if shorter as subtraction only
-	         needs to start at yc length.
-	         */
-	        if ( ( b = -( ( j = xc.length ) - yc.length ) ) > 0 ) {
-
-	            for ( ; b--; xc[j++] = 0 );
-	        }
-
-	        // Subtract yc from xc.
-	        for ( k = BASE - 1, b = yc.length; b > a; ) {
-
-	            if ( xc[--b] < yc[b] ) {
-
-	                for ( i = b; i && !xc[--i]; xc[i] = k );
-	                --xc[i];
-	                xc[b] += BASE;
-	            }
-	            xc[b] -= yc[b];
-	        }
-
-	        // Remove trailing zeros.
-	        for ( ; xc[--j] == 0; xc.pop() );
-
-	        // Remove leading zeros and adjust exponent accordingly.
-	        for ( ; xc[0] == 0; xc.shift(), --e );
-
-	        if ( !xc[0] ) {
-
-	            // Zero.
-	            xc = [ e = 0 ];
-
-	            // Following IEEE 754 (2008) 6.3, n - n = -0 when rounding towards -Infinity.
-	            y['s'] = rm == 3 ? -1 : 1;
-	        }
-
-	        y['c'] = xc;
-
-	        // Get the number of digits of xc[0].
-	        for ( a = 1, b = xc[0]; b >= 10; b /= 10, a++ );
-	        y['e'] = a + e * LOGBASE - 1;
-
-	        return external ? rnd( y, pr, rm ) : y;
-	    };
-
-
-	    /*
-	     *   n % 0 =  N
-	     *   n % N =  N
-	     *   n % I =  n
-	     *   0 % n =  0
-	     *  -0 % n = -0
-	     *   0 % 0 =  N
-	     *   0 % N =  N
-	     *   0 % I =  0
-	     *   N % n =  N
-	     *   N % 0 =  N
-	     *   N % N =  N
-	     *   N % I =  N
-	     *   I % n =  N
-	     *   I % 0 =  N
-	     *   I % N =  N
-	     *   I % I =  N
-	     *
-	     * Return a new Decimal whose value is the value of this Decimal modulo Decimal(y, b), rounded
-	     * to precision significant digits using rounding mode rounding.
-	     *
-	     * The result depends on the modulo mode.
-	     *
-	     */
-	    P['modulo'] = P['mod'] = function ( y, b ) {
-	        var n, q,
-	            x = this,
-	            Decimal = x['constructor'],
-	            m = Decimal['modulo'];
-
-	        id = 9;
-	        y = new Decimal( y, b );
-	        b = y['s'];
-	        n = !x['c'] || !b || y['c'] && !y['c'][0];
-
-	        /*
-	         Return NaN if x is Infinity or NaN, or y is NaN or zero, else return x if y is Infinity
-	         or x is zero.
-	         */
-	        if ( n || !y['c'] || x['c'] && !x['c'][0] ) {
-
-	            return n
-	              ? new Decimal(NaN)
-	              : rnd( new Decimal(x), Decimal['precision'], Decimal['rounding'] );
-	        }
-
-	        external = false;
-
-	        if ( m == 9 ) {
-
-	            // Euclidian division: q = sign(y) * floor(x / abs(y))
-	            // r = x - qy    where  0 <= r < abs(y)
-	            y['s'] = 1;
-	            q = div( x, y, 0, 3, 1 );
-	            y['s'] = b;
-	            q['s'] *= b;
-	        } else {
-	            q = div( x, y, 0, m, 1 );
-	        }
-
-	        q = q['times'](y);
-	        external = true;
-
-	        return x['minus'](q);
-	    };
-
-
-	    /*
-	     * Return a new Decimal whose value is the natural logarithm of the value of this Decimal,
-	     * rounded to precision significant digits using rounding mode rounding.
-	     *
-	     */
-	    P['naturalLogarithm'] = P['ln'] = function () {
-
-	        return ln(this);
-	    };
-
-
-	    /*
-	     * Return a new Decimal whose value is the value of this Decimal negated, i.e. as if
-	     * multiplied by -1.
-	     *
-	     */
-	    P['negated'] = P['neg'] = function () {
-	        var x = new this['constructor'](this);
-	        x['s'] = -x['s'] || null;
-
-	        return rnd(x);
-	    };
-
-
-	    /*
-	     *  n + 0 = n
-	     *  n + N = N
-	     *  n + I = I
-	     *  0 + n = n
-	     *  0 + 0 = 0
-	     *  0 + N = N
-	     *  0 + I = I
-	     *  N + n = N
-	     *  N + 0 = N
-	     *  N + N = N
-	     *  N + I = N
-	     *  I + n = I
-	     *  I + 0 = I
-	     *  I + N = N
-	     *  I + I = I
-	     *
-	     * Return a new Decimal whose value is the value of this Decimal plus Decimal(y, b), rounded
-	     * to precision significant digits using rounding mode rounding.
-	     *
-	     */
-	    P['plus'] = function ( y, b ) {
-	        var t,
-	            x = this,
-	            Decimal = x['constructor'],
-	            a = x['s'];
-
-	        id = 10;
-	        y = new Decimal( y, b );
-	        b = y['s'];
-
-	        // Either NaN?
-	        if ( !a || !b ) {
-
-	            return new Decimal(NaN);
-	        }
-
-	        // Signs differ?
-	        if ( a != b ) {
-	            y['s'] = -b;
-
-	            return x['minus'](y);
-	        }
-
-	        var xc = x['c'],
-	            yc = y['c'],
-	            e = mathfloor( y['e'] / LOGBASE ),
-	            k = mathfloor( x['e'] / LOGBASE ),
-	            pr = Decimal['precision'],
-	            rm = Decimal['rounding'];
-
-	        if ( !k || !e ) {
-
-	            // Either Infinity?
-	            if ( !xc || !yc ) {
-
-	                // Return +-Infinity.
-	                return new Decimal( a / 0 );
-	            }
-
-	            // Either zero?
-	            if ( !xc[0] || !yc[0] ) {
-
-	                // Return y if y is non-zero, x if x is non-zero, or zero if both are zero.
-	                x = yc[0] ? y : new Decimal( xc[0] ? x : a * 0 );
-
-	                return external ? rnd( x, pr, rm ) : x;
-	            }
-	        }
-
-	        xc = xc.slice();
-
-	        // Prepend zeros to equalise exponents. Note: Faster to use reverse then do unshifts.
-	        if ( a = k - e ) {
-
-	            if ( a < 0 ) {
-	                a = -a;
-	                t = xc;
-	                b = yc.length;
-	            } else {
-	                e = k;
-	                t = yc;
-	                b = xc.length;
-	            }
-
-	            if ( ( k = Math.ceil( pr / LOGBASE ) ) > b ) {
-	                b = k;
-	            }
-
-	            // Limit number of zeros prepended to max( pr, b ) + 1.
-	            if ( a > ++b ) {
-	                a = b;
-	                t.length = 1;
-	            }
-
-	            for ( t.reverse(); a--; t.push(0) );
-	            t.reverse();
-	        }
-
-	        // Point xc to the longer array.
-	        if ( xc.length - yc.length < 0 ) {
-	            t = yc, yc = xc, xc = t;
-	        }
-
-	        // Only start adding at yc.length - 1 as the further digits of xc can be left as they are.
-	        for ( a = yc.length, b = 0, k = BASE; a; xc[a] %= k ) {
-	            b = ( xc[--a] = xc[a] + yc[a] + b ) / k | 0;
-	        }
-
-	        if (b) {
-	            xc.unshift(b);
-	            ++e;
-	        }
-
-	        // Remove trailing zeros.
-	        for ( a = xc.length; xc[--a] == 0; xc.pop() );
-
-	        // No need to check for zero, as +x + +y != 0 && -x + -y != 0
-
-	        y['c'] = xc;
-
-	        // Get the number of digits of xc[0].
-	        for ( a = 1, b = xc[0]; b >= 10; b /= 10, a++ );
-	        y['e'] = a + e * LOGBASE - 1;
-
-	        return external ? rnd( y, pr, rm ) : y;
-	    };
-
-
-	    /*
-	     * Return the number of significant digits of this Decimal.
-	     *
-	     * [z] {boolean|number} Whether to count integer-part trailing zeros: true, false, 1 or 0.
-	     *
-	     */
-	    P['precision'] = P['sd'] = function (z) {
-	        var n = null,
-	            x = this;
-
-	        if ( z != n && z !== !!z && z !== 1 && z !== 0 ) {
-
-	            // 'precision() argument not a boolean or binary digit: {z}'
-	            ifExceptionsThrow( x['constructor'], 'argument', z, 'precision', 1 );
-	        }
-
-	        if ( x['c'] ) {
-	            n = getCoeffLength( x['c'] );
-
-	            if ( z && x['e'] + 1 > n ) {
-	                n = x['e'] + 1;
-	            }
-	        }
-
-	        return n;
-	    };
-
-
-	    /*
-	     * Return a new Decimal whose value is the value of this Decimal rounded to a whole number using
-	     * rounding mode rounding.
-	     *
-	     */
-	    P['round'] = function () {
-	        var x = this,
-	            Decimal = x['constructor'];
-
-	        return rnd( new Decimal(x), x['e'] + 1, Decimal['rounding'] );
-	    };
-
-
-	    /*
-	     *  sqrt(-n) =  N
-	     *  sqrt( N) =  N
-	     *  sqrt(-I) =  N
-	     *  sqrt( I) =  I
-	     *  sqrt( 0) =  0
-	     *  sqrt(-0) = -0
-	     *
-	     * Return a new Decimal whose value is the square root of this Decimal, rounded to precision
-	     * significant digits using rounding mode rounding.
-	     *
-	     */
-	    P['squareRoot'] = P['sqrt'] = function () {
-	        var m, n, sd, r, rep, t,
-	            x = this,
-	            c = x['c'],
-	            s = x['s'],
-	            e = x['e'],
-	            Decimal = x['constructor'],
-	            half = new Decimal(0.5);
-
-	        // Negative/NaN/Infinity/zero?
-	        if ( s !== 1 || !c || !c[0] ) {
-
-	            return new Decimal( !s || s < 0 && ( !c || c[0] ) ? NaN : c ? x : 1 / 0 );
-	        }
-
-	        external = false;
-
-	        // Initial estimate.
-	        s = Math.sqrt( +x );
-
-	        /*
-	         Math.sqrt underflow/overflow?
-	         Pass x to Math.sqrt as integer, then adjust the exponent of the result.
-	         */
-	        if ( s == 0 || s == 1 / 0 ) {
-	            n = coefficientToString(c);
-
-	            if ( ( n.length + e ) % 2 == 0 ) {
-	                n += '0';
-	            }
-
-	            s = Math.sqrt(n);
-	            e = mathfloor( ( e + 1 ) / 2 ) - ( e < 0 || e % 2 );
-
-	            if ( s == 1 / 0 ) {
-	                n = '1e' + e;
-	            } else {
-	                n = s.toExponential();
-	                n = n.slice( 0, n.indexOf('e') + 1 ) + e;
-	            }
-
-	            r = new Decimal(n);
-	        } else {
-	            r = new Decimal( s.toString() );
-	        }
-
-	        sd = ( e = Decimal['precision'] ) + 3;
-
-	        // Newton-Raphson iteration.
-	        for ( ; ; ) {
-	            t = r;
-	            r = half['times']( t['plus']( div( x, t, sd + 2, 1 ) ) );
-
-	            if ( coefficientToString( t['c'] ).slice( 0, sd ) ===
-	                ( n = coefficientToString( r['c'] ) ).slice( 0, sd ) ) {
-	                n = n.slice( sd - 3, sd + 1 );
-
-	                /*
-	                 The 4th rounding digit may be in error by -1 so if the 4 rounding digits are
-	                 9999 or 4999 (i.e. approaching a rounding boundary) continue the iteration.
-	                 */
-	                if ( n == '9999' || !rep && n == '4999' ) {
-
-	                    /*
-	                     On the first iteration only, check to see if rounding up gives the exact result
-	                     as the nines may infinitely repeat.
-	                     */
-	                    if ( !rep ) {
-	                        rnd( t, e + 1, 0 );
-
-	                        if ( t['times'](t)['eq'](x) ) {
-	                            r = t;
-
-	                            break;
-	                        }
-	                    }
-	                    sd += 4;
-	                    rep = 1;
-	                } else {
-
-	                    /*
-	                     If the rounding digits are null, 0{0,4} or 50{0,3}, check for an exact result.
-	                     If not, then there are further digits and m will be truthy.
-	                     */
-	                    if ( !+n || !+n.slice(1) && n.charAt(0) == '5' ) {
-
-	                        // Truncate to the first rounding digit.
-	                        rnd( r, e + 1, 1 );
-	                        m = !r['times'](r)['eq'](x);
-	                    }
-
-	                    break;
-	                }
-	            }
-	        }
-	        external = true;
-
-	        return rnd( r, e, Decimal['rounding'], m );
-	    };
-
-
-	    /*
-	     *  n * 0 = 0
-	     *  n * N = N
-	     *  n * I = I
-	     *  0 * n = 0
-	     *  0 * 0 = 0
-	     *  0 * N = N
-	     *  0 * I = N
-	     *  N * n = N
-	     *  N * 0 = N
-	     *  N * N = N
-	     *  N * I = N
-	     *  I * n = I
-	     *  I * 0 = N
-	     *  I * N = N
-	     *  I * I = I
-	     *
-	     * Return a new Decimal whose value is this Decimal times Decimal(y), rounded to precision
-	     * significant digits using rounding mode rounding.
-	     *
-	     */
-	    P['times'] = function ( y, b ) {
-	        var c, e,
-	            x = this,
-	            Decimal = x['constructor'],
-	            xc = x['c'],
-	            yc = ( id = 11, y = new Decimal( y, b ), y['c'] ),
-	            i = mathfloor( x['e'] / LOGBASE ),
-	            j = mathfloor( y['e'] / LOGBASE ),
-	            a = x['s'];
-
-	        b = y['s'];
-
-	        y['s'] = a == b ? 1 : -1;
-
-	        // Either NaN/Infinity/0?
-	        if ( !i && ( !xc || !xc[0] ) || !j && ( !yc || !yc[0] ) ) {
-
-	            // Either NaN?
-	            return new Decimal( !a || !b ||
-
-	              // x is 0 and y is Infinity  or y is 0 and x is Infinity?
-	              xc && !xc[0] && !yc || yc && !yc[0] && !xc
-
-	                // Return NaN.
-	                ? NaN
-
-	                // Either Infinity?
-	                : !xc || !yc
-
-	                  // Return +-Infinity.
-	                  ? y['s'] / 0
-
-	                  // x or y is 0. Return +-0.
-	                  : y['s'] * 0 );
-	        }
-
-	        e = i + j;
-	        a = xc.length;
-	        b = yc.length;
-
-	        if ( a < b ) {
-
-	            // Swap.
-	            c = xc, xc = yc, yc = c;
-	            j = a, a = b, b = j;
-	        }
-
-	        for ( j = a + b, c = []; j--; c.push(0) );
-
-	        // Multiply!
-	        for ( i = b - 1; i > -1; i-- ) {
-	            b = 0;
-
-	            for ( j = a + i; j > i; ) {
-	                  b = c[j] + yc[i] * xc[j - i - 1] + b;
-	                  c[j--] = b % BASE | 0;
-	                  b = b / BASE | 0;
-	            }
-	            c[j] = ( c[j] + b ) % BASE | 0;
-	        }
-
-	        if (b) {
-	            ++e;
-	        } else if ( !c[0] ) {
-
-	            // Remove leading zero.
-	            c.shift();
-	        }
-
-	        // Remove trailing zeros.
-	        for ( j = c.length; !c[--j]; c.pop() );
-	        y['c'] = c;
-
-	        // Get the number of digits of c[0].
-	        for ( a = 1, b = c[0]; b >= 10; b /= 10, a++ );
-	        y['e'] = a + e * LOGBASE - 1;
-
-	        return external ? rnd( y, Decimal['precision'], Decimal['rounding'] ) : y;
-	    };
-
-
-	    /*
-	     * Return a new Decimal whose value is the value of this Decimal rounded to a maximum of dp
-	     * decimal places using rounding mode rm or rounding if rm is omitted.
-	     *
-	     * If dp is omitted, return a new Decimal whose value is the value of this Decimal.
-	     *
-	     * [dp] {number} Decimal places. Integer, 0 to MAX_DIGITS inclusive.
-	     * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
-	     *
-	     * 'toDP() dp out of range: {dp}'
-	     * 'toDP() dp not an integer: {dp}'
-	     * 'toDP() rounding mode not an integer: {rm}'
-	     * 'toDP() rounding mode out of range: {rm}'
-	     *
-	     */
-	    P['toDecimalPlaces'] = P['toDP'] = function ( dp, rm ) {
-	        var x = this;
-	        x = new x['constructor'](x);
-
-	        return dp == null || !checkArg( x, dp, 'toDP' )
-	          ? x
-	          : rnd( x, ( dp | 0 ) + x['e'] + 1, checkRM( x, rm, 'toDP' ) );
-	    };
-
-
-	    /*
-	     * Return a string representing the value of this Decimal in exponential notation rounded to dp
-	     * fixed decimal places using rounding mode rounding.
-	     *
-	     * [dp] {number} Decimal places. Integer, 0 to MAX_DIGITS inclusive.
-	     * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
-	     *
-	     * errors true: Throw if dp and rm are not undefined, null or integers in range.
-	     * errors false: Ignore dp and rm if not numbers or not in range, and truncate non-integers.
-	     *
-	     * 'toExponential() dp not an integer: {dp}'
-	     * 'toExponential() dp out of range: {dp}'
-	     * 'toExponential() rounding mode not an integer: {rm}'
-	     * 'toExponential() rounding mode out of range: {rm}'
-	     *
-	     */
-	    P['toExponential'] = function ( dp, rm ) {
-	        var x = this;
-
-	        return x['c']
-	          ? format( x, dp != null && checkArg( x, dp, 'toExponential' ) ? dp | 0 : null,
-	            dp != null && checkRM( x, rm, 'toExponential' ), 1 )
-	          : x.toString();
-	    };
-
-
-	    /*
-	     * Return a string representing the value of this Decimal in normal (fixed-point) notation to
-	     * dp fixed decimal places and rounded using rounding mode rm or rounding if rm is omitted.
-	     *
-	     * Note: as with JS numbers, (-0).toFixed(0) is '0', but e.g. (-0.00001).toFixed(0) is '-0'.
-	     *
-	     * [dp] {number} Decimal places. Integer, 0 to MAX_DIGITS inclusive.
-	     * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
-	     *
-	     * errors true: Throw if dp and rm are not undefined, null or integers in range.
-	     * errors false: Ignore dp and rm if not numbers or not in range, and truncate non-integers.
-	     *
-	     * 'toFixed() dp not an integer: {dp}'
-	     * 'toFixed() dp out of range: {dp}'
-	     * 'toFixed() rounding mode not an integer: {rm}'
-	     * 'toFixed() rounding mode out of range: {rm}'
-	     *
-	     */
-	    P['toFixed'] = function ( dp, rm ) {
-	        var str,
-	            x = this,
-	            Decimal = x['constructor'],
-	            neg = Decimal['toExpNeg'],
-	            pos = Decimal['toExpPos'];
-
-	        if ( dp != null ) {
-	            dp = checkArg( x, dp, str = 'toFixed' ) ? x['e'] + ( dp | 0 ) : null;
-	            rm = checkRM( x, rm, str );
-	        }
-
-	        // Prevent toString returning exponential notation;
-	        Decimal['toExpNeg'] = -( Decimal['toExpPos'] = 1 / 0 );
-
-	        if ( dp == null || !x['c'] ) {
-	            str = x.toString();
-	        } else {
-	            str = format( x, dp, rm );
-
-	            // (-0).toFixed() is '0', but (-0.1).toFixed() is '-0'.
-	            // (-0).toFixed(1) is '0.0', but (-0.01).toFixed(1) is '-0.0'.
-	            if ( x['s'] < 0 && x['c'] ) {
-
-	                // As e.g. (-0).toFixed(3), will wrongly be returned as -0.000 from toString.
-	                if ( !x['c'][0] ) {
-	                    str = str.replace( '-', '' );
-
-	                // As e.g. -0.5 if rounded to -0 will cause toString to omit the minus sign.
-	                } else if ( str.indexOf('-') < 0 ) {
-	                    str = '-' + str;
-	                }
-	            }
-	        }
-	        Decimal['toExpNeg'] = neg;
-	        Decimal['toExpPos'] = pos;
-
-	        return str;
-	    };
-
-
-	    /*
-	     * Return a string representing the value of this Decimal in fixed-point notation to dp decimal
-	     * places, rounded using rounding mode rm or Decimal.rounding if rm is omitted, and formatted
-	     * according to the following properties of the Decimal.format object.
-	     *
-	     *  Decimal.format = {
-	     *      decimalSeparator : '.',
-	     *      groupSeparator : ',',
-	     *      groupSize : 3,
-	     *      secondaryGroupSize : 0,
-	     *      fractionGroupSeparator : '\xA0',    // non-breaking space
-	     *      fractionGroupSize : 0
-	     *  };
-	     *
-	     * [dp] {number} Decimal places. Integer, 0 to MAX_DIGITS inclusive.
-	     * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive
-	     *
-	     * (If dp or rm are invalid the error message will give the offending method call as toFixed.)
-	     *
-	     */
-	    P['toFormat'] = function( dp, rm ) {
-	        var x = this;
-
-	        if ( !x['c'] ) {
-	            return x.toString();
-	        }
-
-	        var i,
-	            isNeg = x['s'] < 0,
-	            f = x['constructor']['format'],
-	            groupSeparator = f['groupSeparator'],
-	            g1 = +f['groupSize'],
-	            g2 = +f['secondaryGroupSize'],
-	            arr = x.toFixed( dp, rm ).split('.'),
-	            intPart = arr[0],
-	            fractionPart = arr[1],
-	            intDigits = isNeg ? intPart.slice(1) : intPart,
-	            len = intDigits.length;
-
-	        if (g2) {
-	            len -= ( i = g1, g1 = g2, g2 = i );
-	        }
-
-	        if ( g1 > 0 && len > 0 ) {
-	            i = len % g1 || g1;
-	            intPart = intDigits.substr( 0, i );
-
-	            for ( ; i < len; i += g1 ) {
-	                intPart += groupSeparator + intDigits.substr( i, g1 );
-	            }
-
-	            if ( g2 > 0 ) {
-	                intPart += groupSeparator + intDigits.slice(i);
-	            }
-
-	            if (isNeg) {
-	                intPart = '-' + intPart;
-	            }
-	        }
-
-	        return fractionPart
-	          ? intPart + f['decimalSeparator'] + ( ( g2 = +f['fractionGroupSize'] )
-	            ? fractionPart.replace( new RegExp( '\\d{' + g2 + '}\\B', 'g' ),
-	              '$&' + f['fractionGroupSeparator'] )
-	            : fractionPart )
-	          : intPart;
-	    };
-
-
-	    /*
-	     * Return a string array representing the value of this Decimal as a simple fraction with an
-	     * integer numerator and an integer denominator.
-	     *
-	     * The denominator will be a positive non-zero value less than or equal to the specified
-	     * maximum denominator. If a maximum denominator is not specified, the denominator will be
-	     * the lowest value necessary to represent the number exactly.
-	     *
-	     * [maxD] {number|string|Decimal} Maximum denominator. Integer >= 1 and < Infinity.
-	     *
-	     */
-	    P['toFraction'] = function (maxD) {
-	        var d0, d2, e, frac, n, n0, p, q,
-	            x = this,
-	            Decimal = x['constructor'],
-	            n1 = d0 = new Decimal( Decimal['ONE'] ),
-	            d1 = n0 = new Decimal(0),
-	            xc = x['c'],
-	            d = new Decimal(d1);
-
-	        // NaN, Infinity.
-	        if ( !xc ) {
-
-	            return x.toString();
-	        }
-
-	        e = d['e'] = getCoeffLength(xc) - x['e'] - 1;
-	        d['c'][0] = mathpow( 10, ( p = e % LOGBASE ) < 0 ? LOGBASE + p : p );
-
-	        // If maxD is undefined or null...
-	        if ( maxD == null ||
-
-	             // or NaN...
-	             ( !( id = 12, n = new Decimal(maxD) )['s'] ||
-
-	               // or less than 1, or Infinity...
-	               ( outOfRange = n['cmp'](n1) < 0 || !n['c'] ) ||
-
-	                 // or not an integer...
-	                 ( Decimal['errors'] && mathfloor( n['e'] / LOGBASE ) < n['c'].length - 1 ) ) &&
-
-	                   // 'toFraction() max denominator not an integer: {maxD}'
-	                   // 'toFraction() max denominator out of range: {maxD}'
-	                   !ifExceptionsThrow( Decimal, 'max denominator', maxD, 'toFraction', 0 ) ||
-
-	                     // or greater than the maximum denominator needed to specify the value exactly.
-	                     ( maxD = n )['cmp'](d) > 0 ) {
-
-	            // d is 10**e, n1 is 1.
-	            maxD = e > 0 ? d : n1;
-	        }
-
-	        external = false;
-	        n = new Decimal( coefficientToString(xc) );
-	        p = Decimal['precision'];
-	        Decimal['precision'] = e = xc.length * LOGBASE * 2;
-
-	        for ( ; ; )  {
-	            q = div( n, d, 0, 1, 1 );
-	            d2 = d0['plus']( q['times'](d1) );
-
-	            if ( d2['cmp'](maxD) == 1 ) {
-
-	                break;
-	            }
-	            d0 = d1;
-	            d1 = d2;
-
-	            n1 = n0['plus']( q['times']( d2 = n1 ) );
-	            n0 = d2;
-
-	            d = n['minus']( q['times']( d2 = d ) );
-	            n = d2;
-	        }
-
-	        d2 = div( maxD['minus'](d0), d1, 0, 1, 1 );
-	        n0 = n0['plus']( d2['times'](n1) );
-	        d0 = d0['plus']( d2['times'](d1) );
-	        n0['s'] = n1['s'] = x['s'];
-
-	        // Determine which fraction is closer to x, n0/d0 or n1/d1?
-	        frac = div( n1, d1, e, 1 )['minus'](x)['abs']()['cmp'](
-	               div( n0, d0, e, 1 )['minus'](x)['abs']() ) < 1
-	          ? [ n1 + '', d1 + '' ]
-	          : [ n0 + '', d0 + '' ];
-
-	        external = true;
-	        Decimal['precision'] = p;
-
-	        return frac;
-	    };
-
-
-	    /*
-	     * Returns a new Decimal whose value is the nearest multiple of the magnitude of n to the value
-	     * of this Decimal.
-	     *
-	     * If the value of this Decimal is equidistant from two multiples of n, the rounding mode rm,
-	     * or rounding if rm is omitted or is null or undefined, determines the direction of the
-	     * nearest multiple.
-	     *
-	     * In the context of this method, rounding mode 4 (ROUND_HALF_UP) is the same as rounding mode 0
-	     * (ROUND_UP), and so on.
-	     *
-	     * The return value will always have the same sign as this Decimal, unless either this Decimal
-	     * or n is NaN, in which case the return value will be also be NaN.
-	     *
-	     * The return value is not rounded to precision significant digits.
-	     *
-	     * n {number|string|Decimal} The magnitude to round to a multiple of.
-	     * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
-	     *
-	     * 'toNearest() rounding mode not an integer: {rm}'
-	     * 'toNearest() rounding mode out of range: {rm}'
-	     *
-	     */
-	    P['toNearest'] = function ( n, rm ) {
-	        var x = this,
-	            Decimal = x['constructor'];
-
-	        x = new Decimal(x);
-
-	        if ( n == null ) {
-	            n = new Decimal( Decimal['ONE'] );
-	            rm = Decimal['rounding'];
-	        } else {
-	            id = 17;
-	            n = new Decimal(n);
-	            rm = checkRM( x, rm, 'toNearest' );
-	        }
-
-	        // If n is finite...
-	        if ( n['c'] ) {
-
-	           // If x is finite...
-	            if ( x['c'] ) {
-
-	                if ( n['c'][0] ) {
-	                    external = false;
-	                    x = div( x, n, 0, rm < 4 ? [4, 5, 7, 8][rm] : rm, 1 )['times'](n);
-	                    external = true;
-	                    rnd(x);
-	                } else {
-	                    x['c'] = [ x['e'] = 0 ];
-	                }
-	            }
-
-	        // n is NaN or +-Infinity. If x is not NaN...
-	        } else if ( x['s'] ) {
-
-	            // If n is +-Infinity...
-	            if ( n['s'] ) {
-	                n['s'] = x['s'];
-	            }
-	            x = n;
-	        }
-
-	        return x;
-	    };
-
-
-	    /*
-	     * Return the value of this Decimal converted to a number primitive.
-	     *
-	     */
-	    P['toNumber'] = function () {
-	        var x = this;
-
-	        // Ensure zero has correct sign.
-	        return +x || ( x['s'] ? 0 * x['s'] : NaN );
-	    };
-
-
-	    /*
-	     * Return a new Decimal whose value is the value of this Decimal raised to the power
-	     * Decimal(y, b), rounded to precision significant digits using rounding mode rounding.
-	     *
-	     * ECMAScript compliant.
-	     *
-	     *   x is any value, including NaN.
-	     *   n is any number, including �Infinity unless stated.
-	     *
-	     *   pow( x, NaN )                           = NaN
-	     *   pow( x, �0 )                            = 1
-
-	     *   pow( NaN, nonzero )                     = NaN
-	     *   pow( abs(n) > 1, +Infinity )            = +Infinity
-	     *   pow( abs(n) > 1, -Infinity )            = +0
-	     *   pow( abs(n) == 1, �Infinity )           = NaN
-	     *   pow( abs(n) < 1, +Infinity )            = +0
-	     *   pow( abs(n) < 1, -Infinity )            = +Infinity
-	     *   pow( +Infinity, n > 0 )                 = +Infinity
-	     *   pow( +Infinity, n < 0 )                 = +0
-	     *   pow( -Infinity, odd integer > 0 )       = -Infinity
-	     *   pow( -Infinity, even integer > 0 )      = +Infinity
-	     *   pow( -Infinity, odd integer < 0 )       = -0
-	     *   pow( -Infinity, even integer < 0 )      = +0
-	     *   pow( +0, n > 0 )                        = +0
-	     *   pow( +0, n < 0 )                        = +Infinity
-	     *   pow( -0, odd integer > 0 )              = -0
-	     *   pow( -0, even integer > 0 )             = +0
-	     *   pow( -0, odd integer < 0 )              = -Infinity
-	     *   pow( -0, even integer < 0 )             = +Infinity
-	     *   pow( finite n < 0, finite non-integer ) = NaN
-	     *
-	     * For non-integer and larger exponents pow(x, y) is calculated using
-	     *
-	     *   x^y = exp(y*ln(x))
-	     *
-	     * Assuming the first 15 rounding digits are each equally likely to be any digit 0-9, the
-	     * probability of an incorrectly rounded result
-	     * P( [49]9{14} | [50]0{14} ) = 2 * 0.2 * 10^-14 = 4e-15 = 1/2.5e+14
-	     * i.e. 1 in 250,000,000,000,000
-	     *
-	     * If a result is incorrectly rounded the maximum error will be 1 ulp (unit in last place).
-	     *
-	     * y {number|string|Decimal} The power to which to raise this Decimal.
-	     * [b] {number} The base of y.
-	     *
-	     */
-	    P['toPower'] = P['pow'] = function ( y, b ) {
-	        var a, e, n, r,
-	            x = this,
-	            Decimal = x['constructor'],
-	            s = x['s'],
-	            yN = +( id = 13, y = new Decimal( y, b ) ),
-	            i = yN < 0 ? -yN : yN,
-	            pr = Decimal['precision'],
-	            rm = Decimal['rounding'];
-
-	        // Handle +-Infinity, NaN and +-0.
-	        if ( !x['c'] || !y['c'] || ( n = !x['c'][0] ) || !y['c'][0] ) {
-
-	            // valueOf -0 is 0, so check for 0 then multiply it by the sign.
-	            return new Decimal( mathpow( n ? s * 0 : +x, yN ) );
-	        }
-
-	        x = new Decimal(x);
-	        a = x['c'].length;
-
-	        // if x == 1
-	        if ( !x['e'] && x['c'][0] == x['s'] && a == 1 ) {
-
-	            return x;
-	        }
-
-	        b = y['c'].length - 1;
-
-	        // if y == 1
-	        if ( !y['e'] && y['c'][0] == y['s'] && !b ) {
-	            r = rnd( x, pr, rm );
-	        } else {
-	            e = mathfloor( y['e'] / LOGBASE );
-	            n = e >= b;
-
-	            // If y is not an integer and x is negative, return NaN.
-	            if ( !n && s < 0 ) {
-	                r = new Decimal(NaN);
-	            } else {
-
-	                /*
-	                 If the approximate number of significant digits of x multiplied by abs(y) is less
-	                 than INT_POW_LIMIT use the 'exponentiation by squaring' algorithm.
-	                 */
-	                if ( n && a * LOGBASE * i < INT_POW_LIMIT ) {
-	                    r = intPow( Decimal, x, i );
-
-	                    if ( y['s'] < 0 ) {
-
-	                        return Decimal['ONE']['div'](r);
-	                    }
-	                } else {
-
-	                    // Result is negative if x is negative and the last digit of integer y is odd.
-	                    s = s < 0 && y['c'][ Math.max( e, b ) ] & 1 ? -1 : 1;
-
-	                    b = mathpow( +x, yN );
-
-	                    /*
-	                     Estimate result exponent.
-	                     x^y = 10^e,  where e = y * log10(x)
-	                     log10(x) = log10(x_significand) + x_exponent
-	                     log10(x_significand) = ln(x_significand) / ln(10)
-	                     */
-	                    e = b == 0 || !isFinite(b)
-	                      ? mathfloor( yN * ( Math.log( '0.' + coefficientToString( x['c'] ) ) /
-	                        Math.LN10 + x['e'] + 1 ) )
-	                      : new Decimal( b + '' )['e'];
-
-	                    // Estimate may be incorrect e.g. x: 0.999999999999999999, y: 2.29, e: 0, r.e:-1
-
-	                    // Overflow/underflow?
-	                    if ( e > Decimal['maxE'] + 1 || e < Decimal['minE'] - 1 ) {
-
-	                        return new Decimal( e > 0 ? s / 0 : 0 );
-	                    }
-
-	                    external = false;
-	                    Decimal['rounding'] = x['s'] = 1;
-
-	                    /*
-	                     Estimate extra digits needed from ln(x) to ensure five correct rounding digits
-	                     in result (i was unnecessary before max exponent was extended?).
-	                     Example of failure before i was introduced: (precision: 10),
-	                     new Decimal(2.32456).pow('2087987436534566.46411')
-	                     should be 1.162377823e+764914905173815, but is 1.162355823e+764914905173815
-	                     */
-	                    i = Math.min( 12, ( e + '' ).length );
-
-	                    // r = x^y = exp(y*ln(x))
-	                    r = exp( y['times']( ln( x, pr + i ) ), pr );
-
-	                    // Truncate to the required precision plus five rounding digits.
-	                    r = rnd( r, pr + 5, 1 );
-
-	                    /*
-	                     If the rounding digits are [49]9999 or [50]0000 increase the precision by 10
-	                     and recalculate the result.
-	                     */
-	                    if ( checkRoundingDigits( r['c'], pr, rm ) ) {
-	                        e = pr + 10;
-
-	                        // Truncate to the increased precision plus five rounding digits.
-	                        r = rnd( exp( y['times']( ln( x, e + i ) ), e ), e + 5, 1 );
-
-	                        /*
-	                          Check for 14 nines from the 2nd rounding digit (the first rounding digit
-	                          may be 4 or 9).
-	                         */
-	                        if ( +coefficientToString( r['c'] ).slice( pr + 1, pr + 15 ) + 1 == 1e14 ) {
-	                            r = rnd( r, pr + 1, 0 );
-	                        }
-	                    }
-
-	                    r['s'] = s;
-	                    external = true;
-	                    Decimal['rounding'] = rm;
-	                }
-
-	                r = rnd( r, pr, rm );
-	            }
-	        }
-
-	        return r;
-	    };
-
-
-	    /*
-	     * Return a string representing the value of this Decimal rounded to sd significant digits
-	     * using rounding mode rounding.
-	     *
-	     * Return exponential notation if sd is less than the number of digits necessary to represent
-	     * the integer part of the value in normal notation.
-	     *
-	     * sd {number} Significant digits. Integer, 1 to MAX_DIGITS inclusive.
-	     * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
-	     *
-	     * errors true: Throw if sd and rm are not undefined, null or integers in range.
-	     * errors false: Ignore sd and rm if not numbers or not in range, and truncate non-integers.
-	     *
-	     * 'toPrecision() sd not an integer: {sd}'
-	     * 'toPrecision() sd out of range: {sd}'
-	     * 'toPrecision() rounding mode not an integer: {rm}'
-	     * 'toPrecision() rounding mode out of range: {rm}'
-	     *
-	     */
-	    P['toPrecision'] = function ( sd, rm ) {
-	        var x = this;
-
-	        return sd != null && checkArg( x, sd, 'toPrecision', 1 ) && x['c']
-	          ? format( x, --sd | 0, checkRM( x, rm, 'toPrecision' ), 2 )
-	          : x.toString();
-	    };
-
-
-	    /*
-	     * Return a new Decimal whose value is this Decimal rounded to a maximum of d significant
-	     * digits using rounding mode rm, or to precision and rounding respectively if omitted.
-	     *
-	     * [d] {number} Significant digits. Integer, 1 to MAX_DIGITS inclusive.
-	     * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
-	     *
-	     * 'toSD() digits out of range: {d}'
-	     * 'toSD() digits not an integer: {d}'
-	     * 'toSD() rounding mode not an integer: {rm}'
-	     * 'toSD() rounding mode out of range: {rm}'
-	     *
-	     */
-	    P['toSignificantDigits'] = P['toSD'] = function ( d, rm ) {
-	        var x = this,
-	            Decimal = x['constructor'];
-
-	        x = new Decimal(x);
-
-	        return d == null || !checkArg( x, d, 'toSD', 1 )
-	          ? rnd( x, Decimal['precision'], Decimal['rounding'] )
-	          : rnd( x, d | 0, checkRM( x, rm, 'toSD' ) );
-	    };
-
-
-	    /*
-	     * Return a string representing the value of this Decimal in base b, or base 10 if b is
-	     * omitted. If a base is specified, including base 10, round to precision significant digits
-	     * using rounding mode rounding.
-	     *
-	     * Return exponential notation if a base is not specified, and this Decimal has a positive
-	     * exponent equal to or greater than toExpPos, or a negative exponent equal to or less than
-	     * toExpNeg.
-	     *
-	     * [b] {number} Base. Integer, 2 to 64 inclusive.
-	     *
-	     */
-	    P['toString'] = function (b) {
-	        var u, str, strL,
-	            x = this,
-	            Decimal = x['constructor'],
-	            xe = x['e'];
-
-	        // Infinity or NaN?
-	        if ( xe === null ) {
-	            str = x['s'] ? 'Infinity' : 'NaN';
-
-	        // Exponential format?
-	        } else if ( b === u && ( xe <= Decimal['toExpNeg'] || xe >= Decimal['toExpPos'] ) ) {
-
-	            return format( x, null, Decimal['rounding'], 1 );
-	        } else {
-	            str = coefficientToString( x['c'] );
-
-	            // Negative exponent?
-	            if ( xe < 0 ) {
-
-	                // Prepend zeros.
-	                for ( ; ++xe; str = '0' + str );
-	                str = '0.' + str;
-
-	            // Positive exponent?
-	            } else if ( strL = str.length, xe > 0 ) {
-
-	                if ( ++xe > strL ) {
-
-	                    // Append zeros.
-	                    for ( xe -= strL; xe-- ; str += '0' );
-
-	                } else if ( xe < strL ) {
-	                    str = str.slice( 0, xe ) + '.' + str.slice(xe);
-	                }
-
-	            // Exponent zero.
-	            } else {
-	                u = str.charAt(0);
-
-	                if ( strL > 1 ) {
-	                    str = u + '.' + str.slice(1);
-
-	                // Avoid '-0'
-	                } else if ( u == '0' ) {
-
-	                    return u;
-	                }
-	            }
-
-	            if ( b != null ) {
-
-	                if ( !( outOfRange = !( b >= 2 && b < 65 ) ) &&
-	                  ( b == (b | 0) || !Decimal['errors'] ) ) {
-	                    str = convertBase( Decimal, str, b | 0, 10, x['s'] );
-
-	                    // Avoid '-0'
-	                    if ( str == '0' ) {
-
-	                        return str;
-	                    }
-	                } else {
-
-	                    // 'toString() base not an integer: {b}'
-	                    // 'toString() base out of range: {b}'
-	                    ifExceptionsThrow( Decimal, 'base', b, 'toString', 0 );
-	                }
-	            }
-	        }
-
-	        return x['s'] < 0 ? '-' + str : str;
-	    };
-
-
-	    /*
-	     * Return a new Decimal whose value is the value of this Decimal truncated to a whole number.
-	     *
-	     */
-	    P['truncated'] = P['trunc'] = function () {
-
-	        return rnd( new this['constructor'](this), this['e'] + 1, 1 );
-	    };
-
-
-	    /*
-	     * Return as toString, but do not accept a base argument.
-	     *
-	     * Ensures that JSON.stringify() uses toString for serialization.
-	     *
-	     */
-	    P['valueOf'] = P['toJSON'] = function () {
-
-	        return this.toString();
-	    };
-
-
-	    /*
-	    // Add aliases to match BigDecimal method names.
-	    P['add'] = P['plus'];
-	    P['subtract'] = P['minus'];
-	    P['multiply'] = P['times'];
-	    P['divide'] = P['div'];
-	    P['remainder'] = P['mod'];
-	    P['compareTo'] = P['cmp'];
-	    P['negate'] = P['neg'];
-	     */
-
-
-	    // Private functions for Decimal.prototype methods.
-
-
-	    /*
-	     *  coefficientToString
-	     *  checkRoundingDigits
-	     *  checkRM
-	     *  checkArg
-	     *  convertBase
-	     *  div
-	     *  exp
-	     *  format
-	     *  getCoeffLength
-	     *  ifExceptionsThrow
-	     *  intPow
-	     *  ln
-	     *  rnd
-	     */
-
-
-	    function coefficientToString(a) {
-	        var s, z,
-	            i = 1,
-	            j = a.length,
-	            r = a[0] + '';
-
-	        for ( ; i < j; i++ ) {
-	            s = a[i] + '';
-
-	            for ( z = LOGBASE - s.length; z--; ) {
-	                s = '0' + s;
-	            }
-
-	            r += s;
-	        }
-
-	        // '0'
-	        for ( j = r.length; r.charCodeAt(--j) === 48; );
-
-	        return r.slice( 0, j + 1 || 1 );
-	    }
-
-
-	    /*
-	     * Check 5 rounding digits if repeating is null, 4 otherwise.
-	     * repeating == null if caller is log or pow,
-	     * repeating != null if caller is ln or exp.
-	     *
-	     *
-	     // Previous, much simpler implementation when coefficient was base 10.
-	     function checkRoundingDigits( c, i, rm, repeating ) {
-	         return ( !repeating && rm > 3 && c[i] == 4 ||
-	           ( repeating || rm < 4 ) && c[i] == 9 ) && c[i + 1] == 9 && c[i + 2] == 9 &&
-	             c[i + 3] == 9 && ( repeating != null || c[i + 4] == 9 ) ||
-	               repeating == null && ( c[i] == 5 || !c[i] ) && !c[i + 1] && !c[i + 2] &&
-	                 !c[i + 3] && !c[i + 4];
-	     }
-	     */
-	    function checkRoundingDigits( c, i, rm, repeating ) {
-	        var ci, k, n, r, rd;
-
-	        // Get the length of the first element of the array c.
-	        for ( k = 1, n = c[0]; n >= 10; n /= 10, k++ );
-
-	        n = i - k;
-
-	        // Is the rounding digit in the first element of c?
-	        if ( n < 0 ) {
-	            n += LOGBASE;
-	            ci = 0;
-	        } else {
-	            ci = Math.ceil( ( n + 1 ) / LOGBASE );
-	            n %= LOGBASE;
-	        }
-
-	        k = mathpow( 10, LOGBASE - n );
-	        rd = c[ci] % k | 0;
-
-	        if ( repeating == null ) {
-
-	            if ( n < 3 ) {
-
-	                if ( n == 0 ) {
-	                    rd = rd / 100 | 0;
-	                } else if ( n == 1 ) {
-	                    rd = rd / 10 | 0;
-	                }
-
-	                r = rm < 4 && rd == 99999 || rm > 3 && rd == 49999 || rd == 50000 || rd == 0;
-	            } else {
-	                r = ( rm < 4 && rd + 1 == k || rm > 3 && rd + 1 == k / 2 ) &&
-	                    ( c[ci + 1] / k / 100 | 0 ) == mathpow( 10, n - 2 ) - 1 ||
-	                        ( rd == k / 2 || rd == 0 ) && ( c[ci + 1] / k / 100 | 0 ) == 0;
-	            }
-	        } else {
-
-	            if ( n < 4 ) {
-
-	                if ( n == 0 ) {
-	                    rd = rd / 1000 | 0;
-	                } else if ( n == 1 ) {
-	                    rd = rd / 100 | 0;
-	                } else if ( n == 2 ) {
-	                    rd = rd / 10 | 0;
-	                }
-
-	                r = ( repeating || rm < 4 ) && rd == 9999 || !repeating && rm > 3 && rd == 4999;
-	            } else {
-	                r = ( ( repeating || rm < 4 ) && rd + 1 == k ||
-	                ( !repeating && rm > 3 ) && rd + 1 == k / 2 ) &&
-	                    ( c[ci + 1] / k / 1000 | 0 ) == mathpow( 10, n - 3 ) - 1;
-	            }
-	        }
-
-	        return r;
-	    }
-
-
-	    /*
-	     * Check and return rounding mode. If rm is invalid, return rounding mode rounding.
-	     */
-	    function checkRM( x, rm, method ) {
-	        var Decimal = x['constructor'];
-
-	        return rm == null || ( ( outOfRange = rm < 0 || rm > 8 ) ||
-	          rm !== 0 && ( Decimal['errors'] ? parseInt : parseFloat )(rm) != rm ) &&
-	            !ifExceptionsThrow( Decimal, 'rounding mode', rm, method, 0 )
-	              ? Decimal['rounding'] : rm | 0;
-	    }
-
-
-	    /*
-	     * Check that argument n is in range, return true or false.
-	     */
-	    function checkArg( x, n, method, min ) {
-	        var Decimal = x['constructor'];
-
-	        return !( outOfRange = n < ( min || 0 ) || n >= MAX_DIGITS + 1 ) &&
-
-	          /*
-	           * Include 'n === 0' because Opera has 'parseFloat(-0) == -0' as false
-	           * despite having 'parseFloat(-0) === -0 && parseFloat('-0') === -0 && 0 == -0' as true.
-	           */
-	          ( n === 0 || ( Decimal['errors'] ? parseInt : parseFloat )(n) == n ) ||
-	            ifExceptionsThrow( Decimal, 'argument', n, method, 0 );
-	    }
-
-
-	    /*
-	     * Convert a numeric string of baseIn to a numeric string of baseOut.
-	     */
-	    convertBase = (function () {
-
-	        /*
-	         * Convert string of baseIn to an array of numbers of baseOut.
-	         * Eg. convertBase('255', 10, 16) returns [15, 15].
-	         * Eg. convertBase('ff', 16, 10) returns [2, 5, 5].
-	         */
-	        function toBaseOut( str, baseIn, baseOut ) {
-	            var j,
-	                arr = [0],
-	                arrL,
-	                i = 0,
-	                strL = str.length;
-
-	            for ( ; i < strL; ) {
-	                for ( arrL = arr.length; arrL--; arr[arrL] *= baseIn );
-	                arr[ j = 0 ] += NUMERALS.indexOf( str.charAt( i++ ) );
-
-	                for ( ; j < arr.length; j++ ) {
-
-	                    if ( arr[j] > baseOut - 1 ) {
-
-	                        if ( arr[j + 1] == null ) {
-	                            arr[j + 1] = 0;
-	                        }
-	                        arr[j + 1] += arr[j] / baseOut | 0;
-	                        arr[j] %= baseOut;
-	                    }
-	                }
-	            }
-
-	            return arr.reverse();
-	        }
-
-	        return function ( Decimal, str, baseOut, baseIn, sign ) {
-	            var e, j, r, x, xc, y,
-	                i = str.indexOf( '.' ),
-	                pr = Decimal['precision'],
-	                rm = Decimal['rounding'];
-
-	            if ( baseIn < 37 ) {
-	                str = str.toLowerCase();
-	            }
-
-	            // Non-integer.
-	            if ( i >= 0 ) {
-	                str = str.replace( '.', '' );
-	                y = new Decimal(baseIn);
-	                x = intPow( Decimal, y, str.length - i );
-
-	                /*
-	                 Convert str as if an integer, then divide the result by its base raised to a power
-	                 such that the fraction part will be restored.
-	                 Use toFixed to avoid possible exponential notation.
-	                 */
-	                y['c'] = toBaseOut( x.toFixed(), 10, baseOut );
-	                y['e'] = y['c'].length;
-	            }
-
-	            // Convert the number as integer.
-	            xc = toBaseOut( str, baseIn, baseOut );
-	            e = j = xc.length;
-
-	            // Remove trailing zeros.
-	            for ( ; xc[--j] == 0; xc.pop() );
-
-	            if ( !xc[0] ) {
-
-	                return '0';
-	            }
-
-	            if ( i < 0 ) {
-	                e--;
-	            } else {
-	                x['c'] = xc;
-	                x['e'] = e;
-
-	                // sign is needed for correct rounding.
-	                x['s'] = sign;
-	                x = div( x, y, pr, rm, 0, baseOut );
-	                xc = x['c'];
-	                r = x['r'];
-	                e = x['e'];
-	            }
-
-	            // The rounding digit, i.e. the digit after the digit that may be rounded up.
-	            i = xc[pr];
-	            j = baseOut / 2;
-	            r = r || xc[pr + 1] != null;
-
-	            if ( rm < 4
-	              ? ( i != null || r ) && ( rm == 0 || rm == ( sign < 0 ? 3 : 2 ) )
-	              : i > j || i == j && ( rm == 4 || r || rm == 6 && xc[pr - 1] & 1 ||
-	                rm == ( sign < 0 ? 8 : 7 ) ) ) {
-
-	                xc.length = pr;
-
-	                // Rounding up may mean the previous digit has to be rounded up and so on.
-	                for ( --baseOut; ++xc[--pr] > baseOut; ) {
-	                    xc[pr] = 0;
-
-	                    if ( !pr ) {
-	                        ++e;
-	                        xc.unshift(1);
-	                    }
-	                }
-	            } else {
-	                xc.length = pr;
-	            }
-
-	            // Determine trailing zeros.
-	            for ( j = xc.length; !xc[--j]; );
-
-	            // E.g. [4, 11, 15] becomes 4bf.
-	            for ( i = 0, str = ''; i <= j; str += NUMERALS.charAt( xc[i++] ) );
-
-	            // Negative exponent?
-	            if ( e < 0 ) {
-
-	                // Prepend zeros.
-	                for ( ; ++e; str = '0' + str );
-
-	                str = '0.' + str;
-
-	            // Positive exponent?
-	            } else {
-	                i = str.length;
-
-	                if ( ++e > i ) {
-
-	                    // Append zeros.
-	                    for ( e -= i; e-- ; str += '0' );
-
-	                } else if ( e < i ) {
-	                    str = str.slice( 0, e ) + '.' + str.slice(e);
-	                }
-	            }
-
-	            // No negative numbers: the caller will add the sign.
-	            return str;
-	        };
-	    })();
-
-
-
-	    /*
-	     * Perform division in the specified base. Called by div and convertBase.
-	     */
-	    var div = ( function () {
-
-	        // Assumes non-zero x and k, and hence non-zero result.
-	        function multiplyInteger( x, k, base ) {
-	            var temp,
-	                carry = 0,
-	                i = x.length;
-
-	            for ( x = x.slice(); i--; ) {
-	                temp = x[i] * k + carry;
-	                x[i] = temp % base | 0;
-	                carry = temp / base | 0;
-	            }
-
-	            if (carry) {
-	                x.unshift(carry);
-	            }
-
-	            return x;
-	        }
-
-	        function compare( a, b, aL, bL ) {
-	            var i, cmp;
-
-	            if ( aL != bL ) {
-	                cmp = aL > bL ? 1 : -1;
-	            } else {
-
-	                for ( i = cmp = 0; i < aL; i++ ) {
-
-	                    if ( a[i] != b[i] ) {
-	                        cmp = a[i] > b[i] ? 1 : -1;
-
-	                        break;
-	                    }
-	                }
-	            }
-
-	            return cmp;
-	        }
-
-	        function subtract( a, b, aL, base ) {
-	            var i = 0;
-
-	            // Subtract b from a.
-	            for ( ; aL--; ) {
-	                a[aL] -= i;
-	                i = a[aL] < b[aL] ? 1 : 0;
-	                a[aL] = i * base + a[aL] - b[aL];
-	            }
-
-	            // Remove leading zeros.
-	            for ( ; !a[0] && a.length > 1; a.shift() );
-	        }
-
-	        // x: dividend, y: divisor.
-	        return function ( x, y, pr, rm, dp, base ) {
-	            var cmp, e, i, logbase, more, n, prod, prodL, q, qc, rem, remL, rem0, t, xi, xL, yc0,
-	                yL, yz,
-	                Decimal = x['constructor'],
-	                s = x['s'] == y['s'] ? 1 : -1,
-	                xc = x['c'],
-	                yc = y['c'];
-
-	            // Either NaN, Infinity or 0?
-	            if ( !xc || !xc[0] || !yc || !yc[0] ) {
-
-	                return new Decimal(
-
-	                  // Return NaN if either NaN, or both Infinity or 0.
-	                  !x['s'] || !y['s'] || ( xc ? yc && xc[0] == yc[0] : !yc ) ? NaN :
-
-	                    // Return +-0 if x is 0 or y is +-Infinity, or return +-Infinity as y is 0.
-	                    xc && xc[0] == 0 || !yc ? s * 0 : s / 0
-	                );
-	            }
-
-	            if (base) {
-	                logbase = 1;
-	                e = x['e'] - y['e'];
-	            } else {
-	                base = BASE;
-	                logbase = LOGBASE;
-	                e = mathfloor( x['e'] / logbase ) - mathfloor( y['e'] / logbase );
-	            }
-
-	            yL = yc.length;
-	            xL = xc.length;
-	            q = new Decimal(s);
-	            qc = q['c'] = [];
-
-	            // Result exponent may be one less then the current value of e.
-	            // The coefficients of the Decimals from convertBase may have trailing zeros.
-	            for ( i = 0; yc[i] == ( xc[i] || 0 ); i++ );
-
-	            if ( yc[i] > ( xc[i] || 0 ) ) {
-	                e--;
-	            }
-
-	            if ( pr == null ) {
-	                s = pr = Decimal['precision'];
-	                rm = Decimal['rounding'];
-	            } else if (dp) {
-	                s = pr + ( x['e'] - y['e'] ) + 1;
-	            } else {
-	                s = pr;
-	            }
-
-	            if ( s < 0 ) {
-	                qc.push(1);
-	                more = true;
-	            } else {
-
-	                // Convert base 10 decimal places to base 1e7 decimal places.
-	                s = s / logbase + 2 | 0;
-	                i = 0;
-
-	                // divisor < 1e7
-	                if ( yL == 1 ) {
-	                    n = 0;
-	                    yc = yc[0];
-	                    s++;
-
-	                    // 'n' is the carry.
-	                    for ( ; ( i < xL || n ) && s--; i++ ) {
-	                        t = n * base + ( xc[i] || 0 );
-	                        qc[i] = t / yc | 0;
-	                        n = t % yc | 0;
-	                    }
-
-	                    more = n || i < xL;
-
-	                // divisor >= 1e7
-	                } else {
-
-	                    // Normalise xc and yc so highest order digit of yc is >= base/2
-	                    n = base / ( yc[0] + 1 ) | 0;
-
-	                    if ( n > 1 ) {
-	                        yc = multiplyInteger( yc, n, base );
-	                        xc = multiplyInteger( xc, n, base );
-	                        yL = yc.length;
-	                        xL = xc.length;
-	                    }
-
-	                    xi = yL;
-	                    rem = xc.slice( 0, yL );
-	                    remL = rem.length;
-
-	                    // Add zeros to make remainder as long as divisor.
-	                    for ( ; remL < yL; rem[remL++] = 0 );
-
-	                    yz = yc.slice();
-	                    yz.unshift(0);
-	                    yc0 = yc[0];
-
-	                    if ( yc[1] >= base / 2 ) {
-	                        yc0++;
-	                    }
-
-	                    do {
-	                        n = 0;
-
-	                        // Compare divisor and remainder.
-	                        cmp = compare( yc, rem, yL, remL );
-
-	                        // If divisor < remainder.
-	                        if ( cmp < 0 ) {
-
-	                            // Calculate trial digit, n.
-	                            rem0 = rem[0];
-
-	                            if ( yL != remL ) {
-	                                rem0 = rem0 * base + ( rem[1] || 0 );
-	                            }
-
-	                            // n will be how many times the divisor goes into the current remainder.
-	                            n = rem0 / yc0 | 0;
-
-	                            /*
-	                              Algorithm:
-	                              1. product = divisor * trial digit (n)
-	                              2. if product > remainder: product -= divisor, n--
-	                              3. remainder -= product
-	                              4. if product was < remainder at 2:
-	                                5. compare new remainder and divisor
-	                                6. If remainder > divisor: remainder -= divisor, n++
-	                            */
-
-	                            if ( n > 1 ) {
-
-	                                if ( n >= base ) {
-	                                    n = base - 1;
-	                                }
-
-	                                // product = divisor * trial digit.
-	                                prod = multiplyInteger( yc, n, base );
-	                                prodL = prod.length;
-	                                remL = rem.length;
-
-	                                // Compare product and remainder.
-	                                cmp = compare( prod, rem, prodL, remL );
-
-	                                // product > remainder.
-	                                if ( cmp == 1 ) {
-	                                    n--;
-
-	                                    // Subtract divisor from product.
-	                                    subtract( prod, yL < prodL ? yz : yc, prodL, base );
-	                                }
-	                            } else {
-
-	                                // cmp is -1.
-	                                // If n is 0, there is no need to compare yc and rem again below, so change cmp to 1 to avoid it.
-	                                // If n is 1 there IS a need to compare yc and rem again below.
-	                                if ( n == 0 ) {
-	                                    cmp = n = 1;
-	                                }
-	                                prod = yc.slice();
-	                            }
-	                            prodL = prod.length;
-
-	                            if ( prodL < remL ) {
-	                                prod.unshift(0);
-	                            }
-
-	                            // Subtract product from remainder.
-	                            subtract( rem, prod, remL, base );
-
-	                            // If product was < previous remainder.
-	                            if ( cmp == -1 ) {
-	                                remL = rem.length;
-
-	                                // Compare divisor and new remainder.
-	                                cmp = compare( yc, rem, yL, remL );
-
-	                                // If divisor < new remainder, subtract divisor from remainder.
-	                                if ( cmp < 1 ) {
-	                                    n++;
-
-	                                    // Subtract divisor from remainder.
-	                                    subtract( rem, yL < remL ? yz : yc, remL, base );
-	                                }
-	                            }
-
-	                            remL = rem.length;
-
-	                        } else if ( cmp === 0 ) {
-	                            n++;
-	                            rem = [0];
-	                        }    // if cmp === 1, n will be 0
-
-	                        // Add the next digit, n, to the result array.
-	                        qc[i++] = n;
-
-	                        // Update the remainder.
-	                        if ( cmp && rem[0] ) {
-	                            rem[remL++] = xc[xi] || 0;
-	                        } else {
-	                            rem = [ xc[xi] ];
-	                            remL = 1;
-	                        }
-
-	                    } while ( ( xi++ < xL || rem[0] != null ) && s-- );
-
-	                    more = rem[0] != null;
-	                }
-
-	                // Leading zero?
-	                if ( !qc[0] ) {
-	                    qc.shift();
-	                }
-	            }
-
-	            // If div is being used for base conversion.
-	            if ( logbase == 1 ) {
-	                q['e'] = e;
-	                q['r'] = +more;
-	            } else {
-
-	                // To calculate q.e, first get the number of digits of qc[0].
-	                for ( i = 1, s = qc[0]; s >= 10; s /= 10, i++ );
-	                q['e'] = i + e * logbase - 1;
-
-	                rnd( q, dp ? pr + q['e'] + 1 : pr, rm, more );
-	            }
-
-	            return q;
-	        };
-	    })();
-
-
-	    /*
-	     * Taylor/Maclaurin series.
-	     *
-	     * exp(x) = x^0/0! + x^1/1! + x^2/2! + x^3/3! + ...
-	     *
-	     * Argument reduction:
-	     *   Repeat x = x / 32, k += 5, until |x| < 0.1
-	     *   exp(x) = exp(x / 2^k)^(2^k)
-	     *
-	     * Previously, the argument was initially reduced by
-	     * exp(x) = exp(r) * 10^k  where r = x - k * ln10, k = floor(x / ln10)
-	     * to first put r in the range [0, ln10], before dividing by 32 until |x| < 0.1, but this was
-	     * found to be slower than just dividing repeatedly by 32 as above.
-	     *
-	     * Max integer argument: exp('20723265836946413') = 6.3e+9000000000000000
-	     * Min integer argument: exp('-20723265836946411') = 1.2e-9000000000000000
-	     * ( Math object integer min/max: Math.exp(709) = 8.2e+307, Math.exp(-745) = 5e-324 )
-	     *
-	     *  exp(Infinity)  = Infinity
-	     *  exp(-Infinity) = 0
-	     *  exp(NaN)       = NaN
-	     *  exp(+-0)       = 1
-	     *
-	     *  exp(x) is non-terminating for any finite, non-zero x.
-	     *
-	     *  The result will always be correctly rounded.
-	     *
-	     */
-	    function exp( x, pr ) {
-	        var denom, guard, j, pow, sd, sum, t,
-	            rep = 0,
-	            i = 0,
-	            k = 0,
-	            Decimal = x['constructor'],
-	            one = Decimal['ONE'],
-	            rm = Decimal['rounding'],
-	            precision = Decimal['precision'];
-
-	        // 0/NaN/Infinity?
-	        if ( !x['c'] || !x['c'][0] || x['e'] > 17 ) {
-
-	            return new Decimal( x['c']
-	              ? !x['c'][0] ? one : x['s'] < 0 ? 0 : 1 / 0
-	              : x['s'] ? x['s'] < 0 ? 0 : x : NaN );
-	        }
-
-	        if ( pr == null ) {
-
-	            /*
-	             Estimate result exponent.
-	             e^x = 10^j, where j = x * log10(e) and
-	             log10(e) = ln(e) / ln(10) = 1 / ln(10),
-	             so j = x / ln(10)
-	            j = mathfloor( x / Math.LN10 );
-
-	            // Overflow/underflow? Estimate may be +-1 of true value.
-	            if ( j > Decimal['maxE'] + 1 || j < Decimal['minE'] - 1 ) {
-
-	                return new Decimal( j > 0 ? 1 / 0 : 0 );
-	            }
-	             */
-
-	            external = false;
-	            sd = precision;
-	        } else {
-	            sd = pr;
-	        }
-
-	        t = new Decimal(0.03125);
-
-	        // while abs(x) >= 0.1
-	        while ( x['e'] > -2 ) {
-
-	            // x = x / 2^5
-	            x = x['times'](t);
-	            k += 5;
-	        }
-
-	        /*
-	         Use 2 * log10(2^k) + 5 to estimate the increase in precision necessary to ensure the first
-	         4 rounding digits are correct.
-	         */
-	        guard = Math.log( mathpow( 2, k ) ) / Math.LN10 * 2 + 5 | 0;
-	        sd += guard;
-
-	        denom = pow = sum = new Decimal(one);
-	        Decimal['precision'] = sd;
-
-	        for ( ; ; ) {
-	            pow = rnd( pow['times'](x), sd, 1 );
-	            denom = denom['times'](++i);
-	            t = sum['plus']( div( pow, denom, sd, 1 ) );
-
-	            if ( coefficientToString( t['c'] ).slice( 0, sd ) ===
-	                 coefficientToString( sum['c'] ).slice( 0, sd ) ) {
-	                j = k;
-
-	                while ( j-- ) {
-	                    sum = rnd( sum['times'](sum), sd, 1 );
-	                }
-
-	                /*
-	                 Check to see if the first 4 rounding digits are [49]999.
-	                 If so, repeat the summation with a higher precision, otherwise
-	                 E.g. with precision: 18, rounding: 1
-	                 exp(18.404272462595034083567793919843761) = 98372560.1229999999
-	                                           when it should be 98372560.123
-
-	                 sd - guard is the index of first rounding digit.
-	                 */
-	                if ( pr == null ) {
-
-	                    if ( rep < 3 && checkRoundingDigits( sum['c'], sd - guard, rm, rep ) ) {
-	                        Decimal['precision'] = sd += 10;
-	                        denom = pow = t = new Decimal(one);
-	                        i = 0;
-	                        rep++;
-	                    } else {
-
-	                        return rnd( sum, Decimal['precision'] = precision, rm, external = true );
-	                    }
-	                } else {
-	                    Decimal['precision'] = precision;
-
-	                    return sum;
-	                }
-	            }
-	            sum = t;
-	        }
-	    }
-
-
-	    /*
-	     * Return a string representing the value of Decimal n in normal or exponential notation
-	     * rounded to the specified decimal places or significant digits.
-	     * Called by toString, toExponential (k is 1), toFixed, and toPrecision (k is 2).
-	     * i is the index (with the value in normal notation) of the digit that may be rounded up.
-	     * j is the rounding mode, then the number of digits required including fraction-part trailing
-	     * zeros.
-	     */
-	    function format( n, i, j, k ) {
-	        var s, z,
-	            Decimal = n['constructor'],
-	            e = ( n = new Decimal(n) )['e'];
-
-	        // i == null when toExponential(no arg), or toString() when x >= toExpPos etc.
-	        if ( i == null ) {
-	            j = 0;
-	        } else {
-	            rnd( n, ++i, j );
-
-	            // If toFixed, n['e'] may have changed if the value was rounded up.
-	            j = k ? i : i + n['e'] - e;
-	        }
-
-	        e = n['e'];
-	        s = coefficientToString( n['c'] );
-
-	        /*
-	         toPrecision returns exponential notation if the number of significant digits specified
-	         is less than the number of digits necessary to represent the integer part of the value
-	         in normal notation.
-	         */
-
-	        // Exponential notation.
-	        if ( k == 1 || k == 2 && ( i <= e || e <= Decimal['toExpNeg'] ) ) {
-
-	            // Append zeros?
-	            for ( ; s.length < j; s += '0' );
-
-	            if ( s.length > 1 ) {
-	                s = s.charAt(0) + '.' + s.slice(1);
-	            }
-
-	            s += ( e < 0 ? 'e' : 'e+' ) + e;
-
-	        // Normal notation.
-	        } else {
-	            k = s.length;
-
-	            // Negative exponent?
-	            if ( e < 0 ) {
-	                z = j - k;
-
-	                // Prepend zeros.
-	                for ( ; ++e; s = '0' + s );
-	                s = '0.' + s;
-
-	            // Positive exponent?
-	            } else {
-
-	                if ( ++e > k ) {
-	                    z = j - e;
-
-	                    // Append zeros.
-	                    for ( e -= k; e-- ; s += '0' );
-
-	                    if ( z > 0 ) {
-	                        s += '.';
-	                    }
-
-	                } else {
-	                    z = j - k;
-
-	                    if ( e < k ) {
-	                        s = s.slice( 0, e ) + '.' + s.slice(e);
-	                    } else if ( z > 0 ) {
-	                        s += '.';
-	                    }
-	                }
-	            }
-
-	            // Append more zeros?
-	            if ( z > 0 ) {
-
-	                for ( ; z--; s += '0' );
-	            }
-	        }
-
-	        return n['s'] < 0 && n['c'][0] ? '-' + s : s;
-	    }
-
-
-	    function getCoeffLength(c) {
-	        var v = c.length - 1,
-	            n = v * LOGBASE + 1;
-
-	        if ( v = c[v] ) {
-
-	            // Subtract the number of trailing zeros of the last number.
-	            for ( ; v % 10 == 0; v /= 10, n-- );
-
-	            // Add the number of digits of the first number.
-	            for ( v = c[0]; v >= 10; v /= 10, n++ );
-	        }
-
-	        return n;
-	    }
-
-
-	    /*
-	     * Assemble error messages. Throw Decimal Errors.
-	     */
-	    function ifExceptionsThrow( Decimal, message, arg, method, more ) {
-
-	        if ( Decimal['errors'] ) {
-	            var error = new Error( ( method || [
-	              'new Decimal', 'cmp', 'div', 'eq', 'gt', 'gte', 'lt', 'lte', 'minus', 'mod',
-	              'plus', 'times', 'toFraction', 'pow', 'random', 'log', 'sqrt', 'toNearest', 'divToInt'
-	              ][ id ? id < 0 ? -id : id : 1 / id < 0 ? 1 : 0 ] ) + '() ' + ( [
-	              'number type has more than 15 significant digits', 'LN10 out of digits' ][message]
-	              || message + ( [ outOfRange ? ' out of range' : ' not an integer',
-	              ' not a boolean or binary digit' ][more] || '' ) ) + ': ' + arg
-	            );
-	            error['name'] = 'Decimal Error';
-	            outOfRange = id = 0;
-
-	            throw error;
-	        }
-	    }
-
-
-
-
-	    /*
-	     * Use 'exponentiation by squaring' for small integers. Called by convertBase and pow.
-	     */
-	    function intPow( Decimal, x, i ) {
-	        var r = new Decimal( Decimal['ONE'] );
-
-	        for ( external = false; ; ) {
-
-	            if ( i & 1 ) {
-	                r = r['times'](x);
-	            }
-	            i >>= 1;
-
-	            if ( !i ) {
-
-	                break;
-	            }
-	            x = x['times'](x);
-	        }
-	        external = true;
-
-	        return r;
-	    }
-
-
-	    /*
-	     *  ln(-n)        = NaN
-	     *  ln(0)         = -Infinity
-	     *  ln(-0)        = -Infinity
-	     *  ln(1)         = 0
-	     *  ln(Infinity)  = Infinity
-	     *  ln(-Infinity) = NaN
-	     *  ln(NaN)       = NaN
-	     *
-	     *  ln(n) (n != 1) is non-terminating.
-	     *
-	     */
-	    function ln( y, pr ) {
-	        var c, c0, denom, e, num, rep, sd, sum, t, x1, x2,
-	            n = 1,
-	            guard = 10,
-	            x = y,
-	            xc = x['c'],
-	            Decimal = x['constructor'],
-	            one = Decimal['ONE'],
-	            rm = Decimal['rounding'],
-	            precision = Decimal['precision'];
-
-	        // x < 0 or +-Infinity/NaN or 0 or 1.
-	        if ( x['s'] < 0 || !xc || !xc[0] || !x['e'] && xc[0] == 1 && xc.length == 1 ) {
-
-	            return new Decimal( xc && !xc[0] ? -1 / 0 : x['s'] != 1 ? NaN : xc ? 0 : x );
-	        }
-
-	        if ( pr == null ) {
-	            external = false;
-	            sd = precision;
-	        } else {
-	            sd = pr;
-	        }
-
-	        Decimal['precision'] = sd += guard;
-
-	        c = coefficientToString(xc);
-	        c0 = c.charAt(0);
-
-	        if ( Math.abs( e = x['e'] ) < 1.5e15 ) {
-
-	            /*
-	             Argument reduction.
-	             The series converges faster the closer the argument is to 1, so using
-	             ln(a^b) = b * ln(a),   ln(a) = ln(a^b) / b
-	             multiply the argument by itself until the leading digits of the significand are 7, 8,
-	             9, 10, 11, 12 or 13, recording the number of multiplications so the sum of the series
-	             can later be divided by this number, then separate out the power of 10 using
-	             ln(a*10^b) = ln(a) + b*ln(10).
-	             */
-
-	            // max n is 21 ( gives 0.9, 1.0 or 1.1 ) ( 9e15 / 21 = 4.2e14 ).
-	            //while ( c0 < 9 && c0 != 1 || c0 == 1 && c.charAt(1) > 1 ) {
-	            // max n is 6 ( gives 0.7 - 1.3 )
-	            while ( c0 < 7 && c0 != 1 || c0 == 1 && c.charAt(1) > 3 ) {
-	                x = x['times'](y);
-	                c = coefficientToString( x['c'] );
-	                c0 = c.charAt(0);
-	                n++;
-	            }
-
-	            e = x['e'];
-
-	            if ( c0 > 1 ) {
-	                x = new Decimal( '0.' + c );
-	                e++;
-	            } else {
-	                x = new Decimal( c0 + '.' + c.slice(1) );
-	            }
-	        } else {
-
-	            /*
-	             The argument reduction method above may result in overflow if the argument y is a
-	             massive number with exponent >= 1500000000000000 ( 9e15 / 6 = 1.5e15 ), so instead
-	             recall this function using ln(x*10^e) = ln(x) + e*ln(10).
-	             */
-	            x = new Decimal( c0 + '.' + c.slice(1) );
-
-	            if ( sd + 2 > LN10.length ) {
-	                ifExceptionsThrow( Decimal, 1, sd + 2, 'ln' );
-	            }
-
-	            x = ln( x, sd - guard )['plus'](
-	                new Decimal( LN10.slice( 0, sd + 2 ) )['times']( e + '' )
-	            );
-
-	            Decimal['precision'] = precision;
-
-	            return pr == null ? rnd( x, precision, rm, external = true ) : x;
-	        }
-
-	        // x1 is x reduced to a value near 1.
-	        x1 = x;
-
-	        /*
-	         Taylor series.
-	         ln(y) = ln( (1 + x)/(1 - x) ) = 2( x + x^3/3 + x^5/5 + x^7/7 + ... )
-	         where
-	         x = (y - 1)/(y + 1)              ( |x| < 1 )
-	         */
-	        sum = num = x = div( x['minus'](one), x['plus'](one), sd, 1 );
-	        x2 = rnd( x['times'](x), sd, 1 );
-	        denom = 3;
-
-	        for ( ; ; ) {
-	            num = rnd( num['times'](x2), sd, 1 );
-	            t = sum['plus']( div( num, new Decimal(denom), sd, 1 ) );
-
-	            if ( coefficientToString( t['c'] ).slice( 0, sd ) ===
-	                 coefficientToString( sum['c'] ).slice( 0, sd ) ) {
-	                sum = sum['times'](2);
-
-	                /*
-	                 Reverse the argument reduction. Check that e is not 0 because, as well as
-	                 preventing an unnecessary calculation, -0 + 0 = +0 and to ensure correct
-	                 rounding later -0 needs to stay -0.
-	                 */
-	                if ( e !== 0 ) {
-
-	                    if ( sd + 2 > LN10.length ) {
-	                        ifExceptionsThrow( Decimal, 1, sd + 2, 'ln' );
-	                    }
-
-	                    sum = sum['plus'](
-	                        new Decimal( LN10.slice( 0, sd + 2 ) )['times']( e + '' )
-	                    );
-	                }
-
-	                sum = div( sum, new Decimal(n), sd, 1 );
-
-	                /*
-	                 Is rm > 3 and the first 4 rounding digits 4999, or rm < 4 (or the summation has
-	                 been repeated previously) and the first 4 rounding digits 9999?
-
-	                 If so, restart the summation with a higher precision, otherwise
-	                 e.g. with precision: 12, rounding: 1
-	                 ln(135520028.6126091714265381533) = 18.7246299999 when it should be 18.72463.
-
-	                 sd - guard is the index of first rounding digit.
-	                 */
-	                if ( pr == null ) {
-
-	                    if ( checkRoundingDigits( sum['c'], sd - guard, rm, rep ) ) {
-	                        Decimal['precision'] = sd += guard;
-	                        t = num = x = div( x1['minus'](one), x1['plus'](one), sd, 1 );
-	                        x2 = rnd( x['times'](x), sd, 1 );
-	                        denom = rep = 1;
-	                    } else {
-
-	                        return rnd( sum, Decimal['precision'] = precision, rm, external = true );
-	                    }
-	                } else {
-	                    Decimal['precision'] = precision;
-
-	                    return sum;
-	                }
-	            }
-
-	            sum = t;
-	            denom += 2;
-	        }
-	    }
-
-
-	    /*
-	     * Round x to sd significant digits using rounding mode rm. Check for over/under-flow.
-	     */
-	     function rnd( x, sd, rm, r ) {
-	        var digits, i, j, k, n, rd, xc, xci,
-	            Decimal = x['constructor'];
-
-	        // Don't round if sd is null or undefined.
-	        out: if ( sd != null ) {
-
-	            // Infinity/NaN.
-	            if ( !( xc = x['c'] ) ) {
-
-	                return x;
-	            }
-
-	            /*
-	             rd, the rounding digit, i.e. the digit after the digit that may be rounded up,
-	             n, a base 1e7 number, the element of xc containing rd,
-	             xci, the index of n within xc,
-	             digits, the number of digits of n,
-	             i, what would be the index of rd within n if all the numbers were 7 digits long (i.e. they had leading zeros)
-	             j, if > 0, the actual index of rd within n (if < 0, rd is a leading zero),
-	             nLeadingZeros, the number of leading zeros n would have if it were 7 digits long.
-	             */
-
-	            // Get the length of the first element of the coefficient array xc.
-	            for ( digits = 1, k = xc[0]; k >= 10; k /= 10, digits++ );
-
-	            i = sd - digits;
-
-	            // Is the rounding digit in the first element of xc?
-	            if ( i < 0 ) {
-	                i += LOGBASE;
-	                j = sd;
-	                n = xc[ xci = 0 ];
-
-	                // Get the rounding digit at index j of n.
-	                rd = n / mathpow( 10, digits - j - 1 ) % 10 | 0;
-	            } else {
-	                xci = Math.ceil( ( i + 1 ) / LOGBASE );
-
-	                if ( xci >= xc.length ) {
-
-	                    if (r) {
-
-	                        // Needed by exp, ln and sqrt.
-	                        for ( ; xc.length <= xci; xc.push(0) );
-
-	                        n = rd = 0;
-	                        digits = 1;
-	                        i %= LOGBASE;
-	                        j = i - LOGBASE + 1;
-	                    } else {
-
-	                      break out;
-	                    }
-	                } else {
-	                    n = k = xc[xci];
-
-	                    // Get the number of digits of n.
-	                    for ( digits = 1; k >= 10; k /= 10, digits++ );
-
-	                    // Get the index of rd within n.
-	                    i %= LOGBASE;
-
-	                    // Get the index of rd within n, adjusted for leading zeros.
-	                    // The number of leading zeros of n is given by LOGBASE - digits.
-	                    j = i - LOGBASE + digits;
-
-	                    // Get the rounding digit at index j of n.
-	                    // Floor using Math.floor instead of | 0 as rd may be outside int range.
-	                    rd = j < 0 ? 0 : mathfloor( n / mathpow( 10, digits - j - 1 ) % 10 );
-	                }
-	            }
-
-	            r = r || sd < 0 ||
-	              // Are there any non-zero digits after the rounding digit?
-	              xc[xci + 1] != null || ( j < 0 ? n : n % mathpow( 10, digits - j - 1 ) );
-
-	            /*
-	             The expression  n % mathpow( 10, digits - j - 1 )  returns all the digits of n to the
-	             right of the digit at (left-to-right) index j,
-	             e.g. if n is 908714 and j is 2, the expression will give 714.
-	             */
-
-	            r = rm < 4
-	              ? ( rd || r ) && ( rm == 0 || rm == ( x['s'] < 0 ? 3 : 2 ) )
-	              : rd > 5 || rd == 5 && ( rm == 4 || r ||
-	                // Check whether the digit to the left of the rounding digit is odd.
-	                rm == 6 && ( ( i > 0 ? j > 0 ? n / mathpow( 10, digits - j ) : 0 : xc[xci - 1] ) % 10 ) & 1 ||
-	                  rm == ( x['s'] < 0 ? 8 : 7 ) );
-
-	            if ( sd < 1 || !xc[0] ) {
-	                xc.length = 0;
-
-	                if (r) {
-
-	                    // Convert sd to decimal places.
-	                    sd -= x['e'] + 1;
-
-	                    // 1, 0.1, 0.01, 0.001, 0.0001 etc.
-	                    xc[0] = mathpow( 10, ( LOGBASE - sd % LOGBASE ) % LOGBASE );
-	                    x['e'] = -sd || 0;
-	                } else {
-
-	                    // Zero.
-	                    xc[0] = x['e'] = 0;
-	                }
-
-	                return x;
-	            }
-
-	            // Remove excess digits.
-
-	            if ( i == 0 ) {
-	                xc.length = xci;
-	                k = 1;
-	                xci--;
-	            } else {
-	                xc.length = xci + 1;
-	                k = mathpow( 10, LOGBASE - i );
-
-	                // E.g. 56700 becomes 56000 if 7 is the rounding digit.
-	                // j > 0 means i > number of leading zeros of n.
-	                xc[xci] = j > 0 ? ( n / mathpow( 10, digits - j ) % mathpow( 10, j ) | 0 ) * k : 0;
-	            }
-
-	            // Round up?
-	            if (r) {
-
-	                for ( ; ; ) {
-
-	                    // Is the digit to be rounded up in the first element of xc?
-	                    if ( xci == 0 ) {
-
-	                        // i will be the length of xc[0] before k is added.
-	                        for ( i = 1, j = xc[0]; j >= 10; j /= 10, i++ );
-
-	                        j = xc[0] += k;
-
-	                        for ( k = 1; j >= 10; j /= 10, k++ );
-
-	                        // if i != k the length has increased.
-	                        if ( i != k ) {
-	                            x['e']++;
-
-	                            if ( xc[0] == BASE ) {
-	                                xc[0] = 1;
-	                            }
-	                        }
-
-	                        break;
-	                    } else {
-	                        xc[xci] += k;
-
-	                        if ( xc[xci] != BASE ) {
-
-	                            break;
-	                        }
-
-	                        xc[xci--] = 0;
-	                        k = 1;
-	                    }
-	                }
-	            }
-
-	            // Remove trailing zeros.
-	            for ( i = xc.length; xc[--i] === 0; xc.pop() );
-	        }
-
-	        if (external) {
-
-	            // Overflow?
-	            if ( x['e'] > Decimal['maxE'] ) {
-
-	                // Infinity.
-	                x['c'] = x['e'] = null;
-
-	            // Underflow?
-	            } else if ( x['e'] < Decimal['minE'] ) {
-
-	                // Zero.
-	                x['c'] = [ x['e'] = 0 ];
-	            }
-	        }
-
-	        return x;
-	    }
-
-
-	    decimal = (function () {
-
-
-	        // Private functions used by static Decimal methods.
-
-
-	        /*
-	         *  The following emulations or wrappers of Math object functions are currently
-	         *  commented-out and not in the public API.
-	         *
-	         *  abs
-	         *  acos
-	         *  asin
-	         *  atan
-	         *  atan2
-	         *  ceil
-	         *  cos
-	         *  floor
-	         *  round
-	         *  sin
-	         *  tan
-	         *  trunc
-	         */
-
-
-	        /*
-	         * Return a new Decimal whose value is the absolute value of n.
-	         *
-	         * n {number|string|Decimal}
-	         *
-	        function abs(n) { return new this(n)['abs']() }
-	         */
-
-
-	        /*
-	         * Return a new Decimal whose value is the arccosine in radians of n.
-	         *
-	         * n {number|string|Decimal}
-	         *
-	        function acos(n) { return new this( Math.acos(n) + '' ) }
-	         */
-
-
-	        /*
-	         * Return a new Decimal whose value is the arcsine in radians of n.
-	         *
-	         * n {number|string|Decimal}
-	         *
-	        function asin(n) { return new this( Math.asin(n) + '' ) }
-	         */
-
-
-	        /*
-	         * Return a new Decimal whose value is the arctangent in radians of n.
-	         *
-	         * n {number|string|Decimal}
-	         *
-	        function atan(n) { return new this( Math.atan(n) + '' ) }
-	         */
-
-
-	        /*
-	         * Return a new Decimal whose value is the arctangent in radians of y/x in the range
-	         * -PI to PI (inclusive).
-	         *
-	         * y {number|string|Decimal} The y-coordinate.
-	         * x {number|string|Decimal} The x-coordinate.
-	         *
-	        function atan2( y, x ) { return new this( Math.atan2( y, x ) + '' ) }
-	         */
-
-
-	        /*
-	         * Return a new Decimal whose value is n round to an integer using ROUND_CEIL.
-	         *
-	         * n {number|string|Decimal}
-	         *
-	        function ceil(n) { return new this(n)['ceil']() }
-	         */
-
-
-	        /*
-	         * Configure global settings for a Decimal constructor.
-	         *
-	         * obj is an object with any of the following properties,
-	         *
-	         *   precision  {number}
-	         *   rounding   {number}
-	         *   toExpNeg   {number}
-	         *   toExpPos   {number}
-	         *   minE       {number}
-	         *   maxE       {number}
-	         *   errors     {boolean|number}
-	         *   crypto     {boolean|number}
-	         *   modulo     {number}
-	         *
-	         *   format     {object}     See Decimal.prototype.toFormat
-	         *      decimalSeparator       {string}
-	         *      groupSeparator         {string}
-	         *      groupSize              {number}
-	         *      secondaryGroupSize     {number}
-	         *      fractionGroupSeparator {string}
-	         *      fractionGroupSize      {number}
-	         *
-	         *   A format object will replace the existing Decimal.format object without any property
-	         *   checking.
-	         *
-	         * E.g.
-	         *   Decimal.config({ precision: 20, rounding: 4 })
-	         *
-	         */
-	        function config(obj) {
-	            var p, u, v,
-	                Decimal = this,
-	                c = 'config',
-	                parse = Decimal['errors'] ? parseInt : parseFloat;
-
-	            if ( obj == u || typeof obj != 'object' &&
-	              // 'config() object expected: {obj}'
-	              !ifExceptionsThrow( Decimal, 'object expected', obj, c ) ) {
-
-	                return Decimal;
-	            }
-
-	            // precision {number} Integer, 1 to MAX_DIGITS inclusive.
-	            if ( ( v = obj[ p = 'precision' ] ) != u ) {
-
-	                if ( !( outOfRange = v < 1 || v > MAX_DIGITS ) && parse(v) == v ) {
-	                    Decimal[p] = v | 0;
-	                } else {
-
-	                    // 'config() precision not an integer: {v}'
-	                    // 'config() precision out of range: {v}'
-	                    ifExceptionsThrow( Decimal, p, v, c, 0 );
-	                }
-	            }
-
-	            // rounding {number} Integer, 0 to 8 inclusive.
-	            if ( ( v = obj[ p = 'rounding' ] ) != u ) {
-
-	                if ( !( outOfRange = v < 0 || v > 8 ) && parse(v) == v ) {
-	                    Decimal[p] = v | 0;
-	                } else {
-
-	                    // 'config() rounding not an integer: {v}'
-	                    // 'config() rounding out of range: {v}'
-	                    ifExceptionsThrow( Decimal, p, v, c, 0 );
-	                }
-	            }
-
-	            // toExpNeg {number} Integer, -EXP_LIMIT to 0 inclusive.
-	            if ( ( v = obj[ p = 'toExpNeg' ] ) != u ) {
-
-	                if ( !( outOfRange = v < -EXP_LIMIT || v > 0 ) && parse(v) == v ) {
-	                    Decimal[p] = mathfloor(v);
-	                } else {
-
-	                    // 'config() toExpNeg not an integer: {v}'
-	                    // 'config() toExpNeg out of range: {v}'
-	                    ifExceptionsThrow( Decimal, p, v, c, 0 );
-	                }
-	            }
-
-	            // toExpPos {number} Integer, 0 to EXP_LIMIT inclusive.
-	            if ( ( v = obj[ p = 'toExpPos' ] ) != u ) {
-
-	                if ( !( outOfRange = v < 0 || v > EXP_LIMIT ) && parse(v) == v ) {
-	                    Decimal[p] = mathfloor(v);
-	                } else {
-
-	                    // 'config() toExpPos not an integer: {v}'
-	                    // 'config() toExpPos out of range: {v}'
-	                    ifExceptionsThrow( Decimal, p, v, c, 0 );
-	                }
-	            }
-
-	             // minE {number} Integer, -EXP_LIMIT to 0 inclusive.
-	            if ( ( v = obj[ p = 'minE' ] ) != u ) {
-
-	                if ( !( outOfRange = v < -EXP_LIMIT || v > 0 ) && parse(v) == v ) {
-	                    Decimal[p] = mathfloor(v);
-	                } else {
-
-	                    // 'config() minE not an integer: {v}'
-	                    // 'config() minE out of range: {v}'
-	                    ifExceptionsThrow( Decimal, p, v, c, 0 );
-	                }
-	            }
-
-	            // maxE {number} Integer, 0 to EXP_LIMIT inclusive.
-	            if ( ( v = obj[ p = 'maxE' ] ) != u ) {
-
-	                if ( !( outOfRange = v < 0 || v > EXP_LIMIT ) && parse(v) == v ) {
-	                    Decimal[p] = mathfloor(v);
-	                } else {
-
-	                    // 'config() maxE not an integer: {v}'
-	                    // 'config() maxE out of range: {v}'
-	                    ifExceptionsThrow( Decimal, p, v, c, 0 );
-	                }
-	            }
-
-	            // errors {boolean|number} true, false, 1 or 0.
-	            if ( ( v = obj[ p = 'errors' ] ) != u ) {
-
-	                if ( v === !!v || v === 1 || v === 0 ) {
-	                    outOfRange = id = 0;
-	                    Decimal[p] = !!v;
-	                } else {
-
-	                    // 'config() errors not a boolean or binary digit: {v}'
-	                    ifExceptionsThrow( Decimal, p, v, c, 1 );
-	                }
-	            }
-
-	            // crypto {boolean|number} true, false, 1 or 0.
-	            if ( ( v = obj[ p = 'crypto' ] ) != u ) {
-
-	                if ( v === !!v || v === 1 || v === 0 ) {
-	                    Decimal[p] = !!( v && crypto && typeof crypto == 'object' );
-	                } else {
-
-	                    // 'config() crypto not a boolean or binary digit: {v}'
-	                    ifExceptionsThrow( Decimal, p, v, c, 1 );
-	                }
-	            }
-
-	            // modulo {number} Integer, 0 to 9 inclusive.
-	            if ( ( v = obj[ p = 'modulo' ] ) != u ) {
-
-	                if ( !( outOfRange = v < 0 || v > 9 ) && parse(v) == v ) {
-	                    Decimal[p] = v | 0;
-	                } else {
-
-	                    // 'config() modulo not an integer: {v}'
-	                    // 'config() modulo out of range: {v}'
-	                    ifExceptionsThrow( Decimal, p, v, c, 0 );
-	                }
-	            }
-
-	            // format {object}
-	            if ( ( obj = obj[ p = 'format' ] ) != u ) {
-
-	                if ( typeof obj == 'object' ) {
-	                    Decimal[p] = obj;
-	                } else {
-
-	                    // 'config() format object expected: {obj}'
-	                    ifExceptionsThrow( Decimal, 'format object expected', obj, c );
-	                }
-	            }
-
-	            return Decimal;
-	        }
-
-
-	        /*
-	         * Return a new Decimal whose value is the cosine of n.
-	         *
-	         * n {number|string|Decimal} A number given in radians.
-	         *
-	        function cos(n) { return new this( Math.cos(n) + '' ) }
-	         */
-
-
-	        /*
-	         * Return a new Decimal whose value is the exponential of n,
-	         *
-	         * n {number|string|Decimal} The power to which to raise the base of the natural log.
-	         *
-	         */
-	        function exp(n) { return new this(n)['exp'](); }
-
-
-	        /*
-	         * Return a new Decimal whose value is n round to an integer using ROUND_FLOOR.
-	         *
-	         * n {number|string|Decimal}
-	         *
-	        function floor(n) { return new this(n)['floor']() }
-	         */
-
-
-
-
-	        /*
-	         * Return a new Decimal whose value is the natural logarithm of n.
-	         *
-	         * n {number|string|Decimal}
-	         *
-	         */
-	        function ln(n) { return new this(n)['ln'](); }
-
-
-	        /*
-	         * Return a new Decimal whose value is the log of x to the base y, or to base 10 if no
-	         * base is specified.
-	         *
-	         * log[y](x)
-	         *
-	         * x {number|string|Decimal} The argument of the logarithm.
-	         * y {number|string|Decimal} The base of the logarithm.
-	         *
-	         */
-	        function log( x, y ) { return new this(x)['log'](y); }
-
-
-	        /*
-	         * Handle max and min. ltgt is 'lt' or 'gt'.
-	         */
-	        function maxOrMin( Decimal, args, ltgt ) {
-	            var m, n,
-	                i = 0;
-
-	            if ( toString.call( args[0] ) == '[object Array]' ) {
-	                args = args[0];
-	            }
-
-	            m = new Decimal( args[0] );
-
-	            for ( ; ++i < args.length; ) {
-	                n = new Decimal( args[i] );
-
-	                if ( !n['s'] ) {
-	                    m = n;
-
-	                    break;
-	                } else if ( m[ltgt](n) ) {
-	                    m = n;
-	                }
-	            }
-
-	            return m;
-	        }
-
-
-	        /*
-	         * Return a new Decimal whose value is the maximum of the arguments.
-	         *
-	         * arguments {number|string|Decimal}
-	         *
-	         */
-	        function max() { return maxOrMin( this, arguments, 'lt' ); }
-
-
-	        /*
-	         * Return a new Decimal whose value is the minimum of the arguments.
-	         *
-	         * arguments {number|string|Decimal}
-	         *
-	         */
-	        function min() { return maxOrMin( this, arguments, 'gt' ); }
-
-
-	        /*
-	         * Parse the value of a new Decimal from a number or string.
-	         */
-	        var parseDecimal = (function () {
-	            var isValid = /^-?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,
-	                trim = String.prototype.trim ||
-	                  function () { return this.replace(/^\s+|\s+$/g, ''); };
-
-	            return function ( Decimal, x, n, b ) {
-	                var d, e, i, isNum, orig, valid;
-
-	                if ( typeof n != 'string' ) {
-
-	                    // If n is a number, check if minus zero.
-	                    n = ( isNum = typeof n == 'number' || toString.call(n) == '[object Number]' ) &&
-	                        n === 0 && 1 / n < 0 ? '-0' : n + '';
-	                }
-	                orig = n;
-
-	                if ( b == null && isValid.test(n) ) {
-
-	                    // Determine sign.
-	                    x['s'] = n.charCodeAt(0) === 45 ? ( n = n.slice(1), -1 ) : 1;
-
-	                // Either n is not a valid Decimal or a base has been specified.
-	                } else {
-
-	                    /*
-	                     Enable exponential notation to be used with base 10 argument.
-	                     Ensure return value is rounded to precision as with other bases.
-	                     */
-	                    if ( b == 10 ) {
-
-	                        return rnd( new Decimal(n), Decimal['precision'], Decimal['rounding'] );
-	                    }
-
-	                    n = trim.call(n).replace( /^\+(?!-)/, '' );
-
-	                    x['s'] = n.charCodeAt(0) === 45 ? ( n = n.replace( /^-(?!-)/, '' ), -1 ) : 1;
-
-	                    if ( b != null ) {
-
-	                        if ( ( b == (b | 0) || !Decimal['errors'] ) &&
-	                          !( outOfRange = !( b >= 2 && b < 65 ) ) ) {
-	                            d = '[' + NUMERALS.slice( 0, b = b | 0 ) + ']+';
-
-	                           // Remove the `.` from e.g. '1.', and replace e.g. '.1' with '0.1'.
-	                            n = n.replace( /\.$/, '' ).replace( /^\./, '0.' );
-
-	                            // Any number in exponential form will fail due to the e+/-.
-	                            if ( valid = new RegExp(
-	                              '^' + d + '(?:\\.' + d + ')?$', b < 37 ? 'i' : '' ).test(n) ) {
-
-	                                if (isNum) {
-
-	                                    if ( n.replace( /^0\.0*|\./, '' ).length > 15 ) {
-
-	                                        // '{method} number type has more than 15 significant digits: {n}'
-	                                        ifExceptionsThrow( Decimal, 0, orig );
-	                                    }
-
-	                                    // Prevent later check for length on converted number.
-	                                    isNum = !isNum;
-	                                }
-	                                n = convertBase( Decimal, n, 10, b, x['s'] );
-
-	                            } else if ( n != 'Infinity' && n != 'NaN' ) {
-
-	                                // '{method} not a base {b} number: {n}'
-	                                ifExceptionsThrow( Decimal, 'not a base ' + b + ' number', orig );
-	                                n = 'NaN';
-	                            }
-	                        } else {
-
-	                            // '{method} base not an integer: {b}'
-	                            // '{method} base out of range: {b}'
-	                            ifExceptionsThrow( Decimal, 'base', b, 0, 0 );
-
-	                            // Ignore base.
-	                            valid = isValid.test(n);
-	                        }
-	                    } else {
-	                        valid = isValid.test(n);
-	                    }
-
-	                    if ( !valid ) {
-
-	                        // Infinity/NaN
-	                        x['c'] = x['e'] = null;
-
-	                        // NaN
-	                        if ( n != 'Infinity' ) {
-
-	                            // No exception on NaN.
-	                            if ( n != 'NaN' ) {
-
-	                                // '{method} not a number: {n}'
-	                                ifExceptionsThrow( Decimal, 'not a number', orig );
-	                            }
-	                            x['s'] = null;
-	                        }
-	                        id = 0;
-
-	                        return x;
-	                    }
-	                }
-
-	                // Decimal point?
-	                if ( ( e = n.indexOf('.') ) > -1 ) {
-	                    n = n.replace( '.', '' );
-	                }
-
-	                // Exponential form?
-	                if ( ( i = n.search(/e/i) ) > 0 ) {
-
-	                    // Determine exponent.
-	                    if ( e < 0 ) {
-	                        e = i;
-	                    }
-	                    e += +n.slice( i + 1 );
-	                    n = n.substring( 0, i );
-
-	                } else if ( e < 0 ) {
-
-	                    // Integer.
-	                    e = n.length;
-	                }
-
-	                // Determine leading zeros.
-	                for ( i = 0; n.charCodeAt(i) === 48; i++ );
-
-	                // Determine trailing zeros.
-	                for ( b = n.length; n.charCodeAt(--b) === 48; );
-
-	                n = n.slice( i, b + 1 );
-
-	                if (n) {
-	                    b = n.length;
-
-	                    // Disallow numbers with over 15 significant digits if number type.
-	                    if ( isNum && b > 15 ) {
-
-	                        // '{method} number type has more than 15 significant digits: {n}'
-	                        ifExceptionsThrow( Decimal, 0, orig );
-	                    }
-
-	                    x['e'] = e = e - i - 1;
-	                    x['c'] = [];
-
-	                    // Transform base
-
-	                    // e is the base 10 exponent.
-	                    // i is where to slice n to get the first element of the coefficient array.
-	                    i = ( e + 1 ) % LOGBASE;
-
-	                    if ( e < 0 ) {
-	                        i += LOGBASE;
-	                    }
-
-	                    // b is n.length.
-	                    if ( i < b ) {
-
-	                        if (i) {
-	                            x['c'].push( +n.slice( 0, i ) );
-	                        }
-
-	                        for ( b -= LOGBASE; i < b; ) {
-                                // UCA: Fix left-to-right execution of function arguments
-                                // https://github.com/MikeMcl/decimal.js/issues/15#issuecomment-97339343
-                                var next = i + LOGBASE;
-                                x['c'].push( +n.slice( i, next ) );
-                                i = next;
-	                        }
-
-	                        n = n.slice(i);
-	                        i = LOGBASE - n.length;
-	                    } else {
-	                        i -= b;
-	                    }
-
-	                    for ( ; i--; n += '0' );
-
-	                    x['c'].push( +n );
-
-	                    if (external) {
-
-	                        // Overflow?
-	                        if ( x['e'] > Decimal['maxE'] ) {
-
-	                            // Infinity.
-	                            x['c'] = x['e'] = null;
-
-	                        // Underflow?
-	                        } else if ( x['e'] < Decimal['minE'] ) {
-
-	                            // Zero.
-	                            x['c'] = [ x['e'] = 0 ];
-	                        }
-	                    }
-	                } else {
-
-	                    // Zero.
-	                    x['c'] = [ x['e'] = 0 ];
-	                }
-	                id = 0;
-
-	                return x;
-	            };
-	        })();
-
-
-	        /*
-	         * Return a new Decimal whose value is x raised to the power y.
-	         *
-	         * x {number|string|Decimal} The base.
-	         * y {number|string|Decimal} The exponent.
-	         *
-	         */
-	        function pow( x, y ) { return new this(x)['pow'](y); }
-
-
-	        /*
-	         * Returns a new Decimal with a random value equal to or greater than 0 and less than 1, and
-	         * with dp, or Decimal.precision if dp is omitted, decimal places (or less if trailing
-	         * zeros are produced).
-	         *
-	         * [dp] {number} Decimal places. Integer, 0 to MAX_DIGITS inclusive.
-	         *
-	         */
-	        function random(dp) {
-	            var a, n, v,
-	                i = 0,
-	                r = [],
-	                Decimal = this,
-	                rand = new Decimal( Decimal['ONE'] );
-
-	            if ( dp == null || !checkArg( rand, dp, 'random' ) ) {
-	                dp = Decimal['precision'];
-	            } else {
-	                dp |= 0;
-	            }
-
-	            n = Math.ceil( dp / LOGBASE );
-
-	            if ( Decimal['crypto'] ) {
-
-	                // Browsers supporting crypto.getRandomValues.
-	                if ( crypto && crypto['getRandomValues'] ) {
-
-	                    a = crypto['getRandomValues']( new Uint32Array(n) );
-
-	                    for ( ; i < n; ) {
-	                        v = a[i];
-
-	                        // 0 <= v < 4294967296
-	                        // Probability that v >= 4.29e9, is 4967296 / 4294967296 = 0.00116 (1 in 865).
-	                        if ( v >= 4.29e9 ) {
-
-	                            a[i] = crypto['getRandomValues']( new Uint32Array(1) )[0];
-	                        } else {
-
-	                            // 0 <= v <= 4289999999
-	                            // 0 <= ( v % 1e7 ) <= 9999999
-	                            r[i++] = v % 1e7;
-	                        }
-	                    }
-
-	                // Node.js supporting crypto.randomBytes.
-	                } else if ( crypto && crypto['randomBytes'] ) {
-
-	                    // buffer
-	                    a = crypto['randomBytes']( n *= 4 );
-
-	                    for ( ; i < n; ) {
-
-	                        // 0 <= v < 2147483648
-	                        v = a[i] + ( a[i + 1] << 8 ) + ( a[i + 2] << 16 ) +
-	                            ( ( a[i + 3] & 0x7f ) << 24 );
-
-	                        // Probability that v >= 2.14e9, is 7483648 / 2147483648 = 0.0035 (1 in 286).
-	                        if ( v >= 2.14e9 ) {
-	                            crypto['randomBytes'](4).copy( a, i );
-	                        } else {
-
-	                            // 0 <= v <= 2139999999
-	                            // 0 <= ( v % 1e7 ) <= 9999999
-	                            r.push( v % 1e7 );
-	                            i += 4;
-	                        }
-	                    }
-	                    i = n / 4;
-
-	                } else {
-	                    ifExceptionsThrow( Decimal, 'crypto unavailable', crypto, 'random' );
-	                }
-	            }
-
-	            // Use Math.random: either Decimal.crypto is false or crypto is unavailable and errors is false.
-	            if (!i) {
-
-	                for ( ; i < n; ) {
-	                    r[i++] = Math.random() * 1e7 | 0;
-	                }
-	            }
-
-	            n = r[--i];
-	            dp %= LOGBASE;
-
-	            // Convert trailing digits to zeros according to dp.
-	            if ( n && dp ) {
-	                v = mathpow( 10, LOGBASE - dp );
-	                r[i] = ( n / v | 0 ) * v;
-	            }
-
-	            // Remove trailing elements which are zero.
-	            for ( ; r[i] === 0; i-- ) {
-	                r.pop();
-	            }
-
-	            // Zero?
-	            if ( i < 0 ) {
-	                r = [ n = 0 ];
-	            } else {
-	                n = -1;
-
-	                // Remove leading elements which are zero and adjust exponent accordingly.
-	                for ( ; r[0] === 0; ) {
-	                    r.shift();
-	                    n -= LOGBASE;
-	                }
-
-	                // Count the digits of the first element of r to determine leading zeros.
-	                for ( i = 1, v = r[0]; v >= 10; ) {
-	                    v /= 10;
-	                    i++;
-	                }
-
-	                // Adjust the exponent for leading zeros of the first element of r.
-	                if ( i < LOGBASE ) {
-	                    n -= LOGBASE - i;
-	                }
-	            }
-
-	            rand['e'] = n;
-	            rand['c'] = r;
-
-	            return rand;
-	        }
-
-
-	        /*
-	         * Return a new Decimal whose value is n round to an integer using rounding mode rounding.
-	         *
-	         * To emulate Math.round, set rounding to 7 (ROUND_HALF_CEIL).
-	         *
-	         * n {number|string|Decimal}
-	         *
-	        function round(n) {
-	            var x = new this(n);
-
-	            return rnd( x, x['e'] + 1, this['rounding'] );
-	        }
-	         */
-
-
-	        /*
-	         * Return a new Decimal whose value is the sine of n.
-	         *
-	         * n {number|string|Decimal} A number given in radians.
-	         *
-	        function sin(n) { return new this( Math.sin(n) + '' ) }
-	         */
-
-
-	        /*
-	         * Return a new Decimal whose value is the square root of n.
-	         *
-	         * n {number|string|Decimal}
-	         *
-	         */
-	        function sqrt(n) { return new this(n)['sqrt'](); }
-
-
-	        /*
-	         * Return a new Decimal whose value is the tangent of n.
-	         *
-	         * n {number|string|Decimal} A number given in radians.
-	         *
-	        function tan(n) { return new this( Math.tan(n) + '' ) }
-	         */
-
-
-	        /*
-	         * Return a new Decimal whose value is n truncated to an integer.
-	         *
-	         * n {number|string|Decimal}
-	         *
-	        function trunc(n) { return new this(n)['trunc']() }
-	         */
-
-
-	        /*
-	         * Create and return a Decimal constructor.
-	         *
-	         */
-	        function decimalFactory(obj) {
-
-	            /*
-	             * The Decimal constructor and exported function.
-	             * Create and return a new instance of a Decimal object.
-	             *
-	             * n {number|string|Decimal} A numeric value.
-	             * [b] {number} The base of n. Integer, 2 to 64 inclusive.
-	             *
-	             */
-	            function Decimal( n, b ) {
-	                var x = this;
-
-	                // Constructor called without new.
-	                if ( !( x instanceof Decimal ) ) {
-	                    ifExceptionsThrow( Decimal, 'Decimal called without new', n );
-
-	                    return new Decimal( n, b );
-	                }
-
-	                // Retain a reference to this Decimal constructor, and shadow
-	                // Decimal.prototype.constructor which points to Object.
-	                x['constructor'] = Decimal;
-
-	                // Duplicate.
-	                if ( n instanceof Decimal ) {
-
-	                    if ( b == null ) {
-	                        id = 0;
-	                        x['s'] = n['s'];
-	                        x['e'] = n['e'];
-	                        x['c'] = ( n = n['c'] ) ? n.slice() : n;
-
-	                        return x;
-	                    } else if ( b == 10 ) {
-
-	                        return rnd( new Decimal(n), Decimal['precision'], Decimal['rounding'] );
-	                    } else {
-	                        n += '';
-	                    }
-	                }
-
-	                return parseDecimal( Decimal, x, n, b );
-	            }
-
-
-	            /* ************************ CONSTRUCTOR DEFAULT PROPERTIES ************************** */
-
-	            /*
-	             These default values must be integers within the stated ranges (inclusive).
-	             Most of these values can be changed during run-time using Decimal.config.
-	             */
-
-	            /*
-	             The maximum number of significant digits of the result of a calculation or base
-	             conversion.
-	             E.g.  Decimal.config({ precision: 20 })
-	             */
-	            Decimal['precision'] = 20;                        // 1 to MAX_DIGITS
-
-	            /*
-	             The rounding mode used when rounding to precision.
-
-	             ROUND_UP         0 Away from zero.
-	             ROUND_DOWN       1 Towards zero.
-	             ROUND_CEIL       2 Towards +Infinity.
-	             ROUND_FLOOR      3 Towards -Infinity.
-	             ROUND_HALF_UP    4 Towards nearest neighbour. If equidistant, up.
-	             ROUND_HALF_DOWN  5 Towards nearest neighbour. If equidistant, down.
-	             ROUND_HALF_EVEN  6 Towards nearest neighbour. If equidistant, towards even neighbour.
-	             ROUND_HALF_CEIL  7 Towards nearest neighbour. If equidistant, towards +Infinity.
-	             ROUND_HALF_FLOOR 8 Towards nearest neighbour. If equidistant, towards -Infinity.
-
-	             E.g.
-	             Decimal.rounding = 4;
-	             Decimal.rounding = Decimal.ROUND_HALF_UP;
-	             */
-	            Decimal['rounding'] = 4;                          // 0 to 8
-
-	            /*
-	             The modulo mode used when calculating the modulus: a mod n.
-	             The quotient (q = a / n) is calculated according to the corresponding rounding mode.
-	             The remainder (r) is calculated as: r = a - n * q.
-
-	             UP         0 The remainder is positive if the dividend is negative, else is negative.
-	             DOWN       1 The remainder has the same sign as the dividend.
-	                          This modulo mode is commonly known as "truncated division" and matches
-	                          as closely as possible, the behaviour of JS remainder operator (a % n).
-	             FLOOR      3 The remainder has the same sign as the divisor (Python %).
-	             HALF_EVEN  6 This modulo mode implements the IEEE 754 remainder function.
-	             EUCLID     9 Euclidian division. q = sign(n) * floor(a / abs(n)).
-	                          The remainder is always positive.
-
-	             The above modes - truncated division, floored division, Euclidian division and IEEE 754
-	             remainder - are commonly used for the modulus operation. Although any other of the
-	             rounding modes can be used, they may not give useful results.
-	             */
-	            Decimal['modulo'] = 1;                            // 0 to 9
-
-	            // The exponent value at and beneath which toString returns exponential notation.
-	            // Number type: -7
-	            Decimal['toExpNeg'] = -7;                         // 0 to -EXP_LIMIT
-
-	            // The exponent value at and above which toString returns exponential notation.
-	            // Number type: 21
-	            Decimal['toExpPos'] = 21;                         // 0 to EXP_LIMIT
-
-	            // The minimum exponent value, beneath which underflow to zero occurs.
-	            // Number type: -324  (5e-324)
-	            Decimal['minE'] = -EXP_LIMIT;                     // -1 to -EXP_LIMIT
-
-	            // The maximum exponent value, above which overflow to Infinity occurs.
-	            // Number type:  308  (1.7976931348623157e+308)
-	            Decimal['maxE'] = EXP_LIMIT;                      // 1 to EXP_LIMIT
-
-	            // Whether Decimal Errors are ever thrown.
-	            Decimal['errors'] = true;                         // true/false
-
-	            // Whether to use cryptographically-secure random number generation, if available.
-	            Decimal['crypto'] = false;                        // true/false
-
-	            // Format specification for the Decimal.prototype.toFormat method
-	            Decimal.format = {
-	                decimalSeparator: '.',
-	                groupSeparator: ',',
-	                groupSize: 3,
-	                secondaryGroupSize: 0,
-	                fractionGroupSeparator: '\xA0',              // non-breaking space
-	                fractionGroupSize: 0
-	            };
-
-
-	            /* ********************** END OF CONSTRUCTOR DEFAULT PROPERTIES ********************* */
-
-
-	            Decimal.prototype = P;
-
-	            Decimal['ONE'] = new Decimal(1);
-
-	            /*
-	            // Pi to 80 s.d.
-	            Decimal['PI'] = new Decimal(
-	                '3.1415926535897932384626433832795028841971693993751058209749445923078164062862089'
-	            );
-	             */
-
-	            Decimal['ROUND_UP'] = 0;
-	            Decimal['ROUND_DOWN'] = 1;
-	            Decimal['ROUND_CEIL'] = 2;
-	            Decimal['ROUND_FLOOR'] = 3;
-	            Decimal['ROUND_HALF_UP'] = 4;
-	            Decimal['ROUND_HALF_DOWN'] = 5;
-	            Decimal['ROUND_HALF_EVEN'] = 6;
-	            Decimal['ROUND_HALF_CEIL'] = 7;
-	            Decimal['ROUND_HALF_FLOOR'] = 8;
-
-	            // modulo mode
-	            Decimal['EUCLID'] = 9;
-
-	            //Decimal['abs'] = abs;
-	            //Decimal['acos'] = acos;
-	            //Decimal['asin'] = asin;
-	            //Decimal['atan'] = atan;
-	            //Decimal['atan2'] = atan2;
-	            //Decimal['ceil'] = ceil;
-	            //Decimal['cos'] = cos;
-	            //Decimal['floor'] = floor;
-	            //Decimal['round'] = round;
-	            //Decimal['sin'] = sin;
-	            //Decimal['tan'] = tan;
-	            //Decimal['trunc'] = trunc;
-
-	            Decimal['config'] = config;
-	            Decimal['constructor'] = decimalFactory;
-	            Decimal['exp'] = exp;
-	            Decimal['ln'] = ln;
-	            Decimal['log'] = log;
-	            Decimal['max'] = max;
-	            Decimal['min'] = min;
-	            Decimal['pow'] = pow;
-	            Decimal['sqrt'] = sqrt;
-	            Decimal['random'] = random;
-
-	            if ( obj != null ) {
-	                Decimal['config'](obj);
-	            }
-
-	            return Decimal;
-	        }
-
-	        return decimalFactory();
-	    })();
-
-
-	    // Export.
-
-
-	    // AMD.
-	    if ( true ) {
-
-	        !(__WEBPACK_AMD_DEFINE_RESULT__ = function () {
-	            return decimal;
-	        }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
-
-	    // Node and other environments that support module.exports.
-	    } else if ( typeof module != 'undefined' && module.exports ) {
-	        module.exports = decimal;
-
-	        if ( !crypto ) {
-
-	            try {
-	                crypto = require('crypto');
-	            } catch (e) {}
-	        }
-
-	    // Browser.
-	    } else {
-	        noConflict = global['Decimal'];
-
-	        decimal['noConflict'] = function () {
-	            global['Decimal'] = noConflict;
-
-	            return decimal;
-	        };
-
-	        global['Decimal'] = decimal;
-	    }
-	})(this);
-
-
-/***/ },
-/* 18 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var deepMap = __webpack_require__(19);
-
-	function factory (type, config, load, typed) {
-	  /**
-	   * 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
-	   */
-	  var bignumber = typed('bignumber', {
-	    '': function () {
-	      return new type.BigNumber(0);
-	    },
-
-	    'number': function (x) {
-	      // convert to string to prevent errors in case of >15 digits
-	      return new type.BigNumber(x + '');
-	    },
-
-	    'string': function (x) {
-	      return new type.BigNumber(x);
-	    },
-
-	    'BigNumber': function (x) {
-	      // we assume a BigNumber is immutable
-	      return x;
-	    },
-
-	    'Array | Matrix': function (x) {
-	      return deepMap(x, bignumber);
-	    }
-	  });
-
-	  bignumber.toTex = {
-	    0: '0',
-	    1: '\\left(${args[0]}\\right)'
-	  };
-
-	  return bignumber;
-	}
-
-	exports.name = 'bignumber';
-	exports.factory = factory;
-
-
-/***/ },
-/* 19 */
-/***/ function(module, exports) {
-
-	'use strict';
-
-	/**
-	 * 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
-	 */
-	module.exports = function deepMap(array, callback, skipZeros) {
-	  if (array && (typeof array.map === 'function')) {
-	    // TODO: replace array.map with a for loop to improve performance
-	    return array.map(function (x) {
-	      return deepMap(x, callback, skipZeros);
-	    });
-	  }
-	  else {
-	    return callback(array);
-	  }
-	};
-
-
-/***/ },
-/* 20 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var deepMap = __webpack_require__(19);
-
-	function factory (type, config, load, typed) {
-	  /**
-	   * 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
-	   */
-	  var bool = typed('bool', {
-	    '': function () {
-	      return false;
-	    },
-
-	    'boolean': function (x) {
-	      return x;
-	    },
-
-	    'number': function (x) {
-	      return !!x;
-	    },
-
-	    'BigNumber': function (x) {
-	      return !x.isZero();
-	    },
-
-	    'string': function (x) {
-	      // try case insensitive
-	      var lcase = x.toLowerCase();
-	      if (lcase === 'true') {
-	        return true;
-	      }
-	      else if (lcase === 'false') {
-	        return false;
-	      }
-
-	      // test whether value is a valid number
-	      var num = Number(x);
-	      if (x != '' && !isNaN(num)) {
-	        return !!num;
-	      }
-
-	      throw new Error('Cannot convert "' + x + '" to a boolean');
-	    },
-
-	    'Array | Matrix': function (x) {
-	      return deepMap(x, bool);
-	    }
-	  });
-
-	  return bool;
-	}
-
-	exports.name = 'boolean';
-	exports.factory = factory;
-
-
-/***/ },
-/* 21 */
-/***/ function(module, exports, __webpack_require__) {
-
-	module.exports = [
-	  // type
-	  __webpack_require__(22),
-
-	  // construction function
-	  __webpack_require__(25)
-	];
-
-
-/***/ },
-/* 22 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var format = __webpack_require__(23).format;
-	var lazy = __webpack_require__(3).lazy;
-
-	function factory (type, config, load, typed, math) {
-	  /**
-	   * @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 && value.isChain) {
-	      this.value = value.value;
-	    }
-	    else {
-	      this.value = value;
-	    }
-	  }
-
-	  /**
-	   * Attach type information
-	   */
-	  Chain.prototype.type = 'Chain';
-	  Chain.prototype.isChain = true;
-
-	  /**
-	   * 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 format(this.value);
-	  };
-
-	  /**
-	   * Create a proxy method for the chain
-	   * @param {string} name
-	   * @param {Function} fn      The function to be proxied
-	   *                           If fn is no function, it is silently ignored.
-	   * @private
-	   */
-	  function createProxy(name, fn) {
-	    if (typeof fn === 'function') {
-	      Chain.prototype[name] = chainify(fn);
-	    }
-	  }
-
-	  /**
-	   * Create a proxy method for the chain
-	   * @param {string} name
-	   * @param {function} resolver   The function resolving with the
-	   *                              function to be proxied
-	   * @private
-	   */
-	  function createLazyProxy(name, resolver) {
-	    lazy(Chain.prototype, name, function outerResolver() {
-	      var fn = resolver();
-	      if (typeof fn === 'function') {
-	        return chainify(fn);
-	      }
-
-	      return undefined; // if not a function, ignore
-	    });
-	  }
-
-	  /**
-	   * Make a function chainable
-	   * @param {function} fn
-	   * @return {Function} chain function
-	   * @private
-	   */
-	  function chainify (fn) {
-	    return function () {
-	      var args = [this.value];  // `this` will be the context of a Chain instance
-	      for (var i = 0; i < arguments.length; i++) {
-	        args[i + 1] = arguments[i];
-	      }
-
-	      return new Chain(fn.apply(fn, args));
-	    }
-	  }
-
-	  /**
-	   * Create a proxy for a single method, or an object with multiple methods.
-	   * Example usage:
-	   *
-	   *   Chain.createProxy('add', function add (x, y) {...});
-	   *   Chain.createProxy({
-	   *     add:      function add (x, y) {...},
-	   *     subtract: function subtract (x, y) {...}
-	   *   }
-	   *
-	   * @param {string | Object} arg0   A name (string), or an object with
-	   *                                 functions
-	   * @param {*} [arg1]               A function, when arg0 is a name
-	   */
-	  Chain.createProxy = function (arg0, arg1) {
-	    if (typeof arg0 === 'string') {
-	      // createProxy(name, value)
-	      createProxy(arg0, arg1);
-	    }
-	    else {
-	      // createProxy(values)
-	      for (var prop in arg0) {
-	        if (arg0.hasOwnProperty(prop)) {
-	          createProxy(prop, arg0[prop]);
-	        }
-	      }
-	    }
-	  };
-
-	  // create proxy for everything that is in math.js
-	  Chain.createProxy(math);
-
-	  // register on the import event, automatically add a proxy for every imported function.
-	  math.on('import', function (name, resolver, path) {
-	    if (path === undefined) {
-	      // an imported function (not a data type or something special)
-	      createLazyProxy(name, resolver);
-	    }
-	  });
-
-	  return Chain;
-	}
-
-	exports.name = 'Chain';
-	exports.path = 'type';
-	exports.factory = factory;
-	exports.math = true;  // require providing the math namespace as 5th argument
-	exports.lazy = false; // we need to register a listener on the import events, so no lazy loading
-
-
-/***/ },
-/* 23 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var formatNumber = __webpack_require__(6).format;
-	var formatBigNumber = __webpack_require__(24).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);
-	  }
-	}
-
-
-/***/ },
-/* 24 */
-/***/ 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.
-	}
-
-
-/***/ },
-/* 25 */
-/***/ function(module, exports) {
-
-	'use strict';
-
-	function factory (type, config, load, typed) {
-	  /**
-	   * 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.type.Chain} The created chain
-	   */
-	  return typed('chain', {
-	    '': function() {
-	      return new type.Chain();
-	    },
-
-	    'any': function(value) {
-	      return new type.Chain(value);
-	    }
-	  });
-	}
-
-	exports.name = 'chain';
-	exports.factory = factory;
-
-
-/***/ },
-/* 26 */
-/***/ function(module, exports, __webpack_require__) {
-
-	module.exports = [
-	  // type
-	  __webpack_require__(27),
-
-	  // construction function
-	  __webpack_require__(29)
-	];
-
-
-/***/ },
-/* 27 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var isNumber = __webpack_require__(6).isNumber;
-	var format = __webpack_require__(6).format;
-
-	function factory (type, config, load, typed) {
-	  // TODO: remove dependency on Unit, not good for modularization
-	  var Unit = load(__webpack_require__(28));
-
-	  /**
-	   * @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');
-	    }
-	  }
-
-	  /**
-	   * Attach type information
-	   */
-	  Complex.prototype.isComplex = true;
-	  Complex.prototype.type = '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;
-	  }
-
-	  function unexpectedEnd () {
-	    return new SyntaxError('End of string expected, got "' + text.substr(index) + '"');
-	  }
-
-	  /**
-	   * Parse a complex number from a string. For example Complex.parse("2 + 3i")
-	   * will return a Complex value where re = 2, im = 3.
-	   * Throws an Error if provided string does not contain a valid complex number.
-	   * @param {string} str
-	   * @returns {Complex} complex
-	   */
-	  Complex.parse = function (str) {
-	    text = str;
-	    index = -1;
-	    c = '';
-
-	    if (typeof text !== 'string') {
-	      throw new TypeError('Invalid argument in Complex.parse, string expected');
-	    }
-
-	    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.
-	          throw unexpectedEnd()
-	        }
-
-	        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.
-	            throw unexpectedEnd()
-	          }
-
-	          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
-	              throw new SyntaxError('Character "i" expected, got "' + c + '"');
-	            }
-	            next();
-	          }
-	          else {
-	            second = parseComplex();
-	            if (!second) {
-	              // imaginary number missing after separator
-	              throw new SyntaxError('Imaginary part expected');
-	            }
-	          }
-
-	          if (separator == '-') {
-	            if (second[0] == '-') {
-	              second = '+' + second.substring(1);
-	            }
-	            else {
-	              second = '-' + second;
-	            }
-	          }
-
-	          next();
-	          skipWhitespace();
-	          if (c) {
-	            // garbage at the end. not good.
-	            throw unexpectedEnd()
-	          }
-
-	          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.
-	          throw unexpectedEnd()
-	        }
-
-	        return new Complex(0, Number(first));
-	      }
-	    }
-
-	    throw new SyntaxError('Could not parse: "' + str + '" as complex number');
-	  };
-
-	  /**
-	   * 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 (phi && phi.isUnit && 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/utils/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 = format(this.re, options);
-	    var strIm = 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;
-
-	  return Complex;
-	}
-
-	exports.name = 'Complex';
-	exports.path = 'type';
-	exports.factory = factory;
-
-
-/***/ },
-/* 28 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var format = __webpack_require__(6).format;
-	var endsWith = __webpack_require__(23).endsWith;
-
-
-	function factory (type, config, load, typed) {
-
-	  /**
-	   * @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
-	   *     var d = new Unit(9.81, "m/s^2");         // 9.81 m/s^2
-	   *
-	   * @param {number} [value]  A value like 5.2
-	   * @param {string} [name]   A unit name like "cm" or "inch", or a derived unit of the form: "u1[^ex1] [u2[^ex2] ...] [/ u3[^ex3] [u4[^ex4]]]", such as "kg m^2/s^2", where each unit appearing after the forward slash is taken to be in the denominator. "kg m^2 s^-2" is a synonym and is also acceptable. Any of the units 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 && typeof value !== 'number') {
-	      throw new TypeError('First parameter in Unit constructor must be a number');
-	    }
-	    if (name != undefined && (typeof name !== 'string' || name == '')) {
-	      throw new TypeError('Second parameter in Unit constructor must be a string');
-	    }
-
-	    if (name != undefined) {
-	      var u = Unit.parse(name);
-	      this.units = u.units;
-	      this.dimensions = u.dimensions;
-	    }
-	    else {
-	      this.units = [
-	        {
-	          unit: UNIT_NONE,
-	          prefix: PREFIX_NONE,  // link to a list with supported prefixes
-	          power: 0
-	        }
-	      ];
-	      this.dimensions = [0, 0, 0, 0, 0, 0, 0, 0, 0];
-	    }
-
-	    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
-
-	    // The justification behind this is that if the constructor is explicitly called,
-	    // the caller wishes the units to be returned exactly as he supplied.
-	    this.isUnitListSimplified = true;
-
-	  }
-
-	  /**
-	   * Attach type information
-	   */
-	  Unit.prototype.type = 'Unit';
-	  Unit.prototype.isUnit = true;
-
-	  // 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') {
-	      // The grammar branches here. This could either be part of an exponent or the start of a unit that begins with the letter e, such as "4exabytes"
-
-	      var tentativeNumber = '';
-	      var tentativeIndex = index;
-
-	      tentativeNumber += c;
-	      next();
-
-	      if (c == '+' || c == '-') {
-	        tentativeNumber += c;
-	        next();
-	      }
-
-	      // Scientific notation MUST be followed by an exponent (otherwise we assume it is not scientific notation)
-	      if (!isDigit(c)) {
-	        // The e or E must belong to something else, so return the number without the e or E.
-	        revert(tentativeIndex);
-	        return number;
-	      }
-	      
-	      // We can now safely say that this is scientific notation.
-	      number = number + tentativeNumber;
-	      while (isDigit(c)) {
-	        number += c;
-	        next();
-	      }
-	    }
-
-	    return number;
-	  }
-
-	  function parseUnit() {
-	    var unitName = '';
-
-	    // Alphanumeric characters only; matches [a-zA-Z0-9]
-	    var code = text.charCodeAt(index);
-	    while ( (code >= 48 && code <= 57) ||
-	            (code >= 65 && code <= 90) ||
-	            (code >= 97 && code <= 122)) {
-	      unitName += c;
-	      next();
-	      code = text.charCodeAt(index);
-	    }
-
-	    // Must begin with [a-zA-Z]
-	    code = unitName.charCodeAt(0);
-	    if ((code >= 65 && code <= 90) ||
-	        (code >= 97 && code <= 122)) {
-	        return unitName || null;
-	    } 
-	    else {
-	      return null;
-	    }
-	  }
-
-	  function parseCharacter(toFind) {
-	    if (c === toFind) {
-	      next();
-	      return toFind;
-	    }
-	    else {
-	      return null;
-	    }
-	  }
-
-	  /**
-	   * Parse a string into a unit. Throws an exception if the provided string does not
-	   * contain a valid unit or cannot be parsed.
-	   * @param {string} str        A string like "5.2 inch", "4e2 cm/s^2"
-	   * @return {Unit} unit
-	   */
-	  Unit.parse = function (str) {
-	    text = str;
-	    index = -1;
-	    c = '';
-
-	    if (typeof text !== 'string') {
-	      throw new TypeError('Invalid argument in Unit.parse, string expected');
-	    }
-
-	    var unit = new Unit();
-	    unit.units = [];
-
-	    // A unit should follow this pattern:
-	    // [number]unit[^number] [unit[^number]]...[/unit[^number] [unit[^number]]]
-
-	    // Rules:
-	    // number is any floating point number.
-	    // unit is any alphanumeric string beginning with an alpha. Units with names like e3 should be avoided because they look like the exponent of a floating point number!
-	    // The string may optionally begin with a number.
-	    // Each unit may optionally be followed by ^number.
-	    // Whitespace or a forward slash is recommended between consecutive units, although the following technically is parseable:
-	    //   2m^2kg/s^2
-	    // it is not good form. If a unit starts with e, then it could be confused as a floating point number:
-	    //   4erg
-
-	    next();
-	    skipWhitespace();
-	    // Optional number at the start of the string
-	    var valueStr = parseNumber();
-	    var value = null;
-	    if(valueStr) {
-	      value = parseFloat(valueStr);
-	    }
-	    skipWhitespace();    // Whitespace is not required here
-
-	    // Next, we read any number of unit[^number]
-	    var powerMultiplierCurrent = 1;
-	    var expectingUnit = false;
-
-	    // Stack to keep track of powerMultipliers applied to each parentheses group
-	    var powerMultiplierStack = [];
-
-	    // Running product of all elements in powerMultiplierStack
-	    var powerMultiplierStackProduct = 1;
-
-	    while (true) {
-	      skipWhitespace();
-
-	      // Check for and consume opening parentheses, pushing powerMultiplierCurrent to the stack
-	      // A '(' will always appear directly before a unit.
-	      while (c === '(') {
-	        powerMultiplierStack.push(powerMultiplierCurrent);
-	        powerMultiplierStackProduct *= powerMultiplierCurrent;
-	        powerMultiplierCurrent = 1;
-	        next();
-	        skipWhitespace();
-	      }
-
-	      // Is there something here?
-	      if(c) {
-	        var oldC = c;
-	        var uStr = parseUnit();
-	        if(uStr == null) {
-	          throw new SyntaxError('Unexpected "' + oldC + '" in "' + text + '" at index ' + index.toString());
-	        }
-	      }
-	      else {
-	        // End of input.
-	        break;
-	      }
-
-	      // Verify the unit exists and get the prefix (if any)
-	      var res = _findUnit(uStr);
-	      if(res == null) {
-	        // Unit not found.
-	        throw new SyntaxError('Unit "' + uStr + '" not found.');
-	      }
-
-	      var power = powerMultiplierCurrent * powerMultiplierStackProduct;
-	      // Is there a "^ number"?
-	      skipWhitespace();
-	      if (parseCharacter('^')) {
-	        skipWhitespace();
-	        var p = parseNumber();
-	        if(p == null) {
-	          // No valid number found for the power!
-	          throw new SyntaxError('In "' + str + '", "^" must be followed by a floating-point number');
-	        }
-	        power *= p;
-	      }
-
-	      // Add the unit to the list
-	      unit.units.push( {
-	        unit: res.unit,
-	        prefix: res.prefix,
-	        power: power
-	      });
-	      for(var i=0; i<BASE_DIMENSIONS.length; i++) {
-	        unit.dimensions[i] += res.unit.dimensions[i] * power;
-	      }
-
-	      // Check for and consume closing parentheses, popping from the stack.
-	      // A ')' will always follow a unit.
-	      skipWhitespace();
-	      while (c === ')') {
-	        if(powerMultiplierStack.length === 0) {
-	          throw new SyntaxError('Unmatched ")" in "' + text + '" at index ' + index.toString());
-	        }
-	        powerMultiplierStackProduct /= powerMultiplierStack.pop();
-	        next();
-	        skipWhitespace();
-	      }
-
-	      // "*" and "/" should mean we are expecting something to come next.
-	      // Is there a forward slash? If so, negate powerMultiplierCurrent. The next unit or paren group is in the denominator.
-	      expectingUnit = false;
-
-	      if (parseCharacter('*')) {
-	        // explicit multiplication
-	        powerMultiplierCurrent = 1;
-	        expectingUnit = true;
-	      }
-	      else if (parseCharacter('/')) {
-	        // division
-	        powerMultiplierCurrent = -1;
-	        expectingUnit = true;
-	      }
-	      else {
-	        // implicit multiplication
-	        powerMultiplierCurrent = 1;
-	      }
-
-	      // Replace the unit into the auto unit system
-	      var baseDim = res.unit.base.key;
-	      UNIT_SYSTEMS.auto[baseDim] = {
-	        unit: res.unit,
-	        prefix: res.prefix
-	      };
-	    }
-	    
-	    // Has the string been entirely consumed?
-	    skipWhitespace();
-	    if(c) {
-	      throw new SyntaxError('Could not parse: "' + str + '"');
-	    }
-
-	    // Is there a trailing slash?
-	    if(expectingUnit) {
-	      throw new SyntaxError('Trailing characters: "' + str + '"');
-	    }
-
-	    // Is the parentheses stack empty?
-	    if(powerMultiplierStack.length !== 0) {
-	      throw new SyntaxError('Unmatched "(" in "' + text + '"');
-	    }
-
-	    // Are there any units at all?
-	    if(unit.units.length == 0) {
-	      throw new SyntaxError('"' + str + '" contains no units');
-	    }
-
-	    unit.value = (value != undefined) ? unit._normalize(value) : null;
-	    return 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];
-	      }
-	    }
-
-	    clone.dimensions = this.dimensions.slice(0);
-	    clone.units = [];
-	    for(var i=0; i<this.units.length; i++) {
-	      clone.units[i] = { };
-	      for (var p in this.units[i]) {
-	        if (this.units[i].hasOwnProperty(p)) {
-	          clone.units[i][p] = this.units[i][p];
-	        }
-	      }
-	    }
-
-	    return clone;
-	  };
-
-	  /**
-	   * Return whether the unit is derived (such as m/s, or cm^2, but not N)
-	   * @return {boolean} True if the unit is derived
-	   */
-	  Unit.prototype._isDerived = function() {
-	    if(this.units.length === 0) {
-	      return false;
-	    }
-	    return this.units.length > 1 || Math.abs(this.units[0].power - 1.0) > 1e-15;
-	  }
-
-	  /**
-	   * Normalize a value, based on its currently set unit(s)
-	   * @param {number} value
-	   * @return {number} normalized value
-	   * @private
-	   */
-	  Unit.prototype._normalize = function (value) {
-	    if (this.units.length === 0) {
-	      return value;
-	    }
-	    else if (this._isDerived()) {
-	      // This is a derived unit, so do not apply offsets.
-	      // For example, with J kg^-1 degC^-1 you would NOT want to apply the offset.
-	      var res = value;
-	      for(var i=0; i < this.units.length; i++) {
-	        res = res * Math.pow(this.units[i].unit.value * this.units[i].prefix.value, this.units[i].power);
-	      }
-	      return res;
-	    }
-	    else {
-	      // This is a single unit of power 1, like kg or degC
-	      return (value + this.units[0].unit.offset) * this.units[0].unit.value * this.units[0].prefix.value;
-	    }
-	  };
-
-	  /**
-	   * Denormalize a value, based on its currently set unit(s)
-	   * @param {number} value
-	   * @param {number} [prefixValue]    Optional prefix value to be used (ignored if this is a derived unit)
-	   * @return {number} denormalized value
-	   * @private
-	   */
-	  Unit.prototype._denormalize = function (value, prefixValue) {
-	    if (this.units.length === 0) {
-	      return value;
-	    }
-	    else if (this._isDerived()) {
-	      // This is a derived unit, so do not apply offsets.
-	      // For example, with J kg^-1 degC^-1 you would NOT want to apply the offset.
-	      // Also, prefixValue is ignored--but we will still use the prefix value stored in each unit, since kg is usually preferrable to g unless the user decides otherwise.
-	      var res = value;
-	      for(var i=0; i<this.units.length; i++) {
-	        res = res / Math.pow(this.units[i].unit.value * this.units[i].prefix.value, this.units[i].power);
-	      }
-	      return res;
-	    }
-	    else {
-	      // This is a single unit of power 1, like kg or degC
-	      if (prefixValue == undefined) {
-	        return value / this.units[0].unit.value / this.units[0].prefix.value - this.units[0].unit.offset;
-	      }
-	      else {
-	        return value / this.units[0].unit.value / prefixValue - this.units[0].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 (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
-	   * If this unit is a derived unit, this will ALWAYS return false, since by definition base units are not derived.
-	   * @param {BASE_UNITS | undefined} base
-	   */
-	  Unit.prototype.hasBase = function (base) {
-
-	    // All dimensions must be the same
-	    for(var i=0; i<BASE_DIMENSIONS.length; i++) {
-	      if (Math.abs(this.dimensions[i] - base.dimensions[i]) > 1e-12) {
-	        return false;
-	      }
-	    }
-	    return true;
-
-	  };
-
-	  /**
-	   * Check if this unit has a base or bases equal to another base or bases
-	   * For derived units, the exponent on each base also must match
-	   * @param {Unit} other
-	   * @return {boolean} true if equal base
-	   */
-	  Unit.prototype.equalBase = function (other) {
-	    // All dimensions must be the same
-	    for(var i=0; i<BASE_DIMENSIONS.length; i++) {
-	      if (Math.abs(this.dimensions[i] - other.dimensions[i]) > 1e-12) {
-	        return false;
-	      }
-	    }
-	    return true;
-	  };
-
-	  /**
-	   * 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);
-	  };
-
-	  /**
-	   * Multiply this unit with another one
-	   * @param {Unit} other
-	   * @return {Unit} product of this unit and the other unit
-	   */
-	  Unit.prototype.multiply = function (other) {
-
-	    var res = this.clone();
-	    
-	    for(var i=0; i<BASE_DIMENSIONS.length; i++) {
-	      res.dimensions[i] = this.dimensions[i] + other.dimensions[i];
-	    }
-
-	    // Append other's units list onto res (simplify later in Unit.prototype.format)
-	    for(var i=0; i<other.units.length; i++) {
-	      var inverted = JSON.parse(JSON.stringify(other.units[i])); 
-	      res.units.push(inverted);
-	    }
-
-	    // If at least one operand has a value, then the result should also have a value
-	    if(this.value != null || other.value != null) {
-	      var valThis = this.value == null ? this._normalize(1) : this.value;
-	      var valOther = other.value == null ? other._normalize(1) : other.value;
-	      res.value = valThis * valOther;
-	    }
-	    else {
-	      res.value = null;
-	    }
-
-	    // Trigger simplification of the unit list at some future time
-	    res.isUnitListSimplified = false;
-	    return res;
-	  }
-
-	  /**
-	   * Divide this unit by another one
-	   * @param {Unit} other
-	   * @return {Unit} result of dividing this unit by the other unit
-	   */
-	  Unit.prototype.divide = function (other) {
-	    var res = this.clone();
-	    
-	    for(var i=0; i<BASE_DIMENSIONS.length; i++) {
-	      res.dimensions[i] = this.dimensions[i] - other.dimensions[i];
-	    }
-
-	    // Invert and append other's units list onto res (simplify later in Unit.prototype.format)
-	    for(var i=0; i<other.units.length; i++) {
-	      // Clone other's unit
-	      var inverted = JSON.parse(JSON.stringify(other.units[i])); 
-	      inverted.power = -inverted.power;
-	      res.units.push(inverted);
-	    }
-
-	    // If at least one operand has a value, the result should have a value
-	    if (this.value != null || other.value != null) {
-	      var valThis = this.value == null ? this._normalize(1) : this.value;
-	      var valOther = other.value == null ? other._normalize(1) : other.value;
-	      res.value = valThis / valOther;
-	    }
-	    else {
-	      res.value = null;
-	    }
-
-	    // Trigger simplification of the unit list at some future time
-	    res.isUnitListSimplified = false;
-	    return res;
-	  };
-
-	  /**
-	   * Calculate the power of a unit
-	   * @param {number} p    Any real number
-	   * @returns {Unit}      The result: this^p
-	   */
-	  Unit.prototype.pow = function (p) {
-	    var res = this.clone();
-	    
-	    for(var i=0; i<BASE_DIMENSIONS.length; i++) {
-	      res.dimensions[i] = this.dimensions[i] * p;
-	    }
-
-	    // Adjust the power of each unit in the list
-	    for(var i=0; i<res.units.length; i++) {
-	      res.units[i].power *= p;
-	    }
-
-	    if(res.value != null) {
-	      res.value = Math.pow(res.value, p);
-	    }
-	    else {
-	      res.value = null;
-	    }
-
-	    // Trigger lazy evaluation of the unit list
-	    res.isUnitListSimplified = false;
-	    return res;
-	  };
-
-
-	  /**
-	   * 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 (typeof valuelessUnit === 'string') {
-	      //other = new Unit(null, valuelessUnit);
-	      other = Unit.parse(valuelessUnit);
-	      if (!this.equalBase(other)) {
-	        throw new Error('Units do not match');
-	      }
-	      if (other.value !== null) {
-	        throw new Error('Cannot convert to a unit with a value');
-	      }
-
-	      other.value = value;
-	      other.fixPrefix = true;
-	      other.isUnitListSimplified = true;
-	      return other;
-	    }
-	    else if (valuelessUnit && valuelessUnit.isUnit) {
-	      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;
-	      other.isUnitListSimplified = 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);
-	    if(other._isDerived()) {
-	      return other._denormalize(other.value);    
-	    }
-	    else {
-	      return other._denormalize(other.value, other.units[0].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.formatUnits(),
-	      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;
-
-	  /**
-	   * Attempt to simplify the list of units for this unit according to the dimensions array and the current unit system. After the call, this Unit will contain a list of the "best" units for formatting.
-	   * Intended to be evaluated lazily. You must set isUnitListSimplified = false before the call! After the call, isUnitListSimplified will be set to true.
-	   */
-	  Unit.prototype.simplifyUnitListLazy = function() {
-
-	    if (this.isUnitListSimplified || this.value == null) {
-	      return;
-	    }
-
-	    var proposedUnitList = [];
-
-	    // Search for a matching base
-	    var matchingBase;
-	    for(var key in currentUnitSystem) {
-	      if(this.hasBase(BASE_UNITS[key])) {
-	        matchingBase = key;
-	        break;
-	      }
-	    }
-
-	    if(matchingBase === 'NONE')
-	    {
-	      this.units = [];
-	    }
-	    else {
-	      var matchingUnit;
-	      if(matchingBase) {
-	        // Does the unit system have a matching unit?
-	        if(currentUnitSystem.hasOwnProperty(matchingBase)) {
-	          matchingUnit = currentUnitSystem[matchingBase]
-	        }
-	      }
-
-	      var value;
-	      var str;
-	      if(matchingUnit) {
-	        this.units = [{
-	          unit: matchingUnit.unit,
-	          prefix: matchingUnit.prefix,
-	          power: 1.0
-	        }];
-	      }
-	      else {
-	        // Multiple units or units with powers are formatted like this:
-	        // 5 (kg m^2) / (s^3 mol)
-	        // Build an representation from the base units of the current unit system
-	        for(var i=0; i<BASE_DIMENSIONS.length; i++) {
-	          var baseDim = BASE_DIMENSIONS[i];
-	          if(Math.abs(this.dimensions[i]) > 1e-12) {
-	            proposedUnitList.push({
-	              unit: currentUnitSystem[baseDim].unit,
-	              prefix: currentUnitSystem[baseDim].prefix,
-	              power: this.dimensions[i]
-	            });
-	          }
-	        }
-
-	        // Is the proposed unit list "simpler" than the existing one?
-	        if(proposedUnitList.length < this.units.length) {
-	          // Replace this unit list with the proposed list
-	          this.units = proposedUnitList;
-	        }
-	      }
-	    }
-
-	    this.isUnitListSimplified = true;
-	  };
-
-	  /**
-	   * Get a string representation of the units of this Unit, without the value.
-	   * @return {string}
-	   */
-	  Unit.prototype.formatUnits = function () {
-
-	    // Lazy evaluation of the unit list
-	    this.simplifyUnitListLazy();
-
-	    var strNum = "";
-	    var strDen = "";
-	    var nNum = 0;
-	    var nDen = 0;
-
-	    for(var i=0; i<this.units.length; i++) {
-	      if(this.units[i].power > 0) {
-	        nNum++;
-	        strNum += " " + this.units[i].prefix.name + this.units[i].unit.name;
-	        if(Math.abs(this.units[i].power - 1.0) > 1e-15) {
-	          strNum += "^" + this.units[i].power;
-	        }
-	      }
-	      else if(this.units[i].power < 0) {
-	        nDen++;
-	      }
-	    }
-
-	    if(nDen > 0) {
-	      for(var i=0; i<this.units.length; i++) {
-	        if(this.units[i].power < 0) {
-	          if(nNum > 0) {
-	            strDen += " " + this.units[i].prefix.name + this.units[i].unit.name;
-	            if(Math.abs(this.units[i].power + 1.0) > 1e-15) {
-	              strDen += "^" + (-this.units[i].power);
-	            }
-	          }
-	          else {
-	            strDen += " " + this.units[i].prefix.name + this.units[i].unit.name;
-	            strDen += "^" + (this.units[i].power);
-	          }
-	        }
-	      }
-	    }
-	    // Remove leading " "
-	    strNum = strNum.substr(1);
-	    strDen = strDen.substr(1);
-
-	    // Add parans for better copy/paste back into the eval, for example, or for better pretty print formatting
-	    if(nNum > 1 && nDen > 0) {
-	      strNum = "(" + strNum + ")";
-	    }
-	    if(nDen > 1 && nNum > 0) {
-	      strDen = "(" + strDen + ")";
-	    }
-
-	    var str = strNum;
-	    if(nNum > 0 && nDen > 0) {
-	      str += " / ";
-	    }
-	    str += strDen;
-
-	    return str;
-	  };
-
-	  /**
-	   * Get a string representation of the Unit, with optional formatting options.
-	   * @param {Object | number | Function} [options]  Formatting options. See
-	   *                                                lib/utils/number:format for a
-	   *                                                description of the available
-	   *                                                options.
-	   * @return {string}
-	   */
-	  Unit.prototype.format = function (options) {
-
-	    // Simplfy the unit list, if necessary
-	    this.simplifyUnitListLazy();
-
-	    // Now apply the best prefix
-	    // Units must have only one unit and not have the fixPrefix flag set
-	    if (this.units.length === 1 && !this.fixPrefix) {
-	      // Units must have integer powers, otherwise the prefix will change the
-	      // outputted value by not-an-integer-power-of-ten
-	      if (Math.abs(this.units[0].power - Math.round(this.units[0].power)) < 1e-14) {
-	        // Apply the prefix
-	        var bestPrefix = this._bestPrefix();
-	        this.units[0].prefix = bestPrefix;
-	      }
-	    }
-
-	    var value = this._denormalize(this.value);
-	    var str = (this.value !== null) ? (format(value, options)) : '';
-	    var unitStr = this.formatUnits();
-	    if(unitStr.length > 0 && str.length > 0) {
-	      str += " ";
-	    }
-	    str += unitStr;
-
-	    return str;
-
-	/*
-	    var value,
-	        str;
-	    if (this._isDerived()) {
-	      value = this._denormalize(this.value);
-	      str = (this.value !== null) ? (format(value, options)) : '';
-	      var unitStr = this.formatUnits();
-	      if(unitStr.length > 0 && str.length > 0) {
-	        str += " ";
-	      }
-	      str += unitStr;
-	    }
-	    else if (this.units.length === 1) {
-	      if (this.value !== null && !this.fixPrefix) {
-	        var bestPrefix = this._bestPrefix();
-	        value = this._denormalize(this.value, bestPrefix.value);
-	        str = format(value, options) + ' ';
-	        str += bestPrefix.name + this.units[0].unit.name;
-	      }
-	      else {
-	        value = this._denormalize(this.value);
-	        str = (this.value !== null) ? (format(value, options) + ' ') : '';
-	        str += this.units[0].prefix.name + this.units[0].unit.name;
-	      }
-	    }
-	    else if (this.units.length === 0) {
-	      str = format(this.value, options);
-	    }
-
-
-	    return str;
-	    */
-	  };
-
-	  /**
-	   * Calculate the best prefix using current value.
-	   * @returns {Object} prefix
-	   * @private
-	   */
-	  Unit.prototype._bestPrefix = function () {
-	    if (this.units.length !== 1) {
-	      throw new Error("Can only compute the best prefix for single units with integer powers, like kg, s^2, N^-1, and so forth!");
-	    }
-	    if (Math.abs(this.units[0].power - Math.round(this.units[0].power)) >= 1e-14) {
-	      throw new Error("Can only compute the best prefix for single units with integer powers, like kg, s^2, N^-1, and so forth!");
-	    }
-
-	    // 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.units[0].unit.value);
-	    var bestPrefix = this.units[0].prefix;
-	    if (absValue === 0) {
-	      return bestPrefix;
-	    }
-	    var power = this.units[0].power;
-	    var bestDiff = Math.abs(
-	        Math.log(absValue / Math.pow(bestPrefix.value * this.units[0].unit.value, power)) / Math.LN10 - 1.2);
-
-	    var prefixes = this.units[0].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 / Math.pow(prefix.value * this.units[0].unit.value, power)) / Math.LN10 - 1.2);
-
-	          if (diff < bestDiff
-	              || (diff === bestDiff && prefix.name.length < bestPrefix.name.length)) {
-	                // choose the prefix with the smallest diff, or if equal, choose the one
-	                // with the shortest name (can happen with SHORTLONG for example)
-	                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-48, 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}
-	    },
-	    BTU: {
-	      '':   {name: '',   value: 1,   scientific: true},
-	      'MM': {name: 'MM', value: 1e6, scientific: true}
-	    }
-	  };
-
-	  // Add a prefix list for both short and long prefixes (for ohm in particular, since Mohm and megaohm are both acceptable):
-	  PREFIXES.SHORTLONG = {};
-	  for (var key in PREFIXES.SHORT) {
-	    if(PREFIXES.SHORT.hasOwnProperty(key)) {
-	      PREFIXES.SHORTLONG[key] = PREFIXES.SHORT[key];
-	    }
-	  }
-	  for (var key in PREFIXES.LONG) {
-	    if(PREFIXES.LONG.hasOwnProperty(key)) {
-	      PREFIXES.SHORTLONG[key] = PREFIXES.LONG[key];
-	    }
-	  }
-
-	  var PREFIX_NONE = {name: '', value: 1, scientific: true};
-
-	  /* Internally, each unit is represented by a value and a dimension array. The elements of the dimensions array have the following meaning:
-	   * Index  Dimension
-	   * -----  ---------
-	   *   0    Length
-	   *   1    Mass
-	   *   2    Time
-	   *   3    Current
-	   *   4    Temperature
-	   *   5    Luminous intensity
-	   *   6    Amount of substance
-	   *   7    Angle
-	   *   8    Bit (digital)
-	   * For example, the unit "298.15 K" is a pure temperature and would have a value of 298.15 and a dimension array of [0, 0, 0, 0, 1, 0, 0, 0, 0]. The unit "1 cal / (gm °C)" can be written in terms of the 9 fundamental dimensions as [length^2] / ([time^2] * [temperature]), and would a value of (after conversion to SI) 4184.0 and a dimensions array of [2, 0, -2, 0, -1, 0, 0, 0, 0].
-	   *
-	   */
-
-	  var BASE_DIMENSIONS = ["MASS", "LENGTH", "TIME", "CURRENT", "TEMPERATURE", "LUMINOUS_INTENSITY", "AMOUNT_OF_SUBSTANCE", "ANGLE", "BIT"];
-
-	  var BASE_UNITS = {
-	    NONE: {
-	      dimensions: [0, 0, 0, 0, 0, 0, 0, 0, 0]
-	    },
-	    MASS: {
-	      dimensions: [1, 0, 0, 0, 0, 0, 0, 0, 0]
-	    },
-	    LENGTH: {
-	      dimensions: [0, 1, 0, 0, 0, 0, 0, 0, 0]
-	    },
-	    TIME: {
-	      dimensions: [0, 0, 1, 0, 0, 0, 0, 0, 0]
-	    },
-	    CURRENT: {
-	      dimensions: [0, 0, 0, 1, 0, 0, 0, 0, 0]
-	    },
-	    TEMPERATURE: {
-	      dimensions: [0, 0, 0, 0, 1, 0, 0, 0, 0]
-	    },
-	    LUMINOUS_INTENSITY: {
-	      dimensions: [0, 0, 0, 0, 0, 1, 0, 0, 0]
-	    },
-	    AMOUNT_OF_SUBSTANCE: {
-	      dimensions: [0, 0, 0, 0, 0, 0, 1, 0, 0]
-	    },
-
-	    FORCE: {
-	      dimensions: [1, 1, -2, 0, 0, 0, 0, 0, 0]
-	    },
-	    SURFACE: {
-	      dimensions: [0, 2, 0, 0, 0, 0, 0, 0, 0]
-	    },
-	    VOLUME: {
-	      dimensions: [0, 3, 0, 0, 0, 0, 0, 0, 0]
-	    },
-	    ENERGY: {
-	      dimensions: [1, 2, -2, 0, 0, 0, 0, 0, 0]
-	    },
-	    POWER: {
-	      dimensions: [1, 2, -3, 0, 0, 0, 0, 0, 0]
-	    },
-	    PRESSURE: {
-	      dimensions: [1, -1, -2, 0, 0, 0, 0, 0, 0]
-	    },
-
-	    ELECTRIC_CHARGE: {
-	      dimensions: [0, 0, 1, 1, 0, 0, 0, 0, 0]
-	    },
-	    ELECTRIC_CAPACITANCE: {
-	      dimensions: [-1, -2, 4, 2, 0, 0, 0, 0, 0]
-	    },
-	    ELECTRIC_POTENTIAL: {
-	      dimensions: [1, 2, -3, -1, 0, 0, 0, 0, 0]
-	    },
-	    ELECTRIC_RESISTANCE: {
-	      dimensions: [1, 2, -3, -2, 0, 0, 0, 0, 0]
-	    },
-	    ELECTRIC_INDUCTANCE: {
-	      dimensions: [1, 2, -2, -2, 0, 0, 0, 0, 0]
-	    },
-	    ELECTRIC_CONDUCTANCE: {
-	      dimensions: [-1, -2, 3, 2, 0, 0, 0, 0, 0]
-	    },
-	    MAGNETIC_FLUX: {
-	      dimensions: [1, 2, -2, -1, 0, 0, 0, 0, 0]
-	    },
-	    MAGNETIC_FLUX_DENSITY: {
-	      dimensions: [1, 0, -2, -1, 0, 0, 0, 0, 0]
-	    },
-
-
-	    ANGLE: {
-	      dimensions: [0, 0, 0, 0, 0, 0, 0, 1, 0]
-	    },
-	    BIT: {
-	      dimensions: [0, 0, 0, 0, 0, 0, 0, 0, 1]
-	    }
-	  };
-
-	  for(var key in BASE_UNITS) {
-	    BASE_UNITS[key].key = key;
-	  }
-
-	  var BASE_UNIT_NONE = {};
-
-	  var UNIT_NONE = {name: '', base: BASE_UNIT_NONE, value: 1, offset: 0, dimensions: [0,0,0,0,0,0,0,0,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: 6.35029318,
-	      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
-	    },
-	    dyn: {
-	      name: 'dyn',
-	      base: BASE_UNITS.FORCE,
-	      prefixes: PREFIXES.SHORT,
-	      value: 0.00001,
-	      offset: 0
-	    },
-	    dyne: {
-	      name: 'dyne',
-	      base: BASE_UNITS.FORCE,
-	      prefixes: PREFIXES.LONG,
-	      value: 0.00001,
-	      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
-	    },
-	    // Energy
-	    J: {
-	      name: 'J',
-	      base: BASE_UNITS.ENERGY,
-	      prefixes: PREFIXES.SHORT,
-	      value: 1,
-	      offset: 0
-	    },
-	    joule: {
-	      name: 'joule',
-	      base: BASE_UNITS.ENERGY,
-	      prefixes: PREFIXES.SHORT,
-	      value: 1,
-	      offset: 0
-	    },
-	    erg: {
-	      name: 'erg',
-	      base: BASE_UNITS.ENERGY,
-	      prefixes: PREFIXES.NONE,
-	      value: 1e-5,
-	      offset: 0
-	    },
-	    Wh: {
-	      name: 'Wh',
-	      base: BASE_UNITS.ENERGY,
-	      prefixes: PREFIXES.SHORT,
-	      value: 3600,
-	      offset: 0
-	    },
-	    BTU: {
-	      name: 'BTU',
-	      base: BASE_UNITS.ENERGY,
-	      prefixes: PREFIXES.BTU,
-	      value: 1055.05585262,
-	      offset: 0
-	    },
-	    eV: {
-	      name: 'eV',
-	      base: BASE_UNITS.ENERGY,
-	      prefixes: PREFIXES.SHORT,
-	      value: 1.602176565e-19,
-	      offset: 0
-	    },
-	    electronvolt: {
-	      name: 'electronvolt',
-	      base: BASE_UNITS.ENERGY,
-	      prefixes: PREFIXES.LONG,
-	      value: 1.602176565e-19,
-	      offset: 0
-	    },
-
-
-	    // Power
-	    W: {
-	      name: 'W',
-	      base: BASE_UNITS.POWER,
-	      prefixes: PREFIXES.SHORT,
-	      value: 1,
-	      offset: 0
-	    },
-	    watt: {
-	      name: 'W',
-	      base: BASE_UNITS.POWER,
-	      prefixes: PREFIXES.LONG,
-	      value: 1,
-	      offset: 0
-	    },
-	    hp: {
-	      name: 'hp',
-	      base: BASE_UNITS.POWER,
-	      prefixes: PREFIXES.NONE,
-	      value: 745.6998715386,
-	      offset: 0
-	    },
-
-	    // Pressure
-	    Pa: {
-	      name: 'Pa',
-	      base: BASE_UNITS.PRESSURE,
-	      prefixes: PREFIXES.SHORT,
-	      value: 1,
-	      offset: 0
-	    },
-	    psi: {
-	      name: 'psi',
-	      base: BASE_UNITS.PRESSURE,
-	      prefixes: PREFIXES.NONE,
-	      value: 6894.75729276459,
-	      offset: 0
-	    },
-	    atm: {
-	      name: 'atm',
-	      base: BASE_UNITS.PRESSURE,
-	      prefixes: PREFIXES.NONE,
-	      value: 101325,
-	      offset: 0
-	    },
-
-	    // Electric charge
-	    coulomb: {
-	      name: 'coulomb',
-	      base: BASE_UNITS.ELECTRIC_CHARGE,
-	      prefixes: PREFIXES.LONG,
-	      value: 1,
-	      offset: 0
-	    },
-	    C: {
-	      name: 'C',
-	      base: BASE_UNITS.ELECTRIC_CHARGE,
-	      prefixes: PREFIXES.SHORT,
-	      value: 1,
-	      offset: 0
-	    },
-	    // Electric capacitance
-	    farad: {
-	      name: 'farad',
-	      base: BASE_UNITS.ELECTRIC_CAPACITANCE,
-	      prefixes: PREFIXES.LONG,
-	      value: 1,
-	      offset: 0
-	    },
-	    F: {
-	      name: 'F',
-	      base: BASE_UNITS.ELECTRIC_CAPACITANCE,
-	      prefixes: PREFIXES.SHORT,
-	      value: 1,
-	      offset: 0
-	    },
-	    // Electric potential
-	    volt: {
-	      name: 'volt',
-	      base: BASE_UNITS.ELECTRIC_POTENTIAL,
-	      prefixes: PREFIXES.LONG,
-	      value: 1,
-	      offset: 0
-	    },
-	    V: {
-	      name: 'V',
-	      base: BASE_UNITS.ELECTRIC_POTENTIAL,
-	      prefixes: PREFIXES.SHORT,
-	      value: 1,
-	      offset: 0
-	    },
-	    // Electric resistance
-	    ohm: {
-	      name: 'ohm',
-	      base: BASE_UNITS.ELECTRIC_RESISTANCE,
-	      prefixes: PREFIXES.SHORTLONG,    // Both Mohm and megaohm are acceptable
-	      value: 1,
-	      offset: 0
-	    },
-	    /*
-	     * Unicode breaks in browsers if charset is not specified
-	    Ω: {
-	      name: 'Ω',
-	      base: BASE_UNITS.ELECTRIC_RESISTANCE,
-	      prefixes: PREFIXES.SHORT,
-	      value: 1,
-	      offset: 0
-	    },
-	    */
-	    // Electric inductance
-	    henry: {
-	      name: 'henry',
-	      base: BASE_UNITS.ELECTRIC_INDUCTANCE,
-	      prefixes: PREFIXES.LONG,
-	      value: 1,
-	      offset: 0
-	    },
-	    H: {
-	      name: 'H',
-	      base: BASE_UNITS.ELECTRIC_INDUCTANCE,
-	      prefixes: PREFIXES.SHORT,
-	      value: 1,
-	      offset: 0
-	    },
-	    // Electric conductance
-	    siemens: {
-	      name: 'siemens',
-	      base: BASE_UNITS.ELECTRIC_CONDUCTANCE,
-	      prefixes: PREFIXES.LONG,
-	      value: 1,
-	      offset: 0
-	    },
-	    S: {
-	      name: 'S',
-	      base: BASE_UNITS.ELECTRIC_CONDUCTANCE,
-	      prefixes: PREFIXES.SHORT,
-	      value: 1,
-	      offset: 0
-	    },
-	    // Magnetic flux
-	    weber: {
-	      name: 'weber',
-	      base: BASE_UNITS.MAGNETIC_FLUX,
-	      prefixes: PREFIXES.LONG,
-	      value: 1,
-	      offset: 0
-	    },
-	    Wb: {
-	      name: 'Wb',
-	      base: BASE_UNITS.MAGNETIC_FLUX,
-	      prefixes: PREFIXES.SHORT,
-	      value: 1,
-	      offset: 0
-	    },
-	    // Magnetic flux density
-	    tesla: {
-	      name: 'tesla',
-	      base: BASE_UNITS.MAGNETIC_FLUX_DENSITY,
-	      prefixes: PREFIXES.LONG,
-	      value: 1,
-	      offset: 0
-	    },
-	    T: {
-	      name: 'T',
-	      base: BASE_UNITS.MAGNETIC_FLUX_DENSITY,
-	      prefixes: PREFIXES.SHORT,
-	      value: 1,
-	      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',
-
-	    BTUs: 'BTU',
-	    watts: 'watt',
-	    joules: 'joule',
-
-	    amperes: 'ampere',
-	    coulombs: 'coulomb',
-	    volts: 'volt',
-	    ohms: 'ohm',
-	    farads: 'farad',
-	    webers: 'weber',
-	    teslas: 'tesla',
-	    electronvolts: 'electronvolt',
-	    moles: 'mole'
-
-	  };
-
-	  /**
-	   * A unit system is a set of dimensionally independent base units plus a set of derived units, formed by multiplication and division of the base units, that are by convention used with the unit system.
-	   * A user perhaps could issue a command to select a preferred unit system, or use the default (see below).
-	   * Auto unit system: The default unit system is updated on the fly anytime a unit is parsed. The corresponding unit in the default unit system is updated, so that answers are given in the same units the user supplies.
-	   */
-	  var UNIT_SYSTEMS = {
-	    si: {
-	      // Base units
-	      NONE:                  {unit: UNIT_NONE, prefix: PREFIXES.NONE['']},
-	      LENGTH:                {unit: UNITS.m,   prefix: PREFIXES.SHORT['']},
-	      MASS:                  {unit: UNITS.g,   prefix: PREFIXES.SHORT['k']}, 
-	      TIME:                  {unit: UNITS.s,   prefix: PREFIXES.SHORT['']}, 
-	      CURRENT:               {unit: UNITS.A,   prefix: PREFIXES.SHORT['']}, 
-	      TEMPERATURE:           {unit: UNITS.K,   prefix: PREFIXES.SHORT['']}, 
-	      LUMINOUS_INTENSITY:    {unit: UNITS.cd,  prefix: PREFIXES.SHORT['']}, 
-	      AMOUNT_OF_SUBSTANCE:   {unit: UNITS.mol, prefix: PREFIXES.SHORT['']}, 
-	      ANGLE:                 {unit: UNITS.rad, prefix: PREFIXES.SHORT['']}, 
-	      BIT:                   {unit: UNITS.bit, prefix: PREFIXES.SHORT['']}, 
-
-	      // Derived units
-	      FORCE:                 {unit: UNITS.N,   prefix: PREFIXES.SHORT['']}, 
-	      ENERGY:                {unit: UNITS.J,   prefix: PREFIXES.SHORT['']},
-	      POWER:                 {unit: UNITS.W,   prefix: PREFIXES.SHORT['']},
-	      PRESSURE:              {unit: UNITS.Pa,  prefix: PREFIXES.SHORT['']},
-	      ELECTRIC_CHARGE:       {unit: UNITS.C,   prefix: PREFIXES.SHORT['']},
-	      ELECTRIC_CAPACITANCE:  {unit: UNITS.F,   prefix: PREFIXES.SHORT['']},
-	      ELECTRIC_POTENTIAL:    {unit: UNITS.V,   prefix: PREFIXES.SHORT['']},
-	      ELECTRIC_RESISTANCE:   {unit: UNITS.ohm, prefix: PREFIXES.SHORT['']},
-	      ELECTRIC_INDUCTANCE:   {unit: UNITS.H,   prefix: PREFIXES.SHORT['']},
-	      ELECTRIC_CONDUCTANCE:  {unit: UNITS.S,   prefix: PREFIXES.SHORT['']},
-	      MAGNETIC_FLUX:         {unit: UNITS.Wb,  prefix: PREFIXES.SHORT['']},
-	      MAGNETIC_FLUX_DENSITY: {unit: UNITS.T,   prefix: PREFIXES.SHORT['']}
-	    }
-	  };
-
-	  // Clone to create the other unit systems
-	  UNIT_SYSTEMS.cgs = JSON.parse(JSON.stringify(UNIT_SYSTEMS.si));
-	  UNIT_SYSTEMS.cgs.LENGTH = {unit: UNITS.m,   prefix: PREFIXES.SHORT['c']};
-	  UNIT_SYSTEMS.cgs.MASS =   {unit: UNITS.g,   prefix: PREFIXES.SHORT['']};
-	  UNIT_SYSTEMS.cgs.FORCE =  {unit: UNITS.dyn, prefix: PREFIXES.SHORT['']};
-	  UNIT_SYSTEMS.cgs.ENERGY = {unit: UNITS.erg, prefix: PREFIXES.NONE['']};
-	  // there are wholly 4 unique cgs systems for electricity and magnetism,
-	  // so let's not worry about it unless somebody complains
-	  
-	  UNIT_SYSTEMS.us = JSON.parse(JSON.stringify(UNIT_SYSTEMS.si));
-	  UNIT_SYSTEMS.us.LENGTH =      {unit: UNITS.ft,   prefix: PREFIXES.NONE['']};
-	  UNIT_SYSTEMS.us.MASS =        {unit: UNITS.lbm,  prefix: PREFIXES.NONE['']};
-	  UNIT_SYSTEMS.us.TEMPERATURE = {unit: UNITS.degF, prefix: PREFIXES.NONE['']};
-	  UNIT_SYSTEMS.us.FORCE =       {unit: UNITS.lbf,  prefix: PREFIXES.NONE['']};
-	  UNIT_SYSTEMS.us.ENERGY =      {unit: UNITS.BTU,  prefix: PREFIXES.BTU['']};
-	  UNIT_SYSTEMS.us.POWER =       {unit: UNITS.hp,   prefix: PREFIXES.NONE['']};
-	  UNIT_SYSTEMS.us.PRESSURE =    {unit: UNITS.psi,  prefix: PREFIXES.NONE['']};
-
-	  // Add additional unit systems here.
-
-
-
-	  // Choose a unit system to seed the auto unit system.
-	  UNIT_SYSTEMS.auto = JSON.parse(JSON.stringify(UNIT_SYSTEMS.si));
-
-	  // Set the current unit system
-	  var currentUnitSystem = UNIT_SYSTEMS.auto;
-
-	  /**
-	   * Set a unit system for formatting derived units.
-	   * @param {string} [name] The name of the unit system.
-	   */
-	  Unit.setUnitSystem = function(name) {
-	    if(UNIT_SYSTEMS.hasOwnProperty(name)) {
-	      currentUnitSystem = UNIT_SYSTEMS[name];
-	    }
-	    else {
-	      var mess = "Unit system " + name + " does not exist. Choices are: " + listAvailableUnitSystems();
-	    }
-	  }
-	 
-	  /**
-	   * Return a list of the available unit systems.
-	   * @return {string} A space-delimited string of the available unit systems.
-	   */
-	  Unit.listAvailableUnitSystems = function() {
-	    var mess = "";
-	    for(var key in UNIT_SYSTEMS) {
-	      mess += " " + key;
-	    }
-	    return mess.substr(1);
-	  }
-
-	  /**
-	   * Return the current unit system.
-	   * @return {string} The current unit system.
-	   */
-	  Unit.getUnitSystem = function() {
-	    for(var key in UNIT_SYSTEMS) {
-	      if(UNIT_SYSTEMS[key] === currentUnitSystem) {
-	        return key;
-	      }
-	    }
-	  }
-
-
-	  // Add dimensions to each built-in unit
-	  for (var key in UNITS) {
-	    var unit = UNITS[key];
-	    unit.dimensions = unit.base.dimensions;
-	  }    
-
-	  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;
-	  Unit.UNIT_SYSTEMS = UNIT_SYSTEMS;
-
-	  return Unit;
-	}
-
-	exports.name = 'Unit';
-	exports.path = 'type';
-	exports.factory = factory;
-
-
-/***/ },
-/* 29 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var deepMap = __webpack_require__(19);
-
-	function factory (type, config, load, typed) {
-	  var latex = __webpack_require__(30);
-
-	  /**
-	   * 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
-	   */
-	  var complex = typed('complex', {
-	    '': function () {
-	      return new type.Complex(0, 0);
-	    },
-
-	    'number': function (x) {
-	      return new type.Complex(x, 0);
-	    },
-
-	    'number, number': function (re, im) {
-	      return new type.Complex(re, im);
-	    },
-
-	    // TODO: this signature should be redundant
-	    'BigNumber, BigNumber': function (re, im) {
-	      return new type.Complex(re.toNumber(), im.toNumber());
-	    },
-
-	    'Complex': function (x) {
-	      return x.clone();
-	    },
-
-	    'string': function (x) {
-	      return type.Complex.parse(x); // for example '2 + 3i'
-	    },
-
-	    'Object': function (x) {
-	      if('re' in x && 'im' in x) {
-	        return new type.Complex(x.re, x.im);
-	      }
-
-	      if ('r' in x && 'phi' in x) {
-	        return type.Complex.fromPolar(x.r, x.phi);
-	      }
-
-	      throw new Error('Expected object with either properties re and im, or properties r and phi.');
-	    },
-
-	    'Array | Matrix': function (x) {
-	      return deepMap(x, complex);
-	    }
-	  });
-
-	  complex.toTex = {
-	    0: '0',
-	    1: '\\left(${args[0]}\\right)',
-	    2: '\\left(\\left(${args[0]}\\right)+'
-	      + latex.symbols['i'] + '\\cdot\\left(${args[1]}\\right)\\right)'
-	  };
-
-	  return complex;
-	}
-
-	exports.name = 'complex';
-	exports.factory = factory;
-
-
-/***/ },
-/* 30 */
-/***/ 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;
-	};
-
-
-/***/ },
-/* 31 */
-/***/ function(module, exports, __webpack_require__) {
-
-	module.exports = [
-	  // type
-	  __webpack_require__(32),
-
-	  // construction function
-	  __webpack_require__(36)
-	];
-
-
-/***/ },
-/* 32 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var Fraction = __webpack_require__(33);
-
-	/**
-	 * Attach type information
-	 */
-	Fraction.prototype.type = 'Fraction';
-	Fraction.prototype.isFraction = true;
-
-	/**
-	 * Get a JSON representation of a Fraction containing type information
-	 * @returns {Object} Returns a JSON object structured as:
-	 *                   `{"mathjs": "Fraction", "n": 3, "d": 8}`
-	 */
-	Fraction.prototype.toJSON = function () {
-	  return {
-	    mathjs: 'Fraction',
-	    n: this.s * this.n,
-	    d: this.d
-	  };
-	};
-
-	/**
-	 * Instantiate a Fraction from a JSON object
-	 * @param {Object} json  a JSON object structured as:
-	 *                       `{"mathjs": "Fraction", "n": 3, "d": 8}`
-	 * @return {BigNumber}
-	 */
-	Fraction.fromJSON = function (json) {
-	  return new Fraction(json);
-	};
-
-
-	function factory (type, config, load, typed) {
-	  return Fraction;
-	}
-
-	exports.name = 'Fraction';
-	exports.path = 'type';
-	exports.factory = factory;
-
-
-/***/ },
-/* 33 */
-/***/ function(module, exports, __webpack_require__) {
-
-	var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module) {/**
-	 * @license Fraction.js v3.0.0 09/09/2015
-	 * http://www.xarg.org/2014/03/precise-calculations-in-javascript/
-	 *
-	 * Copyright (c) 2015, Robert Eisele (robert@xxxxxxxx)
-	 * Dual licensed under the MIT or GPL Version 2 licenses.
-	 **/
-
-
-	/**
-	 *
-	 * This class offers the possebility to calculate fractions.
-	 * You can pass a fraction in different formats. Either as array, as double, as string or as an integer.
-	 *
-	 * Array/Object form
-	 * [ 0 => <nominator>, 1 => <denominator> ]
-	 * [ n => <nominator>, d => <denominator> ]
-	 *
-	 * Integer form
-	 * - Single integer value
-	 *
-	 * Double form
-	 * - Single double value
-	 *
-	 * String form
-	 * 123.456 - a simple double
-	 * 123/456 - A string fraction
-	 * 123.'456' - a double with repeating decimal places
-	 * 123.(456) - synonym
-	 * 123.45'6' - a double with repeating last place
-	 * 123.45(6) - synonym
-	 *
-	 * Example:
-	 *
-	 * var f = new Fraction("9.4'31'");
-	 * f.mul([-4, 3]).div(4.9);
-	 *
-	 */
-
-	(function(root) {
-
-	    "use strict";
-	    
-	    // Maximum search depth for cyclic rational numbers. 2000 should be more than enough. 
-	    // Example: 1/7 = 0.(142857) has 6 repeating decimal places.
-	    // When number gets reduced, long cycles will not be detected and toString() only gets the first 10 digits
-	    var MAX_CYCLE_LEN = 2000;
-
-	    // Parsed data to avoid calling "new" all the time
-	    var P = {
-	        "s": 1,
-	        "n": 0,
-	        "d": 1
-	    };
-
-	    function assign(n, s) {
-
-	        if (isNaN(n = parseInt(n, 10))) {
-	            thorwInvalidParam();
-	        }
-	        return n * s;
-	    }
-
-	    function thorwInvalidParam() {
-	        throw "Invalid Param";
-	    }
-
-	    var parse = function(p1, p2) {
-
-	        var n = 0, d = 1, s = 1;
-	        var v = 0, w = 0, x = 0, y = 1, z = 1;
-
-	        var A = 0, B = 1;
-	        var C = 1, D = 1;
-
-	        var N = 10000000;
-	        var M;
-
-	        if (p1 === undefined || p1 === null) {
-	            /* void */
-	        } else if (p2 !== undefined) {
-	            n = p1;
-	            d = p2;
-	            s = n * d;
-	        } else
-	            switch (typeof p1) {
-
-	                case "object":
-	                {
-	                    if ("d" in p1 && "n" in p1) {
-	                        n = p1["n"];
-	                        d = p1["d"];
-	                        if ("s" in p1)
-	                            n*= p1["s"];
-	                    } else if (0 in p1) {
-	                        n = p1[0];
-	                        if (1 in p1)
-	                            d = p1[1];
-	                    } else {
-	                        thorwInvalidParam();
-	                    }
-	                    s = n * d;
-	                    break;
-	                }
-	                case "number":
-	                {
-	                    if (p1 < 0) {
-	                        s = p1;
-	                        p1 = -p1;
-	                    }
-
-	                    if (p1 % 1 === 0) {
-	                        n = p1;
-	                    } else if (p1 > 0) { // check for != 0, scale would become NaN (log(0)), which converges really slow
-
-	                        if (p1 >= 1) {
-	                            z = Math.pow(10, Math.floor(1 + Math.log(p1) / Math.LN10));
-	                            p1/= z;
-	                        }
-
-	                        // Using Farey Sequences
-	                        // http://www.johndcook.com/blog/2010/10/20/best-rational-approximation/
-
-	                        while (B <= N && D <= N) {
-	                            M = (A + C) / (B + D);
-
-	                            if (p1 === M) {
-	                                if (B + D <= N) {
-	                                    n = A + C;
-	                                    d = B + D;
-	                                } else if (D > B) {
-	                                    n = C;
-	                                    d = D;
-	                                } else {
-	                                    n = A;
-	                                    d = B;
-	                                }
-	                                break;
-
-	                            } else {
-
-	                                if (p1 > M) {
-	                                    A+= C;
-	                                    B+= D;
-	                                } else {
-	                                    C+= A;
-	                                    D+= B;
-	                                }
-
-	                                if (B > N) {
-	                                    n = C;
-	                                    d = D;
-	                                } else {
-	                                    n = A;
-	                                    d = B;
-	                                }
-	                            }
-	                        }
-	                        n*= z;
-	                    }
-	                    break;
-	                }
-	                case "string":
-	                {
-	                    B = p1.match(/\d+|./g);
-
-	                    if (B[A] === '-') {// Check for minus sign at the beginning
-	                        s = -1;
-	                        A++;
-	                    } else if (B[A] === '+') {// Check for plus sign at the beginning
-	                        A++;
-	                    }
-
-	                    if (B.length === A + 1) { // Check if it's just a simple number "1234"
-	                        w = assign(B[A++], s);
-	                    } else if (B[A + 1] === '.' || B[A] === '.') { // Check if it's a decimal number
-
-	                        if (B[A] !== '.') { // Handle 0.5 and .5
-	                            v = assign(B[A++], s);
-	                        }
-	                        A++;
-
-	                        // Check for decimal places
-	                        if (A + 1 === B.length || B[A + 1] === '(' && B[A + 3] === ')' || B[A + 1] === "'" && B[A + 3] === "'") {
-	                            w = assign(B[A], s);
-	                            y = Math.pow(10, B[A].length);
-	                            A++;
-	                        }
-
-	                        // Check for repeating places
-	                        if (B[A] === '(' && B[A + 2] === ')' || B[A] === "'" && B[A + 2] === "'") {
-	                            x = assign(B[A + 1], s);
-	                            z = Math.pow(10, B[A + 1].length) - 1;
-	                            A+= 3;
-	                        }
-
-	                    } else if (B[A + 1] === '/' || B[A + 1] === ':') { // Check for a simple fraction "123/456" or "123:456"
-	                        w = assign(B[A], s);
-	                        y = assign(B[A + 2], 1);
-	                        A+= 3;
-	                    } else if (B[A + 3] === '/' && B[A + 1] === ' ') { // Check for a complex fraction "123 1/2"
-	                        v = assign(B[A], s);
-	                        w = assign(B[A + 2], s);
-	                        y = assign(B[A + 4], 1);
-	                        A+= 5;
-	                    }
-
-	                    if (B.length <= A) { // Check for more tokens on the stack
-	                        s = /* void */
-	                        n = x + z * (v * y + w);
-	                        d = y * z;
-	                        break;
-	                    }
-
-	                    /* Fall through on error */
-	                }
-	                default:
-	                    thorwInvalidParam();
-	            }
-
-	        if (!d) {
-	            throw "DIV/0";
-	        }
-
-	        P["s"] = s < 0 ? -1 : 1;
-	        P["n"] = Math.abs(n);
-	        P["d"] = Math.abs(d);
-	    };
-
-	    var modpow = function(b, e, m) {
-
-	        for (var r = 1; e > 0; b = (b * b) % m, e >>= 1) {
-
-	            if (e & 1) {
-	                r = (r * b) % m;
-	            }
-	        }
-	        return r;
-	    };
-
-	    var cycleLen = function(n, d) {
-
-	        for (; d % 2 === 0; 
-	            d/= 2) {}
-
-	        for (; d % 5 === 0; 
-	            d/= 5) {}
-	        
-	        if (d === 1) // Catch non-cyclic numbers
-	            return 0;
-	            
-	        // If we would like to compute really large numbers quicker, we could make use of Fermat's little theorem:
-	        // 10^(d-1) % d == 1
-	        // However, we don't need such large numbers and MAX_CYCLE_LEN should be the capstone, 
-	        // as we want to translate the numbers to strings.
-
-	        var rem = 10 % d;
-
-	        for (var t = 1; rem !== 1; t++) {
-	            rem = rem * 10 % d;
-
-	            if (t > MAX_CYCLE_LEN)
-	                return 0; // Returning 0 here means that we don't print it as a cyclic number. It's likely that the answer is `d-1`
-	        }
-	        return t;
-	    };
-
-	    var cycleStart = function(n, d, len) {
-
-	        var rem1 = 1;
-	        var rem2 = modpow(10, len, d);
-	        
-	        for (var t = 0; t < 300; t++) { // s < ~log10(Number.MAX_VALUE)
-	            // Solve 10^s == 10^(s+t) (mod d)
-
-	            if (rem1 === rem2)
-	                return t;
-
-	            rem1 = rem1 * 10 % d;
-	            rem2 = rem2 * 10 % d;
-	        }
-	        return 0;
-	    };
-
-	    var gcd = function(a, b) {
-
-	        if (!a) return b;
-	        if (!b) return a;
-
-	        while (1) {
-	            a%= b;
-	            if (!a) return b;
-	            b%= a;
-	            if (!b) return a;
-	        }
-	    };
-
-	    /**
-	     * Module constructor
-	     *
-	     * @constructor
-	     * @param {number|Fraction} a
-	     * @param {number=} b
-	     */
-	    function Fraction(a, b) {
-
-	        if (!(this instanceof Fraction)) {
-	            return new Fraction(a, b);
-	        }
-
-	        parse(a, b);
-
-	        if (Fraction['REDUCE']) {
-	            a = gcd(P["d"], P["n"]); // Abuse a
-	        } else {
-	            a = 1;
-	        }
-
-	        this["s"] = P["s"];
-	        this["n"] = P["n"] / a;
-	        this["d"] = P["d"] / a;
-	    }
-
-	    /**
-	     * Boolean global variable to be able to disable automatic reduction of the fraction
-	     *
-	     */
-	    Fraction['REDUCE'] = 1;
-
-	    Fraction.prototype = {
-
-	        "s": 1,
-	        "n": 0,
-	        "d": 1,
-
-	        /**
-	         * Calculates the absolute value
-	         *
-	         * Ex: new Fraction(-4).abs() => 4
-	         **/
-	        "abs": function() {
-
-	            return new Fraction(this["n"], this["d"]);
-	        },
-
-	        /**
-	         * Inverts the sign of the current fraction
-	         *
-	         * Ex: new Fraction(-4).neg() => 4
-	         **/
-	        "neg": function() {
-
-	            return new Fraction(-this["s"] * this["n"], this["d"]);
-	        },
-
-	        /**
-	         * Adds two rational numbers
-	         *
-	         * Ex: new Fraction({n: 2, d: 3}).add("14.9") => 467 / 30
-	         **/
-	        "add": function(a, b) {
-
-	            parse(a, b);
-	            return new Fraction(
-	                    this["s"] * this["n"] * P["d"] + P["s"] * this["d"] * P["n"],
-	                    this["d"] * P["d"]
-	                    );
-	        },
-
-	        /**
-	         * Subtracts two rational numbers
-	         *
-	         * Ex: new Fraction({n: 2, d: 3}).add("14.9") => -427 / 30
-	         **/
-	        "sub": function(a, b) {
-
-	            parse(a, b);
-	            return new Fraction(
-	                    this["s"] * this["n"] * P["d"] - P["s"] * this["d"] * P["n"],
-	                    this["d"] * P["d"]
-	                    );
-	        },
-
-	        /**
-	         * Multiplies two rational numbers
-	         *
-	         * Ex: new Fraction("-17.(345)").mul(3) => 5776 / 111
-	         **/
-	        "mul": function(a, b) {
-
-	            parse(a, b);
-	            return new Fraction(
-	                    this["s"] * P["s"] * this["n"] * P["n"],
-	                    this["d"] * P["d"]
-	                    );
-	        },
-
-	        /**
-	         * Divides two rational numbers
-	         *
-	         * Ex: new Fraction("-17.(345)").inverse().div(3)
-	         **/
-	        "div": function(a, b) {
-
-	            parse(a, b);
-	            return new Fraction(
-	                    this["s"] * P["s"] * this["n"] * P["d"],
-	                    this["d"] * P["n"]
-	                    );
-	        },
-
-	        /**
-	         * Clones the actual object
-	         *
-	         * Ex: new Fraction("-17.(345)").clone()
-	         **/
-	        "clone": function() {
-	            return new Fraction(this);
-	        },
-
-	        /**
-	         * Calculates the modulo of two rational numbers - a more precise fmod
-	         *
-	         * Ex: new Fraction('4.(3)').mod([7, 8]) => (13/3) % (7/8) = (5/6)
-	         **/
-	        "mod": function(a, b) {
-
-	            if (a === undefined) {
-	                return new Fraction(this["s"] * this["n"] % this["d"], 1);
-	            }
-
-	            parse(a, b);
-	            if (0 === (P["n"] * this["d"])) {
-	                Fraction(0, 0); // Throw div/0
-	            }
-
-	            /*
-	             * First silly attempt, kinda slow
-	             *
-	             return that["sub"]({
-	             "n": num["n"] * Math.floor((this.n / this.d) / (num.n / num.d)),
-	             "d": num["d"],
-	             "s": this["s"]
-	             });*/
-
-	            /*
-	             * New attempt: a1 / b1 = a2 / b2 * q + r
-	             * => b2 * a1 = a2 * b1 * q + b1 * b2 * r
-	             * => (b2 * a1 % a2 * b1) / (b1 * b2)
-	             */
-	            return new Fraction(
-	                    (this["s"] * P["d"] * this["n"]) % (P["n"] * this["d"]),
-	                    P["d"] * this["d"]
-	                    );
-	        },
-
-	        /**
-	         * Calculates the fractional gcd of two rational numbers
-	         *
-	         * Ex: new Fraction(5,8).gcd(3,7) => 1/56
-	         */
-	        "gcd": function(a, b) {
-
-	            parse(a, b);
-
-	            // gcd(a / b, c / d) = gcd(a, c) / lcm(b, d)
-
-	            return new Fraction(gcd(P["n"], this["n"]), P["d"] * this["d"] / gcd(P["d"], this["d"]));
-	        },
-
-	        /**
-	         * Calculates the fractional lcm of two rational numbers
-	         *
-	         * Ex: new Fraction(5,8).lcm(3,7) => 15
-	         */
-	        "lcm": function(a, b) {
-
-	            parse(a, b);
-
-	            // lcm(a / b, c / d) = lcm(a, c) / gcd(b, d)
-
-	            return new Fraction(P["n"] * this["n"] / gcd(P["n"], this["n"]), gcd(P["d"], this["d"]));
-	        },
-
-	        /**
-	         * Calculates the ceil of a rational number
-	         *
-	         * Ex: new Fraction('4.(3)').ceil() => (5 / 1)
-	         **/
-	        "ceil": function() {
-
-	            return new Fraction(Math.ceil(this["s"] * this["n"] / this["d"]), 1);
-	        },
-
-	        /**
-	         * Calculates the floor of a rational number
-	         *
-	         * Ex: new Fraction('4.(3)').floor() => (4 / 1)
-	         **/
-	        "floor": function() {
-
-	            return new Fraction(Math.floor(this["s"] * this["n"] / this["d"]), 1);
-	        },
-
-	        /**
-	         * Rounds a rational numbers
-	         *
-	         * Ex: new Fraction('4.(3)').round() => (4 / 1)
-	         **/
-	        "round": function() {
-
-	            return new Fraction(Math.round(this["s"] * this["n"] / this["d"]), 1);
-	        },
-
-	        /**
-	         * Gets the inverse of the fraction, means numerator and denumerator are exchanged
-	         *
-	         * Ex: new Fraction([-3, 4]).inverse() => -4 / 3
-	         **/
-	        "inverse": function() {
-
-	            return new Fraction(this["s"] * this["d"], this["n"]);
-	        },
-
-	        /**
-	         * Calculates the fraction to some integer exponent
-	         *
-	         * Ex: new Fraction(-1,2).pow(-3) => -8
-	         */
-	        "pow": function(m) {
-
-	            var d = this["d"];
-	            var n = this["n"];
-	            if (m < 0) {
-	                this["d"] = Math.pow(n, -m);
-	                this["n"] = Math.pow(d, -m);
-	            } else {
-	                this["d"] = Math.pow(d, m);
-	                this["n"] = Math.pow(n, m);
-	            }
-
-	            if (0 === (m % 2)) {
-	                this["s"] = 1;
-	            }
-	            return this;
-	        },
-
-	        /**
-	         * Check if two rational numbers are the same
-	         *
-	         * Ex: new Fraction(19.6).equals([98, 5]);
-	         **/
-	        "equals": function(a, b) {
-
-	            parse(a, b);
-	            return this["s"] * this["n"] * P["d"] === P["s"] * P["n"] * this["d"]; // Same as compare() === 0
-	        },
-
-	        /**
-	         * Check if two rational numbers are the same
-	         *
-	         * Ex: new Fraction(19.6).equals([98, 5]);
-	         **/
-	        "compare": function(a, b) {
-
-	            parse(a, b);
-	            var t = (this["s"] * this["n"] * P["d"] - P["s"] * P["n"] * this["d"]);
-	            return (0 < t) - (t < 0);
-	        },
-
-	        /**
-	         * Check if two rational numbers are divisible
-	         *
-	         * Ex: new Fraction(19.6).divisible(1.5);
-	         */
-	        "divisible": function(a, b) {
-
-	            parse(a, b);
-	            return !!(P["n"] * this["d"]) && !((this["n"] * P["d"]) % (P["n"] * this["d"]));
-	        },
-
-	        /**
-	         * Returns a decimal representation of the fraction
-	         *
-	         * Ex: new Fraction("100.'91823'").valueOf() => 100.91823918239183
-	         **/
-	        'valueOf': function() {
-
-	            return this["s"] * this["n"] / this["d"];
-	        },
-
-	        /**
-	         * Returns a string-fraction representation of a Fraction object
-	         *
-	         * Ex: new Fraction("1.'3'").toFraction() => "4 1/3"
-	         **/
-	        'toFraction': function(excludeWhole) {
-
-	            var whole, str = "";
-	            var n = this["n"];
-	            var d = this["d"];
-	            if (this["s"] < 0) {
-	                str+= '-';
-	            }
-
-	            if (d === 1) {
-	                str+= n;
-	            } else {
-
-	                if (excludeWhole && (whole = Math.floor(n / d)) > 0) {
-	                    str+= whole;
-	                    str+= " ";
-	                    n %= d;
-	                }
-
-	                str+= n;
-	                str+= '/';
-	                str+= d;
-	            }
-	            return str;
-	        },
-
-	        /**
-	         * Returns a latex representation of a Fraction object
-	         *
-	         * Ex: new Fraction("1.'3'").toLatex() => "\frac{4}{3}"
-	         **/
-	        'toLatex': function(excludeWhole) {
-
-	            var whole, str = "";
-	            var n = this["n"];
-	            var d = this["d"];
-	            if (this["s"] < 0) {
-	                str+= '-';
-	            }
-
-	            if (d === 1) {
-	                str+= n;
-	            } else {
-	                
-	                if (excludeWhole && (whole = Math.floor(n / d)) > 0) {		
-	                    str+= whole;		
-	                    n %= d;		
-	                }
-
-	                str+= "\\frac{";
-	                str+= n;
-	                str+= '}{';
-	                str+= d;
-	                str+= '}';
-	            }
-	            return str;
-	        },
-
-	        /**
-	         * Creates a string representation of a fraction with all digits
-	         *
-	         * Ex: new Fraction("100.'91823'").toString() => "100.(91823)"
-	         **/
-	        'toString': function() {
-
-	            var g;
-	            var N = this["n"];
-	            var D = this["d"];
-
-	            if (!Fraction['REDUCE']) {
-	                g = gcd(N, D);
-	                N/= g;
-	                D/= g;
-	            }
-
-	            var p = String(N).split(""); // Numerator chars
-	            var t = 0; // Tmp var
-
-	            var ret = [~this["s"] ? "" : "-", "", ""]; // Return array, [0] is zero sign, [1] before comma, [2] after
-	            var zeros = ""; // Collection variable for zeros
-
-	            var cycLen = cycleLen(N, D); // Cycle length
-	            var cycOff = cycleStart(N, D, cycLen); // Cycle start
-
-	            var j = -1;
-	            var n = 1; // str index
-
-	            // rough estimate to fill zeros
-	            var length = 10 + cycLen + cycOff + p.length; // 10 = decimal places when no repitation
-
-	            for (var i = 0; i < length; i++, t*= 10) {
-
-	                if (i < p.length) {
-	                    t+= Number(p[i]);
-	                } else {
-	                    n = 2;
-	                    j++; // Start now => after comma
-	                }
-
-	                if (cycLen > 0) { // If we have a repeating part
-	                    if (j === cycOff) {
-	                        ret[n]+= zeros + "(";
-	                        zeros = "";
-	                    } else if (j === cycLen + cycOff) {
-	                        ret[n]+= zeros + ")";
-	                        break;
-	                    }
-	                }
-
-	                if (t >= D) {
-	                    ret[n]+= zeros + ((t / D) | 0); // Flush zeros, Add current digit
-	                    zeros = "";
-	                    t = t % D;
-	                } else if (n > 1) { // Add zeros to the zero buffer
-	                    zeros+= "0";
-	                } else if (ret[n]) { // If before comma, add zero only if already something was added
-	                    ret[n]+= "0";
-	                }
-	            }
-
-	            // If it's empty, it's a leading zero only
-	            ret[0]+= ret[1] || "0";
-
-	            // If there is something after the comma, add the comma sign
-	            if (ret[2]) {
-	                return ret[0] + "." + ret[2];
-	            }
-	            return ret[0];
-	        }
-	    };
-
-	    if ("function" === "function" && __webpack_require__(35)["amd"]) {
-	        !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = function() {
-	            return Fraction;
-	        }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
-	    } else if (true) {
-	        module["exports"] = Fraction;
-	    } else {
-	        root['Fraction'] = Fraction;
-	    }
-
-	})(this);
-
-	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(34)(module)))
-
-/***/ },
-/* 34 */
-/***/ function(module, exports) {
-
-	module.exports = function(module) {
-		if(!module.webpackPolyfill) {
-			module.deprecate = function() {};
-			module.paths = [];
-			// module.parent = undefined by default
-			module.children = [];
-			module.webpackPolyfill = 1;
-		}
-		return module;
-	}
-
-
-/***/ },
-/* 35 */
-/***/ function(module, exports) {
-
-	module.exports = function() { throw new Error("define cannot be used indirect"); };
-
-
-/***/ },
-/* 36 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var deepMap = __webpack_require__(19);
-
-	function factory (type, config, load, typed) {
-	  /**
-	   * Create a fraction convert a value to a fraction.
-	   *
-	   * Syntax:
-	   *     math.fraction(numerator, denominator)
-	   *     math.fraction({n: numerator, d: denominator})
-	   *     math.fraction(matrix: Array | Matrix)         Turn all matrix entries
-	   *                                                   into fractions
-	   *
-	   * Examples:
-	   *
-	   *     math.fraction(1, 3);
-	   *     math.fraction('2/3');
-	   *     math.fraction({n: 2, d: 3});
-	   *     math.fraction([0.2, 0.25, 1.25]);
-	   *
-	   * See also:
-	   *
-	   *    bignumber, number, string, unit
-	   *
-	   * @param {number | string | Array | Matrix} [args]
-	   *            Arguments specifying the numerator and denominator of
-	   *            the fraction
-	   * @return {fraction | Array | Matrix} Returns a fraction
-	   */
-	  var fraction = typed('fraction', {
-	    'number': function (x) {
-	      if (!isFinite(x) || isNaN(x)) {
-	        throw new Error(x + ' cannot be represented as a fraction');
-	      }
-
-	      return new type.Fraction(x);
-	    },
-
-	    'string': function (x) {
-	      return new type.Fraction(x);
-	    },
-
-	    'number, number': function (numerator, denominator) {
-	      return new type.Fraction(numerator, denominator);
-	    },
-
-	    'Fraction': function (x) {
-	      return x; // fractions are immutable
-	    },
-
-	    'Object': function (x) {
-	      return new type.Fraction(x);
-	    },
-
-	    'Array | Matrix': function (x) {
-	      return deepMap(x, fraction);
-	    }
-	  });
-
-	  return fraction;
-	}
-
-	exports.name = 'fraction';
-	exports.factory = factory;
-
-
-/***/ },
-/* 37 */
-/***/ function(module, exports, __webpack_require__) {
-
-	module.exports = [
-	  // types
-	  __webpack_require__(38),
-	  __webpack_require__(46),
-	  __webpack_require__(47),
-	  __webpack_require__(49),
-	  __webpack_require__(58),
-	  __webpack_require__(64),
-	  __webpack_require__(65),
-	  __webpack_require__(66),
-
-	  // construction functions
-	  __webpack_require__(67),
-	  __webpack_require__(51),
-	  __webpack_require__(68)
-	];
-
-
-/***/ },
-/* 38 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var util = __webpack_require__(39);
-
-	var string = util.string;
-
-	var isString = string.isString;
-
-	function factory (type, config, load, typed) {
-	  /**
-	   * @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)
-	   *
-	   */
-	  function Matrix() {
-	    if (!(this instanceof Matrix)) {
-	      throw new SyntaxError('Constructor must be called with the new operator');
-	    }
-	  }
-
-	  /**
-	   * Attach type information
-	   */
-	  Matrix.prototype.type = 'Matrix';
-	  Matrix.prototype.isMatrix = true;
-
-	  /**
-	   * 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 the datatype of the data stored in the matrix.
-	   *
-	   * Usage:
-	   *     var format = matrix.datatype()                   // retrieve matrix datatype
-	   *
-	   * @return {string}           The datatype.
-	   */
-	  Matrix.prototype.datatype = function () {
-	    // must be implemented by each of the Matrix implementations
-	    throw new Error('Cannot invoke datatype on a Matrix interface');
-	  };
-
-	  /**
-	   * Create a new Matrix With the type of the current matrix instance
-	   * @param {Array | Object} data
-	   * @param {string} [datatype]
-	   */
-	  Matrix.prototype.create = function (data, datatype) {
-	    throw new Error('Cannot invoke create 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
-	   * @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/utils/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');
-	  };
-	   
-	  // exports
-	  return Matrix;
-	}
-
-	exports.name = 'Matrix';
-	exports.path = 'type';
-	exports.factory = factory;
-
-
-/***/ },
-/* 39 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	exports.array = __webpack_require__(40);
-	exports['boolean'] = __webpack_require__(44);
-	exports['function'] = __webpack_require__(45);
-	exports.number = __webpack_require__(6);
-	exports.object = __webpack_require__(3);
-	exports.string = __webpack_require__(23);
-	exports.types = __webpack_require__(41);
-	exports.emitter = __webpack_require__(8);
-
-
-/***/ },
-/* 40 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var number = __webpack_require__(6);
-	var string = __webpack_require__(23);
-	var object = __webpack_require__(3);
-	var types = __webpack_require__(41);
-
-	var DimensionError = __webpack_require__(42);
-	var IndexError = __webpack_require__(43);
-
-	/**
-	 * 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;
-
-
-/***/ },
-/* 41 */
-/***/ function(module, exports) {
-
-	'use strict';
-
-	/**
-	 * 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;
-	};
-
-
-/***/ },
-/* 42 */
-/***/ function(module, exports) {
-
-	'use strict';
-
-	/**
-	 * 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');
-	  }
-
-	  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;
-
-
-/***/ },
-/* 43 */
-/***/ function(module, exports) {
-
-	'use strict';
-
-	/**
-	 * 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;
-
-
-/***/ },
-/* 44 */
-/***/ function(module, exports) {
-
-	'use strict';
-
-	/**
-	 * Test whether value is a boolean
-	 * @param {*} value
-	 * @return {boolean} isBoolean
-	 */
-	exports.isBoolean = function(value) {
-	  return typeof value == 'boolean';
-	};
-
-
-/***/ },
-/* 45 */
-/***/ function(module, exports) {
-
-	// function utils
-
-	/*
-	 * Memoize a given function by caching the computed result.
-	 * The cache of a memoized function can be cleared by deleting the `cache`
-	 * property of the function.
-	 *
-	 * @param {function} fn                     The function to be memoized.
-	 *                                          Must be a pure function.
-	 * @param {function(args: Array)} [hasher]  A custom hash builder.
-	 *                                          Is JSON.stringify by default.
-	 * @return {function}                       Returns the memoized function
-	 */
-	exports.memoize = function(fn, hasher) {
-	  return function memoize() {
-	    if (typeof memoize.cache !== 'object') {
-	      memoize.cache = {};
-	    }
-
-	    var args = [];
-	    for (var i = 0; i < arguments.length; i++) {
-	      args[i] = arguments[i];
-	    }
-
-	    var hash = hasher ? hasher(args) : JSON.stringify(args);
-	    if (!(hash in memoize.cache)) {
-	      return memoize.cache[hash] = fn.apply(fn, args);
-	    }
-	    return memoize.cache[hash];
-	  };
-	};
-
-
-/***/ },
-/* 46 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var util = __webpack_require__(39);
-	var DimensionError = __webpack_require__(42);
-
-	var string = util.string;
-	var array = util.array;
-	var object = util.object;
-	var number = util.number;
-
-	var isArray = Array.isArray;
-	var isNumber = number.isNumber;
-	var isInteger = number.isInteger;
-	var isString = string.isString;
-
-	var validateIndex = array.validateIndex;
-
-	function factory (type, config, load, typed) {
-	  var Matrix = load(__webpack_require__(38)); // force loading Matrix (do not use via type.Matrix)
-
-	  function DenseMatrix(data, datatype) {
-	    if (!(this instanceof DenseMatrix))
-	      throw new SyntaxError('Constructor must be called with the new operator');
-	    if (datatype && !isString(datatype))
-	      throw new Error('Invalid datatype: ' + datatype);
-
-	    if (data && data.isMatrix === true) {
-	      // check data is a DenseMatrix
-	      if (data.type === 'DenseMatrix') {
-	        // clone data & size
-	        this._data = object.clone(data._data);
-	        this._size = object.clone(data._size);
-	        this._datatype = datatype || data._datatype;
-	      }
-	      else {
-	        // build data from existing matrix
-	        this._data = data.toArray();
-	        this._size = data.size();
-	        this._datatype = datatype || data._datatype;
-	      }
-	    }
-	    else if (data && isArray(data.data) && isArray(data.size)) {
-	      // initialize fields from JSON representation
-	      this._data = data.data;
-	      this._size = data.size;
-	      this._datatype = datatype || data.datatype;
-	    }
-	    else if (isArray(data)) {
-	      // replace nested Matrices with Arrays
-	      this._data = preprocess(data);
-	      // get the dimensions of the array
-	      this._size = array.size(this._data);
-	      // verify the dimensions of the array, TODO: compute size while processing array
-	      array.validate(this._data, this._size);
-	      // data type unknown
-	      this._datatype = datatype;
-	    }
-	    else if (data) {
-	      // unsupported type
-	      throw new TypeError('Unsupported type of data (' + util.types.type(data) + ')');
-	    }
-	    else {
-	      // nothing provided
-	      this._data = [];
-	      this._size = [0];
-	      this._datatype = datatype;
-	    }
-	  }
-	  
-	  DenseMatrix.prototype = new Matrix();
-
-	  /**
-	   * Attach type information
-	   */
-	  DenseMatrix.prototype.type = 'DenseMatrix';
-	  DenseMatrix.prototype.isDenseMatrix = true;
-
-	  /**
-	   * 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 the datatype of the data stored in the matrix.
-	   *
-	   * Usage:
-	   *     var format = matrix.datatype()                   // retrieve matrix datatype
-	   *
-	   * @return {string}           The datatype.
-	   */
-	  DenseMatrix.prototype.datatype = function () {
-	    return this._datatype;
-	  };
-
-	  /**
-	   * Create a new DenseMatrix
-	   * @param {Array} data
-	   * @param {string} [datatype]
-	   */
-	  DenseMatrix.prototype.create = function (data, datatype) {
-	    return new DenseMatrix(data, datatype);
-	  };
-
-	  /**
-	   * 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 || index.isIndex !== true) {
-	      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), matrix._datatype);
-	    }
-	  }
-	  
-	  /**
-	   * 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.dimension(dim);
-
-	    if (last) {
-	      return range.map(function (i) {
-	        return data[i];
-	      }).valueOf();
-	    }
-	    else {
-	      return range.map(function (i) {
-	        var child = data[i];
-	        return _getSubmatrix(child, index, dims, dim + 1);
-	      }).valueOf();
-	    }
-	  }
-	  
-	  /**
-	   * 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 || index.isIndex !== true) {
-	      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 && submatrix.isMatrix === true) {
-	      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.dimension(dim);
-
-	    if (last) {
-	      range.forEach(function (dataIndex, subIndex) {
-	        validateIndex(dataIndex);
-	        data[dataIndex] = submatrix[subIndex[0]];
-	      });
-	    }
-	    else {
-	      range.forEach(function (dataIndex, subIndex) {
-	        validateIndex(dataIndex);
-	        _setSubmatrix(data[dataIndex], index, submatrix[subIndex[0]], 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),
-	      datatype: this._datatype
-	    });
-	    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),
-	      datatype: this._datatype
-	    });
-	  };
-	  
-	  /**
-	   * 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/utils/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,
-	      datatype: this._datatype
-	    };
-	  };
-	  
-	  /**
-	   * 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.isBigNumber === true)
-	        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 data = [];
-	    
-	    // loop rows
-	    for (var i = 0; i < n; i++) {
-	      data[i] = object.clone(this._data[i + kSub][i + kSuper]);
-	    }
-
-	    // create DenseMatrix
-	    return new DenseMatrix({
-	      data: data,
-	      size: [n],
-	      datatype: this._datatype
-	    });
-	  };
-	  
-	  /**
-	   * 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, datatype) {
-	    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 && s.isBigNumber === true) {
-	        // 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 && k.isBigNumber === true)
-	        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;
-	    }
-	    
-	    if (defaultValue && isString(datatype)) {
-	      // convert defaultValue to the same datatype
-	      defaultValue = typed.convert(defaultValue, datatype);
-	    }
-
-	    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 if (value && value.isMatrix === true) {
-	      // matrix size
-	      var ms = value.size();
-	      // validate matrix
-	      if (ms.length !== 1 || ms[0] !== n) {
-	        // number of values in array must be n
-	        throw new Error('Invalid matrix length');
-	      }
-	      // define function
-	      _value = function (i) {
-	        // return value @ i
-	        return value.get([i]);
-	      };
-	    }
-	    else {
-	      // define function
-	      _value = function () {
-	        // return value
-	        return value;
-	      };
-	    }
-	    
-	    // discover default value if needed
-	    if (!defaultValue) {
-	      // check first value in array
-	      defaultValue = (_value(0) && _value(0).isBigNumber === true) ? new type.BigNumber(0) : 0;
-	    }
-
-	    // 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]
-	    });
-	  };
-
-	  /**
-	   * 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);
-	  };
-	  
-	  /**
-	   * Swap rows i and j in Matrix.
-	   *
-	   * @param {number} i       Matrix row index 1
-	   * @param {number} j       Matrix row index 2
-	   *
-	   * @return {Matrix}        The matrix reference
-	   */
-	  DenseMatrix.prototype.swapRows = function (i, j) {
-	    // check index
-	    if (!isNumber(i) || !isInteger(i) || !isNumber(j) || !isInteger(j)) {
-	      throw new Error('Row index must be positive integers');
-	    }
-	    // check dimensions
-	    if (this._size.length !== 2) {
-	      throw new Error('Only two dimensional matrix is supported');
-	    }
-	    // validate index
-	    validateIndex(i, this._size[0]);
-	    validateIndex(j, this._size[0]);
-
-	    // swap rows
-	    DenseMatrix._swapRows(i, j, this._data);
-	    // return current instance
-	    return this;
-	  };
-
-	  /**
-	   * Swap rows i and j in Dense Matrix data structure.
-	   *
-	   * @param {number} i       Matrix row index 1
-	   * @param {number} j       Matrix row index 2
-	   */
-	  DenseMatrix._swapRows = function (i, j, data) {
-	    // swap values i <-> j
-	    var vi = data[i];
-	    data[i] = data[j];
-	    data[j] = vi;
-	  };
-	   
-	  /**
-	   * 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 && elem.isMatrix === true) {
-	        data[i] = preprocess(elem.valueOf());
-	      }
-	    }
-
-	    return data;
-	  }
-
-	  // register this type in the base class Matrix
-	  type.Matrix._storage.dense = DenseMatrix;
-	  type.Matrix._storage['default'] = DenseMatrix;
-
-	  // exports
-	  return DenseMatrix;
-	}
-
-	exports.name = 'DenseMatrix';
-	exports.path = 'type';
-	exports.factory = factory;
-	exports.lazy = false;  // no lazy loading, as we alter type.Matrix._storage
-
-/***/ },
-/* 47 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var util = __webpack_require__(39);
-	var DimensionError = __webpack_require__(42);
-
-	var array = util.array;
-	var object = util.object;
-	var string = util.string;
-	var number = util.number;
-
-	var isArray = Array.isArray;
-	var isNumber = number.isNumber;
-	var isInteger = number.isInteger;
-	var isString = string.isString;
-
-	var validateIndex = array.validateIndex;
-
-	function factory (type, config, load, typed) {
-	  var Matrix = load(__webpack_require__(38)); // force loading Matrix (do not use via type.Matrix)
-	  var equalScalar = load(__webpack_require__(48));
-
-	  /**
-	   * Sparse Matrix implementation. This type implements a Compressed Column Storage format
-	   * for sparse matrices.
-	   */
-	  function SparseMatrix(data, datatype) {
-	    if (!(this instanceof SparseMatrix))
-	      throw new SyntaxError('Constructor must be called with the new operator');
-	    if (datatype && !isString(datatype))
-	      throw new Error('Invalid datatype: ' + datatype);
-	    
-	    if (data && data.isMatrix === true) {
-	      // create from matrix
-	      _createFromMatrix(this, data, datatype);
-	    }
-	    else if (data && 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;
-	      this._datatype = datatype || data.datatype;
-	    }
-	    else if (isArray(data)) {
-	      // create from array
-	      _createFromArray(this, data, datatype);
-	    }
-	    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, 0];
-	      this._datatype = datatype;
-	    }
-	  }
-	  
-	  var _createFromMatrix = function (matrix, source, datatype) {
-	    // check matrix type
-	    if (source.type === 'SparseMatrix') {
-	      // clone arrays
-	      matrix._values = source._values ? object.clone(source._values) : undefined;
-	      matrix._index = object.clone(source._index);
-	      matrix._ptr = object.clone(source._ptr);
-	      matrix._size = object.clone(source._size);
-	      matrix._datatype = datatype || source._datatype;
-	    }
-	    else {
-	      // build from matrix data
-	      _createFromArray(matrix, source.valueOf(), datatype || source._datatype);
-	    }
-	  };
-	  
-	  var _createFromArray = function (matrix, data, datatype) {
-	    // initialize fields
-	    matrix._values = [];
-	    matrix._index = [];
-	    matrix._ptr = [];
-	    matrix._datatype = datatype;
-	    // discover rows & columns, do not use math.size() to avoid looping array twice
-	    var rows = data.length;
-	    var columns = 0;
-	    
-	    // equal signature to use
-	    var eq = equalScalar;
-	    // zero value
-	    var zero = 0;
-	    
-	    if (isString(datatype)) {
-	      // find signature that matches (datatype, datatype)
-	      eq = typed.find(equalScalar, [datatype, datatype]) || equalScalar;
-	      // convert 0 to the same datatype
-	      zero = typed.convert(0, datatype);
-	    }
-
-	    // check we have rows (empty array)
-	    if (rows > 0) {
-	      // column index
-	      var j = 0;
-	      do {
-	        // store pointer to values index
-	        matrix._ptr.push(matrix._index.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 (!eq(v, zero)) {
-	                // 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 (!eq(row, zero)) {
-	              // 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._index.length);
-	    // size
-	    matrix._size = [rows, columns];
-	  };
-	  
-	  SparseMatrix.prototype = new Matrix();
-
-	  /**
-	   * Attach type information
-	   */
-	  SparseMatrix.prototype.type = 'SparseMatrix';
-	  SparseMatrix.prototype.isSparseMatrix = true;
-
-	  /**
-	   * Get the storage format used by the matrix.
-	   *
-	   * Usage:
-	   *     var format = matrix.storage()                   // retrieve storage format
-	   *
-	   * @return {string}           The storage format.
-	   */
-	  SparseMatrix.prototype.storage = function () {
-	    return 'sparse';
-	  };
-
-	  /**
-	   * Get the datatype of the data stored in the matrix.
-	   *
-	   * Usage:
-	   *     var format = matrix.datatype()                   // retrieve matrix datatype
-	   *
-	   * @return {string}           The datatype.
-	   */
-	  SparseMatrix.prototype.datatype = function () {
-	    return this._datatype;
-	  };
-
-	  /**
-	   * Create a new SparseMatrix
-	   * @param {Array} data
-	   * @param {string} [datatype]
-	   */
-	  SparseMatrix.prototype.create = function (data, datatype) {
-	    return new SparseMatrix(data, datatype);
-	  };
-
-	  /**
-	   * Get the matrix density.
-	   *
-	   * Usage:
-	   *     var density = matrix.density()                   // retrieve matrix density
-	   *
-	   * @return {number}           The matrix density.
-	   */
-	  SparseMatrix.prototype.density = function () {
-	    // rows & columns
-	    var rows = this._size[0];
-	    var columns = this._size[1];
-	    // calculate density
-	    return rows !== 0 && columns !== 0 ? (this._index.length / (rows * columns)) : 0;
-	  };
-	  
-	  /**
-	   * 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.
-	   */
-	  SparseMatrix.prototype.subset = function (index, replacement, defaultValue) {	
-		// check it is a pattern matrix
-	    if (!this._values)
-	      throw new Error('Cannot invoke subset on a Pattern only matrix');
-
-	    // 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, idx) {
-	    // check idx
-	    if (!idx || idx.isIndex !== true) {
-	      throw new TypeError('Invalid index');
-	    }
-
-	    var isScalar = idx.isScalar();
-	    if (isScalar) {
-	      // return a scalar
-	      return matrix.get(idx.min());
-	    }
-	    // validate dimensions
-	    var size = idx.size();
-	    if (size.length != matrix._size.length) {
-	      throw new DimensionError(size.length, matrix._size.length);
-	    }
-
-	    // vars
-	    var i, ii, k, kk;
-	    
-	    // validate if any of the ranges in the index is out of range
-	    var min = idx.min();
-	    var max = idx.max();
-	    for (i = 0, ii = matrix._size.length; i < ii; i++) {
-	      validateIndex(min[i], matrix._size[i]);
-	      validateIndex(max[i], matrix._size[i]);
-	    }
-	    
-	    // matrix arrays
-	    var mvalues = matrix._values;
-	    var mindex = matrix._index;
-	    var mptr = matrix._ptr;
-	        
-	    // rows & columns dimensions for result matrix
-	    var rows = idx.dimension(0);
-	    var columns = idx.dimension(1);
-	    
-	    // workspace & permutation vector
-	    var w = [];
-	    var pv = [];
-	    
-	    // loop rows in resulting matrix
-	    rows.forEach(function (i, r) {
-	      // update permutation vector
-	      pv[i] = r[0];  
-	      // mark i in workspace
-	      w[i] = true;
-	    });
-
-	    // result matrix arrays
-	    var values = mvalues ? [] : undefined;
-	    var index = [];
-	    var ptr = [];
-	        
-	    // loop columns in result matrix
-	    columns.forEach(function (j) {
-	      // update ptr
-	      ptr.push(index.length);
-	      // loop values in column j
-	      for (k = mptr[j], kk = mptr[j + 1]; k < kk; k++) {
-	        // row
-	        i = mindex[k];
-	        // check row is in result matrix
-	        if (w[i] === true) {
-	          // push index
-	          index.push(pv[i]);
-	          // check we need to process values
-	          if (values)
-	            values.push(mvalues[k]);
-	        }
-	      }
-	    });
-	    // update ptr
-	    ptr.push(index.length);
-	    
-	    // return matrix
-	    return new SparseMatrix({
-	      values: values,
-	      index: index,
-	      ptr: ptr,
-	      size: size,
-	      datatype: matrix._datatype
-	    });
-	  };
-	  
-	  var _setsubset = function (matrix, index, submatrix, defaultValue) {
-	    // check index
-	    if (!index || index.isIndex !== true) {
-	      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 && submatrix.isMatrix === true) {
-	      // 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
-	   */
-	  SparseMatrix.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 it is a pattern matrix
-	    if (!this._values)
-	      throw new Error('Cannot invoke get on a Pattern only matrix');
-
-	    // 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 {SparseMatrix} self
-	   */
-	  SparseMatrix.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);
-
-	    // check it is a pattern matrix
-	    if (!this._values)
-	      throw new Error('Cannot invoke set on a Pattern only matrix');
-	      
-	    // row and column
-	    var i = index[0];
-	    var j = index[1];
-
-	    // rows & columns
-	    var rows = this._size[0];
-	    var columns = this._size[1];
-	    
-	    // equal signature to use
-	    var eq = equalScalar;
-	    // zero value
-	    var zero = 0;
-
-	    if (isString(this._datatype)) {
-	      // find signature that matches (datatype, datatype)
-	      eq = typed.find(equalScalar, [this._datatype, this._datatype]) || equalScalar;
-	      // convert 0 to the same datatype
-	      zero = typed.convert(0, this._datatype);
-	    }
-
-	    // 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 (!eq(v, zero)) {
-	        // 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)
-	      return bottom;
-	    // loop rows [top, bottom[
-	    for (var r = top; r < bottom; r++) {
-	      // check we found value index
-	      if (index[r] === i)
-	        return r;
-	    }
-	    // we did not find row
-	    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
-	   */
-	  SparseMatrix.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;
-	    
-	    // equal signature to use
-	    var eq = equalScalar;
-	    // zero value
-	    var zero = 0;
-
-	    if (isString(matrix._datatype)) {
-	      // find signature that matches (datatype, datatype)
-	      eq = typed.find(equalScalar, [matrix._datatype, matrix._datatype]) || equalScalar;
-	      // convert 0 to the same datatype
-	      zero = typed.convert(0, matrix._datatype);
-	      // convert value to the same datatype
-	      value = typed.convert(value, matrix._datatype);
-	    }
-	    
-	    // should we insert the value?
-	    var ins = !eq(value, zero);
-
-	    // 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 {SparseMatrix} clone
-	   */
-	  SparseMatrix.prototype.clone = function () {
-	    var m = new SparseMatrix({
-	      values: this._values ? object.clone(this._values) : undefined,
-	      index: object.clone(this._index),
-	      ptr: object.clone(this._ptr),
-	      size: object.clone(this._size),
-	      datatype: this._datatype
-	    });
-	    return m;
-	  };
-	  
-	  /**
-	   * Retrieve the size of the matrix.
-	   * @returns {number[]} size
-	   */
-	  SparseMatrix.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 {SparseMatrix} matrix
-	   */
-	  SparseMatrix.prototype.map = function (callback, skipZeros) {
-	    // check it is a pattern matrix
-	    if (!this._values)
-	      throw new Error('Cannot invoke map on a Pattern only matrix');
-	    // 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 = [];
-	    
-	    // equal signature to use
-	    var eq = equalScalar;
-	    // zero value
-	    var zero = 0;
-
-	    if (isString(matrix._datatype)) {
-	      // find signature that matches (datatype, datatype)
-	      eq = typed.find(equalScalar, [matrix._datatype, matrix._datatype]) || equalScalar;
-	      // convert 0 to the same datatype
-	      zero = typed.convert(0, matrix._datatype);
-	    }
-	    
-	    // invoke callback
-	    var invoke = function (v, x, y) {
-	      // invoke callback
-	      v = callback(v, x, y);
-	      // check value != 0
-	      if (!eq(v, zero)) {
-	        // 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 sparse matrix
-	    return new SparseMatrix({
-	      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.
-	   */
-	  SparseMatrix.prototype.forEach = function (callback, skipZeros) {
-	    // check it is a pattern matrix
-	    if (!this._values)
-	      throw new Error('Cannot invoke forEach on a Pattern only matrix');
-	    // 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 SparseMatrix
-	   * @returns {Array} array
-	   */
-	  SparseMatrix.prototype.toArray = function () {
-	    return _toArray(this._values, this._index, this._ptr, this._size, true);
-	  };
-
-	  /**
-	   * Get the primitive value of the SparseMatrix: a two dimensions array
-	   * @returns {Array} array
-	   */
-	  SparseMatrix.prototype.valueOf = function () {
-	    return _toArray(this._values, this._index, this._ptr, this._size, false);
-	  };
-	  
-	  var _toArray = function (values, index, ptr, size, copy) {    
-	    // rows and columns
-	    var rows = size[0];
-	    var columns = size[1];
-	    // result
-	    var a = [];
-	    // vars
-	    var i, j;
-	    // initialize array
-	    for (i = 0; i < rows; i++) {
-	      a[i] = [];
-	      for (j = 0; j < columns; j++)
-	        a[i][j] = 0;
-	    }
-
-	    // loop columns
-	    for (j = 0; j < columns; j++) {
-	      // k0 <= k < k1 where k0 = _ptr[j] && k1 = _ptr[j+1]
-	      var k0 = ptr[j];
-	      var k1 = ptr[j + 1];
-	      // loop k within [k0, k1[
-	      for (var k = k0; k < k1; k++) {
-	        // row index
-	        i = index[k];
-	        // set value (use one for pattern matrix)
-	        a[i][j] = values ? (copy ? object.clone(values[k]) : values[k]) : 1;
-	      }
-	    }
-	    return a;
-	  };
-	  
-	  /**
-	   * Get a string representation of the matrix, with optional formatting options.
-	   * @param {Object | number | Function} [options]  Formatting options. See
-	   *                                                lib/utils/number:format for a
-	   *                                                description of the available
-	   *                                                options.
-	   * @returns {string} str
-	   */
-	  SparseMatrix.prototype.format = function (options) {
-	    // rows and columns
-	    var rows = this._size[0];
-	    var columns = this._size[1];
-	    // density
-	    var density = this.density();
-	    // rows & columns
-	    var str = 'Sparse Matrix [' + string.format(rows, options) + ' x ' + string.format(columns, options) + '] density: ' + string.format(density, 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) + ') ==> ' + (this._values ? string.format(this._values[k], options) : 'X');
-	      }
-	    }
-	    return str;
-	  };
-	  
-	  /**
-	   * Get a string representation of the matrix
-	   * @returns {string} str
-	   */
-	  SparseMatrix.prototype.toString = function () {
-	    return string.format(this.toArray());
-	  };
-	  
-	  /**
-	   * Get a JSON representation of the matrix
-	   * @returns {Object}
-	   */
-	  SparseMatrix.prototype.toJSON = function () {
-	    return {
-	      mathjs: 'SparseMatrix',
-	      values: this._values,
-	      index: this._index,
-	      ptr: this._ptr,
-	      size: this._size,
-	      datatype: this._datatype
-	    };
-	  };
-
-	  /**
-	   * Get the kth Matrix diagonal.
-	   *
-	   * @param {number | BigNumber} [k=0]     The kth diagonal where the vector will retrieved.
-	   *
-	   * @returns {Matrix}                     The matrix vector with the diagonal values.
-	   */
-	  SparseMatrix.prototype.diagonal = function(k) {
-	    // validate k if any
-	    if (k) {
-	      // convert BigNumber to a number
-	      if (k.isBigNumber === true)
-	        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 arrays
-	    var values = [];
-	    var index = [];
-	    var ptr = [];
-	    // initial ptr value
-	    ptr[0] = 0;
-	    // 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];
-	      // 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) {
-	          // value on this column
-	          values.push(object.clone(this._values[x]));
-	          // store row
-	          index[values.length - 1] = i - kSub;
-	          // exit loop
-	          break;
-	        }
-	      }
-	    }
-	    // close ptr
-	    ptr.push(values.length);
-	    // return matrix
-	    return new SparseMatrix({
-	      values: values,
-	      index: index,
-	      ptr: ptr,
-	      size: [n, 1]
-	    });
-	  };
-	  
-	  /**
-	   * Generate a matrix from a JSON object
-	   * @param {Object} json  An object structured like
-	   *                       `{"mathjs": "SparseMatrix", "values": [], "index": [], "ptr": [], "size": []}`,
-	   *                       where mathjs is optional
-	   * @returns {SparseMatrix}
-	   */
-	  SparseMatrix.fromJSON = function (json) {
-	    return new SparseMatrix(json);
-	  };
-
-	  /**
-	   * Create a diagonal matrix.
-	   *
-	   * @param {Array} size                       The matrix size.
-	   * @param {number | Array | Matrix } value   The values for the diagonal.
-	   * @param {number | BigNumber} [k=0]         The kth diagonal where the vector will be filled in.
-	   * @param {string} [datatype]                The Matrix datatype, values must be of this datatype.
-	   *
-	   * @returns {SparseMatrix}
-	   */
-	  SparseMatrix.diagonal = function (size, value, k, defaultValue, datatype) {
-	    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 && s.isBigNumber === true) {
-	        // 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.isBigNumber === true)
-	        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;
-	    }
-
-	    // equal signature to use
-	    var eq = equalScalar;
-	    // zero value
-	    var zero = 0;
-
-	    if (isString(datatype)) {
-	      // find signature that matches (datatype, datatype)
-	      eq = typed.find(equalScalar, [datatype, datatype]) || equalScalar;
-	      // convert 0 to the same datatype
-	      zero = typed.convert(0, datatype);
-	    }
-	    
-	    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 if (value && value.isMatrix === true) {
-	      // matrix size
-	      var ms = value.size();
-	      // validate matrix
-	      if (ms.length !== 1 || ms[0] !== n) {
-	        // number of values in array must be n
-	        throw new Error('Invalid matrix length');
-	      }
-	      // define function
-	      _value = function (i) {
-	        // return value @ i
-	        return value.get([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 (!eq(v, zero)) {
-	          // column
-	          index.push(i + kSub);
-	          // add value
-	          values.push(v);
-	        }
-	      }
-	    }
-	    // last value should be number of values
-	    ptr.push(values.length);
-	    // create SparseMatrix
-	    return new SparseMatrix({
-	      values: values,
-	      index: index,
-	      ptr: ptr,
-	      size: [rows, columns]
-	    });
-	  };
-	  
-	  /**
-	   * Swap rows i and j in Matrix.
-	   *
-	   * @param {number} i       Matrix row index 1
-	   * @param {number} j       Matrix row index 2
-	   *
-	   * @return {Matrix}        The matrix reference
-	   */
-	  SparseMatrix.prototype.swapRows = function (i, j) {
-	    // check index
-	    if (!isNumber(i) || !isInteger(i) || !isNumber(j) || !isInteger(j)) {
-	      throw new Error('Row index must be positive integers');
-	    }
-	    // check dimensions
-	    if (this._size.length !== 2) {
-	      throw new Error('Only two dimensional matrix is supported');
-	    }
-	    // validate index
-	    validateIndex(i, this._size[0]);
-	    validateIndex(j, this._size[0]);
-	    
-	    // swap rows
-	    SparseMatrix._swapRows(i, j, this._size[1], this._values, this._index, this._ptr);
-	    // return current instance
-	    return this;
-	  };
-	  
-	  /**
-	   * Loop rows with data in column j.
-	   *
-	   * @param {number} j            Column
-	   * @param {Array} values        Matrix values
-	   * @param {Array} index         Matrix row indeces
-	   * @param {Array} ptr           Matrix column pointers
-	   * @param {Function} callback   Callback function invoked for every row in column j
-	   */
-	  SparseMatrix._forEachRow = function (j, values, index, ptr, callback) {
-	    // indeces for column j
-	    var k0 = ptr[j];
-	    var k1 = ptr[j + 1];
-	    // loop
-	    for (var k = k0; k < k1; k++) {
-	      // invoke callback
-	      callback(index[k], values[k]);
-	    }
-	  };
-	  
-	  /**
-	   * Swap rows x and y in Sparse Matrix data structures.
-	   *
-	   * @param {number} x         Matrix row index 1
-	   * @param {number} y         Matrix row index 2
-	   * @param {number} columns   Number of columns in matrix
-	   * @param {Array} values     Matrix values
-	   * @param {Array} index      Matrix row indeces
-	   * @param {Array} ptr        Matrix column pointers
-	   */
-	  SparseMatrix._swapRows = function (x, y, columns, values, index, ptr) {
-	    // loop columns
-	    for (var j = 0; j < columns; j++) {
-	      // k0 <= k < k1 where k0 = _ptr[j] && k1 = _ptr[j+1]
-	      var k0 = ptr[j];
-	      var k1 = ptr[j + 1];
-	      // find value index @ x
-	      var kx = _getValueIndex(x, k0, k1, index);
-	      // find value index @ x
-	      var ky = _getValueIndex(y, k0, k1, index);
-	      // check both rows exist in matrix
-	      if (kx < k1 && ky < k1 && index[kx] === x && index[ky] === y) {
-	        // swap values (check for pattern matrix)
-	        if (values) {
-	          var v = values[kx];
-	          values[kx] = values[ky];
-	          values[ky] = v;
-	        }
-	        // next column
-	        continue;
-	      }
-	      // check x row exist & no y row
-	      if (kx < k1 && index[kx] === x && (ky >= k1 || index[ky] !== y)) {
-	        // value @ x (check for pattern matrix)
-	        var vx = values ? values[kx] : undefined;
-	        // insert value @ y
-	        index.splice(ky, 0, y);
-	        if (values)
-	          values.splice(ky, 0, vx);        
-	        // remove value @ x (adjust array index if needed)
-	        index.splice(ky <= kx ? kx + 1 : kx, 1);
-	        if (values)
-	          values.splice(ky <= kx ? kx + 1 : kx, 1);
-	        // next column
-	        continue;
-	      }
-	      // check y row exist & no x row
-	      if (ky < k1 && index[ky] === y && (kx >= k1 || index[kx] !== x)) {
-	        // value @ y (check for pattern matrix)
-	        var vy = values ? values[ky] : undefined;
-	        // insert value @ x
-	        index.splice(kx, 0, x);
-	        if (values)
-	          values.splice(kx, 0, vy);
-	        // remove value @ y (adjust array index if needed)
-	        index.splice(kx <= ky ? ky + 1 : ky, 1);
-	        if (values)
-	          values.splice(kx <= ky ? ky + 1 : ky, 1);
-	      }
-	    }
-	  };
-
-	  // register this type in the base class Matrix
-	  type.Matrix._storage.sparse = SparseMatrix;
-
-	  return SparseMatrix;
-	}
-
-	exports.name = 'SparseMatrix';
-	exports.path = 'type';
-	exports.factory = factory;
-	exports.lazy = false;  // no lazy loading, as we alter type.Matrix._storage
-
-
-/***/ },
-/* 48 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var nearlyEqual = __webpack_require__(6).nearlyEqual;
-
-	function factory (type, config, load, typed) {
-	  
-	  /**
-	   * Test whether two values are equal.
-	   *
-	   * @param  {number | BigNumber | Fraction | boolean | Complex | Unit} x   First value to compare
-	   * @param  {number | BigNumber | Fraction | boolean | Complex} y          Second value to compare
-	   * @return {boolean}                                                  Returns true when the compared values are equal, else returns false
-	   * @private
-	   */
-	  var equalScalar = typed('equalScalar', {
-
-	    'boolean, boolean': function (x, y) {
-	      return x === y;
-	    },
-
-	    'number, number': function (x, y) {
-	      return x === y || nearlyEqual(x, y, config.epsilon);
-	    },
-
-	    'BigNumber, BigNumber': function (x, y) {
-	      return x.eq(y);
-	    },
-
-	    'Fraction, Fraction': function (x, y) {
-	      return x.equals(y);
-	    },
-
-	    'Complex, Complex': function (x, y) {
-	      return (x.re === y.re || nearlyEqual(x.re, y.re, config.epsilon)) &&
-	        (x.im === y.im || nearlyEqual(x.im, y.im, config.epsilon));
-	    },
-
-	    'Unit, Unit': function (x, y) {
-	      if (!x.equalBase(y)) {
-	        throw new Error('Cannot compare units with different base');
-	      }
-	      return x.value === y.value || nearlyEqual(x.value, y.value, config.epsilon);
-	    },
-
-	    'string, string': function (x, y) {
-	      return x === y;
-	    }
-	  });
-	  
-	  return equalScalar;
-	}
-
-	exports.factory = factory;
-
-
-/***/ },
-/* 49 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	function factory (type, config, load) {
-	  
-	  var add = load(__webpack_require__(50));
-	  var equalScalar = load(__webpack_require__(48));
-	  
-	  /**
-	   * An ordered Sparse Accumulator is a representation for a sparse vector that includes a dense array 
-	   * of the vector elements and an ordered list of non-zero elements.
-	   */
-	  function Spa() {
-	    if (!(this instanceof Spa))
-	      throw new SyntaxError('Constructor must be called with the new operator');
-	    
-	    // allocate vector, TODO use typed arrays
-	    this._values = [];
-	    this._heap = new type.FibonacciHeap();
-	  }
-
-	  /**
-	   * Attach type information
-	   */
-	  Spa.prototype.type = 'Spa';
-	  Spa.prototype.isSpa = true;
-
-	  /**
-	   * Set the value for index i.
-	   *
-	   * @param {number} i                       The index
-	   * @param {number | BigNumber | Complex}   The value at index i
-	   */
-	  Spa.prototype.set = function (i, v) {
-	    // check we have a value @ i
-	    if (!this._values[i]) {
-	      // insert in heap
-	      var node = this._heap.insert(i, v);
-	      // set the value @ i
-	      this._values[i] = node;
-	    }
-	    else {
-	      // update the value @ i
-	      this._values[i].value = v;
-	    }
-	  };
-	  
-	  Spa.prototype.get = function (i) {
-	    var node = this._values[i];
-	    if (node)
-	      return node.value;
-	    return 0;
-	  };
-	  
-	  Spa.prototype.accumulate = function (i, v) {
-	    // node @ i
-	    var node = this._values[i];
-	    if (!node) {
-	      // insert in heap
-	      node = this._heap.insert(i, v);
-	      // initialize value
-	      this._values[i] = node;
-	    }
-	    else {
-	      // accumulate value
-	      node.value = add(node.value, v);
-	    }
-	  };
-	  
-	  Spa.prototype.forEach = function (from, to, callback) {
-	    // references
-	    var heap = this._heap;
-	    var values = this._values;
-	    // nodes
-	    var nodes = [];
-	    // node with minimum key, save it
-	    var node = heap.extractMinimum();
-	    if (node)
-	      nodes.push(node);
-	    // extract nodes from heap (ordered)
-	    while (node && node.key <= to) {
-	      // check it is in range
-	      if (node.key >= from) {
-	        // check value is not zero
-	        if (!equalScalar(node.value, 0)) {
-	          // invoke callback
-	          callback(node.key, node.value, this);
-	        }
-	      }
-	      // extract next node, save it
-	      node = heap.extractMinimum();
-	      if (node)
-	        nodes.push(node);
-	    }
-	    // reinsert all nodes in heap
-	    for (var i = 0; i < nodes.length; i++) {
-	      // current node
-	      var n = nodes[i];
-	      // insert node in heap
-	      node = heap.insert(n.key, n.value);
-	      // update values
-	      values[node.key] = node;
-	    }
-	  };
-	  
-	  Spa.prototype.swap = function (i, j) {
-	    // node @ i and j
-	    var nodei = this._values[i];
-	    var nodej = this._values[j];
-	    // check we need to insert indeces
-	    if (!nodei && nodej) {
-	      // insert in heap
-	      nodei = this._heap.insert(i, nodej.value);
-	      // remove from heap
-	      this._heap.remove(nodej);
-	      // set values
-	      this._values[i] = nodei;
-	      this._values[j] = undefined;
-	    }
-	    else if (nodei && !nodej) {
-	      // insert in heap
-	      nodej = this._heap.insert(j, nodei.value);
-	      // remove from heap
-	      this._heap.remove(nodei);
-	      // set values
-	      this._values[j] = nodej;
-	      this._values[i] = undefined;
-	    }
-	    else if (nodei && nodej) {
-	      // swap values
-	      var v = nodei.value;
-	      nodei.value = nodej.value;
-	      nodej.value = v;
-	    }
-	  };
-	  
-	  return Spa;
-	}
-
-	exports.name = 'Spa';
-	exports.path = 'type';
-	exports.factory = factory;
-
-
-/***/ },
-/* 50 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var extend = __webpack_require__(3).extend;
-
-	function factory (type, config, load, typed) {
-
-	  var matrix = load(__webpack_require__(51));
-	  var addScalar = load(__webpack_require__(52));
-	  var latex = __webpack_require__(30);
-	  
-	  var algorithm01 = load(__webpack_require__(53));
-	  var algorithm04 = load(__webpack_require__(54));
-	  var algorithm10 = load(__webpack_require__(55));
-	  var algorithm13 = load(__webpack_require__(56));
-	  var algorithm14 = load(__webpack_require__(57));
-
-	  /**
-	   * 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
-	   *
-	   *    math.add("2.3", "4");         // returns number 6.3
-	   *
-	   * See also:
-	   *
-	   *    subtract
-	   *
-	   * @param  {number | BigNumber | Fraction | Complex | Unit | Array | Matrix} x First value to add
-	   * @param  {number | BigNumber | Fraction | Complex | Unit | Array | Matrix} y Second value to add
-	   * @return {number | BigNumber | Fraction | Complex | Unit | Array | Matrix} Sum of `x` and `y`
-	   */
-	  var add = typed('add', extend({
-	    // we extend the signatures of addScalar with signatures dealing with matrices
-
-	    'Matrix, Matrix': function (x, y) {
-	      // result
-	      var c;
-	      
-	      // process matrix storage
-	      switch (x.storage()) {
-	        case 'sparse':
-	          switch (y.storage()) {
-	            case 'sparse':
-	              // sparse + sparse
-	              c = algorithm04(x, y, addScalar);
-	              break;
-	            default:
-	              // sparse + dense
-	              c = algorithm01(y, x, addScalar, true);
-	              break;
-	          }
-	          break;
-	        default:
-	          switch (y.storage()) {
-	            case 'sparse':
-	              // dense + sparse
-	              c = algorithm01(x, y, addScalar, false);
-	              break;
-	            default:
-	              // dense + dense
-	              c = algorithm13(x, y, addScalar);
-	              break;
-	          }
-	          break;
-	      }
-	      return c;
-	    },
-	    
-	    'Array, Array': function (x, y) {
-	      // use matrix implementation
-	      return add(matrix(x), matrix(y)).valueOf();
-	    },
-	    
-	    'Array, Matrix': function (x, y) {
-	      // use matrix implementation
-	      return add(matrix(x), y);
-	    },
-	    
-	    'Matrix, Array': function (x, y) {
-	      // use matrix implementation
-	      return add(x, matrix(y));
-	    },
-	    
-	    'Matrix, any': function (x, y) {
-	      // result
-	      var c;
-	      // check storage format
-	      switch (x.storage()) {
-	        case 'sparse':
-	          c = algorithm10(x, y, addScalar, false);
-	          break;
-	        default:
-	          c = algorithm14(x, y, addScalar, false);
-	          break;
-	      }
-	      return c;
-	    },
-	    
-	    'any, Matrix': function (x, y) {
-	      // result
-	      var c;
-	      // check storage format
-	      switch (y.storage()) {
-	        case 'sparse':
-	          c = algorithm10(y, x, addScalar, true);
-	          break;
-	        default:
-	          c = algorithm14(y, x, addScalar, true);
-	          break;
-	      }
-	      return c;
-	    },
-	    
-	    'Array, any': function (x, y) {
-	      // use matrix implementation
-	      return algorithm14(matrix(x), y, addScalar, false).valueOf();
-	    },
-
-	    'any, Array': function (x, y) {
-	      // use matrix implementation
-	      return algorithm14(matrix(y), x, addScalar, true).valueOf();
-	    }
-	  }, addScalar.signatures));
-
-	  add.toTex = '\\left(${args[0]}' + latex.operators['add'] + '${args[1]}\\right)';
-	  
-	  return add;
-	}
-
-	exports.name = 'add';
-	exports.factory = factory;
-
-
-/***/ },
-/* 51 */
-/***/ 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(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:
-	   *
-	   *    var m = math.matrix([[1, 2], [3, 4]]);
-	   *    m.size();                        // Array [2, 2]
-	   *    m.resize([3, 2], 5);
-	   *    m.valueOf();                     // Array [[1, 2], [3, 4], [5, 5]]
-	   *    m.get([1, 0])                    // number 3
-	   *
-	   * See also:
-	   *
-	   *    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
-	   */
-	  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 M = type.Matrix.storage(format || 'default');
-
-	    // create instance
-	    return new M(data, datatype);
-	  }
-	}
-
-	exports.name = 'matrix';
-	exports.factory = factory;
-
-
-/***/ },
-/* 52 */
-/***/ 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;
-
-
-/***/ },
-/* 53 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var DimensionError = __webpack_require__(42);
-
-	function factory (type, config, load, typed) {
-
-	  var DenseMatrix = type.DenseMatrix;
-
-	  /**
-	   * Iterates over SparseMatrix nonzero items and invokes the callback function f(Dij, Sij). 
-	   * Callback function invoked NNZ times (number of nonzero items in SparseMatrix).
-	   *
-	   *
-	   *          ┌  f(Dij, Sij)  ; S(i,j) !== 0
-	   * C(i,j) = ┤
-	   *          └  Dij          ; otherwise
-	   *
-	   *
-	   * @param {Matrix}   denseMatrix       The DenseMatrix instance (D)
-	   * @param {Matrix}   sparseMatrix      The SparseMatrix instance (S)
-	   * @param {Function} callback          The f(Dij,Sij) operation to invoke, where Dij = DenseMatrix(i,j) and Sij = SparseMatrix(i,j)
-	   * @param {boolean}  inverse           A true value indicates callback should be invoked f(Sij,Dij)
-	   *
-	   * @return {Matrix}                    DenseMatrix (C)
-	   *
-	   * see https://github.com/josdejong/mathjs/pull/346#issuecomment-97477571
-	   */
-	  var algorithm01 = function (denseMatrix, sparseMatrix, callback, inverse) {
-	    // dense matrix arrays
-	    var adata = denseMatrix._data;
-	    var asize = denseMatrix._size;
-	    var adt = denseMatrix._datatype;
-	    // sparse matrix arrays
-	    var bvalues = sparseMatrix._values;
-	    var bindex = sparseMatrix._index;
-	    var bptr = sparseMatrix._ptr;
-	    var bsize = sparseMatrix._size;
-	    var bdt = sparseMatrix._datatype;
-
-	    // validate dimensions
-	    if (asize.length !== bsize.length)
-	      throw new DimensionError(asize.length, bsize.length);
-
-	    // check rows & columns
-	    if (asize[0] !== bsize[0] || asize[1] !== bsize[1])
-	      throw new RangeError('Dimension mismatch. Matrix A (' + asize + ') must match Matrix B (' + bsize + ')');
-
-	    // sparse matrix cannot be a Pattern matrix
-	    if (!bvalues)
-	      throw new Error('Cannot perform operation on Dense Matrix and Pattern Sparse Matrix');
-
-	    // rows & columns
-	    var rows = asize[0];
-	    var columns = asize[1];
-
-	    // process data types
-	    var dt = typeof adt === 'string' && adt === bdt ? adt : undefined;
-	    // callback function
-	    var cf = dt ? typed.find(callback, [dt, dt]) : callback;
-
-	    // vars
-	    var i, j;
-	    
-	    // result (DenseMatrix)
-	    var cdata = [];
-	    // initialize c
-	    for (i = 0; i < rows; i++)
-	      cdata[i] = [];      
-	    
-	    // workspace
-	    var x = [];
-	    // marks indicating we have a value in x for a given column
-	    var w = [];
-
-	    // loop columns in b
-	    for (j = 0; j < columns; j++) {
-	      // column mark
-	      var mark = j + 1;
-	      // values in column j
-	      for (var k0 = bptr[j], k1 = bptr[j + 1], k = k0; k < k1; k++) {
-	        // row
-	        i = bindex[k];
-	        // update workspace
-	        x[i] = inverse ? cf(bvalues[k], adata[i][j]) : cf(adata[i][j], bvalues[k]);
-	        // mark i as updated
-	        w[i] = mark;
-	      }
-	      // loop rows
-	      for (i = 0; i < rows; i++) {
-	        // check row is in workspace
-	        if (w[i] === mark) {
-	          // c[i][j] was already calculated
-	          cdata[i][j] = x[i];
-	        }
-	        else {
-	          // item does not exist in S
-	          cdata[i][j] = adata[i][j];
-	        }
-	      }
-	    }
-
-	    // return dense matrix
-	    return new DenseMatrix({
-	      data: cdata,
-	      size: [rows, columns],
-	      datatype: dt
-	    });
-	  };
-	  
-	  return algorithm01;
-	}
-
-	exports.name = 'algorithm01';
-	exports.factory = factory;
-
-
-/***/ },
-/* 54 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var DimensionError = __webpack_require__(42);
-
-	function factory (type, config, load, typed) {
-
-	  var equalScalar = load(__webpack_require__(48));
-
-	  var SparseMatrix = type.SparseMatrix;
-
-	  /**
-	   * Iterates over SparseMatrix A and SparseMatrix B nonzero items and invokes the callback function f(Aij, Bij). 
-	   * Callback function invoked MAX(NNZA, NNZB) times
-	   *
-	   *
-	   *          ┌  f(Aij, Bij)  ; A(i,j) !== 0 && B(i,j) !== 0
-	   * C(i,j) = ┤  A(i,j)       ; A(i,j) !== 0
-	   *          └  B(i,j)       ; B(i,j) !== 0
-	   *
-	   *
-	   * @param {Matrix}   a                 The SparseMatrix instance (A)
-	   * @param {Matrix}   b                 The SparseMatrix instance (B)
-	   * @param {Function} callback          The f(Aij,Bij) operation to invoke
-	   *
-	   * @return {Matrix}                    SparseMatrix (C)
-	   *
-	   * see https://github.com/josdejong/mathjs/pull/346#issuecomment-97620294
-	   */
-	  var algorithm04 = function (a, b, callback) {
-	    // sparse matrix arrays
-	    var avalues = a._values;
-	    var aindex = a._index;
-	    var aptr = a._ptr;
-	    var asize = a._size;
-	    var adt = a._datatype;
-	    // sparse matrix arrays
-	    var bvalues = b._values;
-	    var bindex = b._index;
-	    var bptr = b._ptr;
-	    var bsize = b._size;
-	    var bdt = b._datatype;
-
-	    // validate dimensions
-	    if (asize.length !== bsize.length)
-	      throw new DimensionError(asize.length, bsize.length);
-
-	    // check rows & columns
-	    if (asize[0] !== bsize[0] || asize[1] !== bsize[1])
-	      throw new RangeError('Dimension mismatch. Matrix A (' + asize + ') must match Matrix B (' + bsize + ')');
-
-	    // rows & columns
-	    var rows = asize[0];
-	    var columns = asize[1];
-
-	    // datatype
-	    var dt;
-	    // equal signature to use
-	    var eq = equalScalar;
-	    // zero value
-	    var zero = 0;
-	    // callback signature to use
-	    var cf = callback;
-
-	    // process data types
-	    if (typeof adt === 'string' && adt === bdt) {
-	      // datatype
-	      dt = adt;
-	      // find signature that matches (dt, dt)
-	      eq = typed.find(equalScalar, [dt, dt]);
-	      // convert 0 to the same datatype
-	      zero = typed.convert(0, dt);
-	      // callback
-	      cf = typed.find(callback, [dt, dt]);
-	    }
-
-	    // result arrays
-	    var cvalues = avalues && bvalues ? [] : undefined;
-	    var cindex = [];
-	    var cptr = [];
-	    // matrix
-	    var c = new SparseMatrix({
-	      values: cvalues,
-	      index: cindex,
-	      ptr: cptr,
-	      size: [rows, columns],
-	      datatype: dt
-	    });
-
-	    // workspace
-	    var xa = avalues && bvalues ? [] : undefined;
-	    var xb = avalues && bvalues ? [] : undefined;
-	    // marks indicating we have a value in x for a given column
-	    var wa = [];
-	    var wb = [];
-
-	    // vars 
-	    var i, j, k, k0, k1;
-	    
-	    // loop columns
-	    for (j = 0; j < columns; j++) {
-	      // update cptr
-	      cptr[j] = cindex.length;
-	      // columns mark
-	      var mark = j + 1;
-	      // loop A(:,j)
-	      for (k0 = aptr[j], k1 = aptr[j + 1], k = k0; k < k1; k++) {
-	        // row
-	        i = aindex[k];
-	        // update c
-	        cindex.push(i);
-	        // update workspace
-	        wa[i] = mark;
-	        // check we need to process values
-	        if (xa)
-	          xa[i] = avalues[k];
-	      }
-	      // loop B(:,j)
-	      for (k0 = bptr[j], k1 = bptr[j + 1], k = k0; k < k1; k++) {
-	        // row
-	        i = bindex[k];
-	        // check row exists in A
-	        if (wa[i] === mark) {
-	          // update record in xa @ i
-	          if (xa) {
-	            // invoke callback
-	            var v = cf(xa[i], bvalues[k]);
-	            // check for zero
-	            if (!eq(v, zero)) {
-	              // update workspace
-	              xa[i] = v;              
-	            }
-	            else {
-	              // remove mark (index will be removed later)
-	              wa[i] = null;
-	            }
-	          }
-	        }
-	        else {
-	          // update c
-	          cindex.push(i);
-	          // update workspace
-	          wb[i] = mark;
-	          // check we need to process values
-	          if (xb)
-	            xb[i] = bvalues[k];
-	        }
-	      }
-	      // check we need to process values (non pattern matrix)
-	      if (xa && xb) {
-	        // initialize first index in j
-	        k = cptr[j];
-	        // loop index in j
-	        while (k < cindex.length) {
-	          // row
-	          i = cindex[k];
-	          // check workspace has value @ i
-	          if (wa[i] === mark) {
-	            // push value (Aij != 0 || (Aij != 0 && Bij != 0))
-	            cvalues[k] = xa[i];
-	            // increment pointer
-	            k++;
-	          }
-	          else if (wb[i] === mark) {
-	            // push value (bij != 0)
-	            cvalues[k] = xb[i];
-	            // increment pointer
-	            k++;
-	          }
-	          else {
-	            // remove index @ k
-	            cindex.splice(k, 1);
-	          }
-	        }
-	      }
-	    }
-	    // update cptr
-	    cptr[columns] = cindex.length;
-
-	    // return sparse matrix
-	    return c;
-	  };
-	  
-	  return algorithm04;
-	}
-
-	exports.name = 'algorithm04';
-	exports.factory = factory;
-
-
-/***/ },
-/* 55 */
-/***/ function(module, exports) {
-
-	'use strict';
-
-	function factory (type, config, load, typed) {
-
-	  var DenseMatrix = type.DenseMatrix;
-
-	  /**
-	   * Iterates over SparseMatrix S nonzero items and invokes the callback function f(Sij, b). 
-	   * Callback function invoked NZ times (number of nonzero items in S).
-	   *
-	   *
-	   *          ┌  f(Sij, b)  ; S(i,j) !== 0
-	   * C(i,j) = ┤  
-	   *          └  b          ; otherwise
-	   *
-	   *
-	   * @param {Matrix}   s                 The SparseMatrix instance (S)
-	   * @param {Scalar}   b                 The Scalar value
-	   * @param {Function} callback          The f(Aij,b) operation to invoke
-	   * @param {boolean}  inverse           A true value indicates callback should be invoked f(b,Sij)
-	   *
-	   * @return {Matrix}                    DenseMatrix (C)
-	   *
-	   * https://github.com/josdejong/mathjs/pull/346#issuecomment-97626813
-	   */
-	  var algorithm10 = function (s, b, callback, inverse) {
-	    // sparse matrix arrays
-	    var avalues = s._values;
-	    var aindex = s._index;
-	    var aptr = s._ptr;
-	    var asize = s._size;
-	    var adt = s._datatype;
-
-	    // sparse matrix cannot be a Pattern matrix
-	    if (!avalues)
-	      throw new Error('Cannot perform operation on Pattern Sparse Matrix and Scalar value');
-
-	    // rows & columns
-	    var rows = asize[0];
-	    var columns = asize[1];
-
-	    // datatype
-	    var dt;
-	    // callback signature to use
-	    var cf = callback;
-
-	    // process data types
-	    if (typeof adt === 'string') {
-	      // datatype
-	      dt = adt;
-	      // convert b to the same datatype
-	      b = typed.convert(b, dt);
-	      // callback
-	      cf = typed.find(callback, [dt, dt]);
-	    }
-
-	    // result arrays
-	    var cdata = [];
-	    // matrix
-	    var c = new DenseMatrix({
-	      data: cdata,
-	      size: [rows, columns],
-	      datatype: dt
-	    });
-
-	    // workspaces
-	    var x = [];
-	    // marks indicating we have a value in x for a given column
-	    var w = [];
-
-	    // loop columns
-	    for (var j = 0; j < columns; j++) {
-	      // columns mark
-	      var mark = j + 1;
-	      // values in j
-	      for (var k0 = aptr[j], k1 = aptr[j + 1], k = k0; k < k1; k++) {
-	        // row
-	        var r = aindex[k];
-	        // update workspace
-	        x[r] = avalues[k];
-	        w[r] = mark;
-	      }
-	      // loop rows
-	      for (var i = 0; i < rows; i++) {
-	        // initialize C on first column
-	        if (j === 0) {
-	          // create row array
-	          cdata[i] = [];
-	        }
-	        // check sparse matrix has a value @ i,j
-	        if (w[i] === mark) {
-	          // invoke callback, update C
-	          cdata[i][j] = inverse ? cf(b, x[i]) : cf(x[i], b);
-	        }
-	        else {
-	          // dense matrix value @ i, j
-	          cdata[i][j] = b;
-	        }
-	      }
-	    }
-
-	    // return sparse matrix
-	    return c;
-	  };
-
-	  return algorithm10;
-	}
-
-	exports.name = 'algorithm10';
-	exports.factory = factory;
-
-
-/***/ },
-/* 56 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var util = __webpack_require__(39);
-	var DimensionError = __webpack_require__(42);
-
-	var string = util.string,
-	    isString = string.isString;
-
-	function factory (type, config, load, typed) {
-
-	  var DenseMatrix = type.DenseMatrix;
-
-	  /**
-	   * Iterates over DenseMatrix items and invokes the callback function f(Aij..z, Bij..z). 
-	   * Callback function invoked MxN times.
-	   *
-	   * C(i,j,...z) = f(Aij..z, Bij..z)
-	   *
-	   * @param {Matrix}   a                 The DenseMatrix instance (A)
-	   * @param {Matrix}   b                 The DenseMatrix instance (B)
-	   * @param {Function} callback          The f(Aij..z,Bij..z) operation to invoke
-	   *
-	   * @return {Matrix}                    DenseMatrix (C)
-	   *
-	   * https://github.com/josdejong/mathjs/pull/346#issuecomment-97658658
-	   */
-	  var algorithm13 = function (a, b, callback) {
-	    // a arrays
-	    var adata = a._data;
-	    var asize = a._size;
-	    var adt = a._datatype;
-	    // b arrays
-	    var bdata = b._data;
-	    var bsize = b._size;
-	    var bdt = b._datatype;
-	    // c arrays
-	    var csize = [];
-
-	    // validate dimensions
-	    if (asize.length !== bsize.length)
-	      throw new DimensionError(asize.length, bsize.length);
-
-	    // validate each one of the dimension sizes
-	    for (var s = 0; s < asize.length; s++) {
-	      // must match
-	      if (asize[s] !== bsize[s])
-	        throw new RangeError('Dimension mismatch. Matrix A (' + asize + ') must match Matrix B (' + bsize + ')');
-	      // update dimension in c
-	      csize[s] = asize[s];
-	    }
-
-	    // datatype
-	    var dt;
-	    // callback signature to use
-	    var cf = callback;
-
-	    // process data types
-	    if (typeof adt === 'string' && adt === bdt) {
-	      // datatype
-	      dt = adt;
-	      // convert b to the same datatype
-	      b = typed.convert(b, dt);
-	      // callback
-	      cf = typed.find(callback, [dt, dt]);
-	    }
-
-	    // populate cdata, iterate through dimensions
-	    var cdata = csize.length > 0 ? _iterate(cf, 0, csize, csize[0], adata, bdata) : [];
-	    
-	    // c matrix
-	    return new DenseMatrix({
-	      data: cdata,
-	      size: csize,
-	      datatype: dt
-	    });
-	  };
-	  
-	  // recursive function
-	  var _iterate = function (f, level, s, n, av, bv) {
-	    // initialize array for this level
-	    var cv = [];
-	    // check we reach the last level
-	    if (level === s.length - 1) {
-	      // loop arrays in last level
-	      for (var i = 0; i < n; i++) {
-	        // invoke callback and store value
-	        cv[i] = f(av[i], bv[i]);
-	      }
-	    }
-	    else {
-	      // iterate current level
-	      for (var j = 0; j < n; j++) {
-	        // iterate next level
-	        cv[j] = _iterate(f, level + 1, s, s[level + 1], av[j], bv[j]);
-	      }
-	    }
-	    return cv;
-	  };
-	  
-	  return algorithm13;
-	}
-
-	exports.name = 'algorithm13';
-	exports.factory = factory;
-
-
-/***/ },
-/* 57 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var clone = __webpack_require__(3).clone;
-
-	function factory (type, config, load, typed) {
-
-	  var DenseMatrix = type.DenseMatrix;
-
-	  /**
-	   * Iterates over DenseMatrix items and invokes the callback function f(Aij..z, b). 
-	   * Callback function invoked MxN times.
-	   *
-	   * C(i,j,...z) = f(Aij..z, b)
-	   *
-	   * @param {Matrix}   a                 The DenseMatrix instance (A)
-	   * @param {Scalar}   b                 The Scalar value
-	   * @param {Function} callback          The f(Aij..z,b) operation to invoke
-	   * @param {boolean}  inverse           A true value indicates callback should be invoked f(b,Aij..z)
-	   *
-	   * @return {Matrix}                    DenseMatrix (C)
-	   *
-	   * https://github.com/josdejong/mathjs/pull/346#issuecomment-97659042
-	   */
-	  var algorithm14 = function (a, b, callback, inverse) {
-	    // a arrays
-	    var adata = a._data;
-	    var asize = a._size;
-	    var adt = a._datatype;
-	    
-	    // datatype
-	    var dt;
-	    // callback signature to use
-	    var cf = callback;
-
-	    // process data types
-	    if (typeof adt === 'string') {
-	      // datatype
-	      dt = adt;
-	      // convert b to the same datatype
-	      b = typed.convert(b, dt);
-	      // callback
-	      cf = typed.find(callback, [dt, dt]);
-	    }
-	    
-	    // populate cdata, iterate through dimensions
-	    var cdata = asize.length > 0 ? _iterate(cf, 0, asize, asize[0], adata, b, inverse) : [];
-
-	    // c matrix
-	    return new DenseMatrix({
-	      data: cdata,
-	      size: clone(asize),
-	      datatype: dt
-	    });
-	  };
-	  
-	  // recursive function
-	  var _iterate = function (f, level, s, n, av, bv, inverse) {
-	    // initialize array for this level
-	    var cv = [];
-	    // check we reach the last level
-	    if (level === s.length - 1) {
-	      // loop arrays in last level
-	      for (var i = 0; i < n; i++) {
-	        // invoke callback and store value
-	        cv[i] = inverse ? f(bv, av[i]) : f(av[i], bv);
-	      }
-	    }
-	    else {
-	      // iterate current level
-	      for (var j = 0; j < n; j++) {
-	        // iterate next level
-	        cv[j] = _iterate(f, level + 1, s, s[level + 1], av[j], bv, inverse);
-	      }
-	    }
-	    return cv;
-	  };
-
-	  return algorithm14;
-	}
-
-	exports.name = 'algorithm14';
-	exports.factory = factory;
-
-
-/***/ },
-/* 58 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	function factory (type, config, load, typed) {
-	  
-	  var smaller = load(__webpack_require__(59));
-	  var larger = load(__webpack_require__(63));
-	  
-	  var oneOverLogPhi = 1.0 / Math.log((1.0 + Math.sqrt(5.0)) / 2.0);
-	  
-	  function FibonacciHeap() {
-	    if (!(this instanceof FibonacciHeap))
-	      throw new SyntaxError('Constructor must be called with the new operator');
-
-	    // initialize fields
-	    this._minimum = null;
-	    this._size = 0;
-	  }
-
-	  /**
-	   * Attach type information
-	   */
-	  FibonacciHeap.prototype.type = 'FibonacciHeap';
-	  FibonacciHeap.prototype.isFibonacciHeap = true;
-
-	  /**
-	   * Inserts a new data element into the heap. No heap consolidation is
-	   * performed at this time, the new node is simply inserted into the root
-	   * list of this heap. Running time: O(1) actual.
-	   */
-	  FibonacciHeap.prototype.insert = function (key, value) {
-	    // create node
-	    var node = {
-	      key: key,
-	      value: value,
-	      degree: 0
-	    };
-	    // check we have a node in the minimum
-	    if (this._minimum) {
-	      // minimum node
-	      var minimum = this._minimum;
-	      // update left & right of node
-	      node.left = minimum;
-	      node.right = minimum.right;
-	      minimum.right = node;
-	      node.right.left = node;
-	      // update minimum node in heap if needed
-	      if (smaller(key, minimum.key)) {
-	        // node has a smaller key, use it as minimum
-	        this._minimum = node;
-	      }
-	    }
-	    else {
-	      // set left & right
-	      node.left = node;
-	      node.right = node;
-	      // this is the first node
-	      this._minimum = node;
-	    }
-	    // increment number of nodes in heap
-	    this._size++;
-	    // return node
-	    return node;
-	  };
-
-	  /**
-	   * Returns the number of nodes in heap. Running time: O(1) actual.
-	   */
-	  FibonacciHeap.prototype.size = function () {
-	    return this._size;
-	  };
-
-	  /**
-	   * Removes all elements from this heap.
-	   */
-	  FibonacciHeap.prototype.clear = function () {
-	    this._minimum = null;
-	    this._size = 0;
-	  };
-
-	  /**
-	   * Returns true if the heap is empty, otherwise false.
-	   */
-	  FibonacciHeap.prototype.isEmpty = function () {
-	    return !!this._minimum;
-	  };
-	  
-	  /**
-	   * Extracts the node with minimum key from heap. Amortized running 
-	   * time: O(log n).
-	   */
-	  FibonacciHeap.prototype.extractMinimum = function () {
-	    // node to remove
-	    var node = this._minimum;
-	    // check we have a minimum
-	    if (node === null)
-	      return node;
-	    // current minimum
-	    var minimum = this._minimum;
-	    // get number of children
-	    var numberOfChildren = node.degree;
-	    // pointer to the first child
-	    var x = node.child;
-	    // for each child of node do...
-	    while (numberOfChildren > 0) {
-	      // store node in right side
-	      var tempRight = x.right;
-	      // remove x from child list
-	      x.left.right = x.right;
-	      x.right.left = x.left;
-	      // add x to root list of heap
-	      x.left = minimum;
-	      x.right = minimum.right;
-	      minimum.right = x;
-	      x.right.left = x;
-	      // set Parent[x] to null
-	      x.parent = null;
-	      x = tempRight;
-	      numberOfChildren--;
-	    }
-	    // remove node from root list of heap
-	    node.left.right = node.right;
-	    node.right.left = node.left;
-	    // update minimum
-	    if (node == node.right) {
-	      // empty
-	      minimum = null;
-	    }
-	    else {
-	      // update minimum
-	      minimum = node.right;
-	      // we need to update the pointer to the root with minimum key
-	      minimum = _findMinimumNode(minimum, this._size);
-	    }
-	    // decrement size of heap
-	    this._size--;
-	    // update minimum
-	    this._minimum = minimum;
-	    // return node
-	    return node;
-	  };
-	  
-	  /**
-	   * Removes a node from the heap given the reference to the node. The trees
-	   * in the heap will be consolidated, if necessary. This operation may fail
-	   * to remove the correct element if there are nodes with key value -Infinity.
-	   * Running time: O(log n) amortized.
-	   */
-	  FibonacciHeap.prototype.remove = function (node) {
-	    // decrease key value
-	    this._minimum = _decreaseKey(this._minimum, node, -1);
-	    // remove the smallest
-	    this.extractMinimum();
-	  };
-	  
-	  /**
-	   * Decreases the key value for a heap node, given the new value to take on.
-	   * The structure of the heap may be changed and will not be consolidated. 
-	   * Running time: O(1) amortized.
-	   */
-	  var _decreaseKey = function (minimum, node, key) {
-	    // set node key
-	    node.key = key;
-	    // get parent node
-	    var parent = node.parent;
-	    if (parent && smaller(node.key, parent.key)) {
-	      // remove node from parent
-	      _cut(minimum, node, parent);
-	      // remove all nodes from parent to the root parent
-	      _cascadingCut(minimum, parent);
-	    }
-	    // update minimum node if needed
-	    if (smaller(node.key, minimum.key))
-	      minimum = node;
-	    // return minimum
-	    return minimum;
-	  };
-	  
-	  /**
-	   * The reverse of the link operation: removes node from the child list of parent.
-	   * This method assumes that min is non-null. Running time: O(1).
-	   */
-	  var _cut = function (minimum, node, parent) {
-	    // remove node from parent children and decrement Degree[parent]
-	    node.left.right = node.right;
-	    node.right.left = node.left;
-	    parent.degree--;
-	    // reset y.child if necessary
-	    if (parent.child == node)
-	      parent.child = node.right;
-	    // remove child if degree is 0
-	    if (parent.degree === 0)
-	      parent.child = null;
-	    // add node to root list of heap
-	    node.left = minimum;
-	    node.right = minimum.right;
-	    minimum.right = node;
-	    node.right.left = node;
-	    // set parent[node] to null
-	    node.parent = null;
-	    // set mark[node] to false
-	    node.mark = false;
-	  };
-	  
-	  /**
-	   * Performs a cascading cut operation. This cuts node from its parent and then
-	   * does the same for its parent, and so on up the tree.
-	   * Running time: O(log n); O(1) excluding the recursion.
-	   */
-	  var _cascadingCut= function (minimum, node) {
-	    // store parent node
-	    var parent = node.parent;
-	    // if there's a parent...
-	    if (!parent)
-	      return;
-	    // if node is unmarked, set it marked
-	    if (!node.mark) {
-	      node.mark = true;
-	    }
-	    else {
-	      // it's marked, cut it from parent
-	      _cut(minimum, node, parent);
-	      // cut its parent as well
-	      _cascadingCut(parent);
-	    }
-	  };
-	  
-	  /**
-	   * Make the first node a child of the second one. Running time: O(1) actual.
-	   */
-	  var _linkNodes = function (node, parent) {
-	    // remove node from root list of heap
-	    node.left.right = node.right;
-	    node.right.left = node.left;
-	    // make node a Child of parent
-	    node.parent = parent;
-	    if (!parent.child) {
-	      parent.child = node;
-	      node.right = node;
-	      node.left = node;
-	    }
-	    else {
-	      node.left = parent.child;
-	      node.right = parent.child.right;
-	      parent.child.right = node;
-	      node.right.left = node;
-	    }
-	    // increase degree[parent]
-	    parent.degree++;
-	    // set mark[node] false
-	    node.mark = false;
-	  };
-	  
-	  var _findMinimumNode = function (minimum, size) {
-	    // to find trees of the same degree efficiently we use an array of length O(log n) in which we keep a pointer to one root of each degree
-	    var arraySize = Math.floor(Math.log(size) * oneOverLogPhi) + 1;
-	    // create list with initial capacity
-	    var array = new Array(arraySize);
-	    // find the number of root nodes.
-	    var numRoots = 0;
-	    var x = minimum;
-	    if (x) {
-	      numRoots++;
-	      x = x.right;
-	      while (x !== minimum) {
-	        numRoots++;
-	        x = x.right;
-	      }
-	    }
-	    // vars
-	    var y;
-	    // For each node in root list do...
-	    while (numRoots > 0) {
-	      // access this node's degree..
-	      var d = x.degree;
-	      // get next node
-	      var next = x.right;
-	      // check if there is a node already in array with the same degree
-	      while (true) {
-	        // get node with the same degree is any
-	        y = array[d];
-	        if (!y)
-	          break;
-	        // make one node with the same degree a child of the other, do this based on the key value.
-	        if (larger(x.key, y.key)) {
-	          var temp = y;
-	          y = x;
-	          x = temp;
-	        }
-	        // make y a child of x
-	        _linkNodes(y, x);
-	        // we have handled this degree, go to next one.
-	        array[d] = null;
-	        d++;
-	      }
-	      // save this node for later when we might encounter another of the same degree.
-	      array[d] = x;
-	      // move forward through list.
-	      x = next;
-	      numRoots--;
-	    }
-	    // Set min to null (effectively losing the root list) and reconstruct the root list from the array entries in array[].
-	    minimum = null;
-	    // loop nodes in array
-	    for (var i = 0; i < arraySize; i++) {
-	      // get current node
-	      y = array[i];
-	      if (!y)
-	        continue;
-	      // check if we have a linked list
-	      if (minimum) {
-	        // First remove node from root list.
-	        y.left.right = y.right;
-	        y.right.left = y.left;
-	        // now add to root list, again.
-	        y.left = minimum;
-	        y.right = minimum.right;
-	        minimum.right = y;
-	        y.right.left = y;
-	        // check if this is a new min.
-	        if (smaller(y.key, minimum.key))
-	          minimum = y;
-	      }
-	      else
-	        minimum = y;
-	    }
-	    return minimum;
-	  };
-	  
-	  return FibonacciHeap;
-	}
-
-	exports.name = 'FibonacciHeap';
-	exports.path = 'type';
-	exports.factory = factory;
-
-
-/***/ },
-/* 59 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var nearlyEqual = __webpack_require__(6).nearlyEqual;
-
-	function factory (type, config, load, typed) {
-
-	  var matrix = load(__webpack_require__(51));
-
-	  var algorithm03 = load(__webpack_require__(60));
-	  var algorithm07 = load(__webpack_require__(61));
-	  var algorithm12 = load(__webpack_require__(62));
-	  var algorithm13 = load(__webpack_require__(56));
-	  var algorithm14 = load(__webpack_require__(57));
-
-	  var latex = __webpack_require__(30);
-
-	  /**
-	   * Test whether value x is smaller than y.
-	   *
-	   * The function returns true when x is smaller than y and the relative
-	   * difference between x and y is smaller than the configured epsilon. The
-	   * function cannot be used to compare values smaller than approximately 2.22e-16.
-	   *
-	   * For matrices, the function is evaluated element wise.
-	   *
-	   * Syntax:
-	   *
-	   *    math.smaller(x, y)
-	   *
-	   * Examples:
-	   *
-	   *    math.smaller(2, 3);            // returns true
-	   *    math.smaller(5, 2 * 2);        // returns false
-	   *
-	   *    var a = math.unit('5 cm');
-	   *    var b = math.unit('2 inch');
-	   *    math.smaller(a, b);            // returns true
-	   *
-	   * See also:
-	   *
-	   *    equal, unequal, smallerEq, smaller, smallerEq, compare
-	   *
-	   * @param  {number | BigNumber | Fraction | boolean | Unit | string | Array | Matrix} x First value to compare
-	   * @param  {number | BigNumber | Fraction | boolean | Unit | string | Array | Matrix} y Second value to compare
-	   * @return {boolean | Array | Matrix} Returns true when the x is smaller than y, else returns false
-	   */
-	  var smaller = typed('smaller', {
-
-	    'boolean, boolean': function (x, y) {
-	      return x < y;
-	    },
-
-	    'number, number': function (x, y) {
-	      return x < y && !nearlyEqual(x, y, config.epsilon);
-	    },
-
-	    'BigNumber, BigNumber': function (x, y) {
-	      return x.lt(y);
-	    },
-
-	    'Fraction, Fraction': function (x, y) {
-	      return x.compare(y) === -1;
-	    },
-
-	    'Complex, Complex': function (x, y) {
-	      throw new TypeError('No ordering relation is defined for complex numbers');
-	    },
-
-	    'Unit, Unit': function (x, y) {
-	      if (!x.equalBase(y)) {
-	        throw new Error('Cannot compare units with different base');
-	      }
-	      return x.value < y.value && !nearlyEqual(x.value, y.value, config.epsilon);
-	    },
-
-	    'string, string': function (x, y) {
-	      return x < y;
-	    },
-
-	    'Matrix, Matrix': function (x, y) {
-	      // result
-	      var c;
-
-	      // process matrix storage
-	      switch (x.storage()) {
-	        case 'sparse':
-	          switch (y.storage()) {
-	            case 'sparse':
-	              // sparse + sparse
-	              c = algorithm07(x, y, smaller);
-	              break;
-	            default:
-	              // sparse + dense
-	              c = algorithm03(y, x, smaller, true);
-	              break;
-	          }
-	          break;
-	        default:
-	          switch (y.storage()) {
-	            case 'sparse':
-	              // dense + sparse
-	              c = algorithm03(x, y, smaller, false);
-	              break;
-	            default:
-	              // dense + dense
-	              c = algorithm13(x, y, smaller);
-	              break;
-	          }
-	          break;
-	      }
-	      return c;
-	    },
-
-	    'Array, Array': function (x, y) {
-	      // use matrix implementation
-	      return smaller(matrix(x), matrix(y)).valueOf();
-	    },
-
-	    'Array, Matrix': function (x, y) {
-	      // use matrix implementation
-	      return smaller(matrix(x), y);
-	    },
-
-	    'Matrix, Array': function (x, y) {
-	      // use matrix implementation
-	      return smaller(x, matrix(y));
-	    },
-
-	    'Matrix, any': function (x, y) {
-	      // result
-	      var c;
-	      // check storage format
-	      switch (x.storage()) {
-	        case 'sparse':
-	          c = algorithm12(x, y, smaller, false);
-	          break;
-	        default:
-	          c = algorithm14(x, y, smaller, false);
-	          break;
-	      }
-	      return c;
-	    },
-
-	    'any, Matrix': function (x, y) {
-	      // result
-	      var c;
-	      // check storage format
-	      switch (y.storage()) {
-	        case 'sparse':
-	          c = algorithm12(y, x, smaller, true);
-	          break;
-	        default:
-	          c = algorithm14(y, x, smaller, true);
-	          break;
-	      }
-	      return c;
-	    },
-
-	    'Array, any': function (x, y) {
-	      // use matrix implementation
-	      return algorithm14(matrix(x), y, smaller, false).valueOf();
-	    },
-
-	    'any, Array': function (x, y) {
-	      // use matrix implementation
-	      return algorithm14(matrix(y), x, smaller, true).valueOf();
-	    }
-	  });
-
-	  smaller.toTex = '\\left(${args[0]}' + latex.operators['smaller'] + '${args[1]}\\right)';
-
-	  return smaller;
-	}
-
-	exports.name = 'smaller';
-	exports.factory = factory;
-
-
-/***/ },
-/* 60 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var DimensionError = __webpack_require__(42);
-
-	function factory (type, config, load, typed) {
-
-	  var DenseMatrix = type.DenseMatrix;
-
-	  /**
-	   * Iterates over SparseMatrix items and invokes the callback function f(Dij, Sij).
-	   * Callback function invoked M*N times.
-	   *
-	   *
-	   *          ┌  f(Dij, Sij)  ; S(i,j) !== 0
-	   * C(i,j) = ┤
-	   *          └  f(Dij, 0)    ; otherwise
-	   *
-	   *
-	   * @param {Matrix}   denseMatrix       The DenseMatrix instance (D)
-	   * @param {Matrix}   sparseMatrix      The SparseMatrix instance (C)
-	   * @param {Function} callback          The f(Dij,Sij) operation to invoke, where Dij = DenseMatrix(i,j) and Sij = SparseMatrix(i,j)
-	   * @param {boolean}  inverse           A true value indicates callback should be invoked f(Sij,Dij)
-	   *
-	   * @return {Matrix}                    DenseMatrix (C)
-	   *
-	   * see https://github.com/josdejong/mathjs/pull/346#issuecomment-97477571
-	   */
-	  var algorithm03 = function (denseMatrix, sparseMatrix, callback, inverse) {
-	    // dense matrix arrays
-	    var adata = denseMatrix._data;
-	    var asize = denseMatrix._size;
-	    var adt = denseMatrix._datatype;
-	    // sparse matrix arrays
-	    var bvalues = sparseMatrix._values;
-	    var bindex = sparseMatrix._index;
-	    var bptr = sparseMatrix._ptr;
-	    var bsize = sparseMatrix._size;
-	    var bdt = sparseMatrix._datatype;
-
-	    // validate dimensions
-	    if (asize.length !== bsize.length)
-	      throw new DimensionError(asize.length, bsize.length);
-
-	    // check rows & columns
-	    if (asize[0] !== bsize[0] || asize[1] !== bsize[1])
-	      throw new RangeError('Dimension mismatch. Matrix A (' + asize + ') must match Matrix B (' + bsize + ')');
-
-	    // sparse matrix cannot be a Pattern matrix
-	    if (!bvalues)
-	      throw new Error('Cannot perform operation on Dense Matrix and Pattern Sparse Matrix');
-
-	    // rows & columns
-	    var rows = asize[0];
-	    var columns = asize[1];
-
-	    // datatype
-	    var dt;
-	    // zero value
-	    var zero = 0;
-	    // callback signature to use
-	    var cf = callback;
-
-	    // process data types
-	    if (typeof adt === 'string' && adt === bdt) {
-	      // datatype
-	      dt = adt;
-	      // convert 0 to the same datatype
-	      zero = typed.convert(0, dt);
-	      // callback
-	      cf = typed.find(callback, [dt, dt]);
-	    }
-
-	    // result (DenseMatrix)
-	    var cdata = [];
-
-	    // initialize dense matrix
-	    for (var z = 0; z < rows; z++) {
-	      // initialize row
-	      cdata[z] = [];
-	    }
-
-	    // workspace
-	    var x = [];
-	    // marks indicating we have a value in x for a given column
-	    var w = [];
-
-	    // loop columns in b
-	    for (var j = 0; j < columns; j++) {
-	      // column mark
-	      var mark = j + 1;
-	      // values in column j
-	      for (var k0 = bptr[j], k1 = bptr[j + 1], k = k0; k < k1; k++) {
-	        // row
-	        var i = bindex[k];
-	        // update workspace
-	        x[i] = inverse ? cf(bvalues[k], adata[i][j]) : cf(adata[i][j], bvalues[k]);
-	        w[i] = mark;
-	      }
-	      // process workspace
-	      for (var y = 0; y < rows; y++) {
-	        // check we have a calculated value for current row
-	        if (w[y] === mark) {
-	          // use calculated value
-	          cdata[y][j] = x[y];
-	        }
-	        else {
-	          // calculate value
-	          cdata[y][j] = inverse ? cf(zero, adata[y][j]) : cf(adata[y][j], zero);
-	        }
-	      }
-	    }
-
-	    // return dense matrix
-	    return new DenseMatrix({
-	      data: cdata,
-	      size: [rows, columns],
-	      datatype: dt
-	    });
-	  };
-	  
-	  return algorithm03;
-	}
-
-	exports.name = 'algorithm03';
-	exports.factory = factory;
-
-
-/***/ },
-/* 61 */
-/***/ function(module, exports, __webpack_require__) {
-
-	'use strict';
-
-	var DimensionError = __webpack_require__(42);
-
-	function factory (type, config, load, typed) {
-
-	  var DenseMatrix = type.DenseMatrix;
-
-	  /**
-	   * Iterates over SparseMatrix A and SparseMatrix B items (zero and nonzero) and invokes the callback function f(Aij, Bij). 
-	   * Callback function invoked MxN times.
-	   *
-	   * C(i,j) = f(Aij, Bij)
-	   *
-	   * @param {Matrix}   a                 The SparseMatrix instance (A)
-	   * @param {Matrix}   b                 The SparseMatrix instance (B)
-	   * @param {Function} callback          The f(Aij,Bij) operation to invoke
-	   *
-	   * @return {Matrix}                    DenseMatrix (C)
-	   *
-	   * see https://github.com/josdejong/mathjs/pull/346#issuecomment-97620294
-	   */
-	  var algorithm07 = function (a, b, callback) {
-	    // sparse matrix arrays
-	    var asize = a._size;
-	    var adt = a._datatype;
-	    // sparse matrix arrays
-	    var bsize = b._size;
-	    var bdt = b._datatype;
-
-	    // validate dimensions
-	    if (asize.length !== bsize.length)
-	      throw new DimensionError(asize.length, bsize.length);
-
-	    // check rows & columns
-	    if (asize[0] !== bsize[0] || asize[1] !== bsize[1])
-	      throw new RangeError('Dimension mismatch. Matrix A (' + asize + ') must match Matrix B (' + bsize + ')');
-
-	    // rows & columns
-	    var rows = asize[0];
-	    var columns = asize[1];
-
-	    // datatype
-	    var dt;
-	    // zero value
-	    var zero = 0;
-	    // callback signature to use
-	    var cf = callback;
-
-	    // process data types
-	    if (typeof adt === 'string' && adt === bdt) {
-	      // datatype
-	      dt = adt;
-	      // convert 0 to the same datatype
-	      zero = typed.convert(0, dt);
-	      // callback
-	      cf = typed.find(callback, [dt, dt]);
-	    }
-
-	    // vars
-	    var i, j;
-	    
-	    // result arrays
-	    var cdata = [];
-	    // initialize c
-	    for (i = 0; i < rows; i++)
-	      cdata[i] = [];
-
-	    // matrix
-	    var c = new DenseMatrix({
-	      data: cdata,
-	      size: [rows, columns],
-	      datatype: dt
-	    });
-
-	    // workspaces
-	    var xa = [];
-	    var xb = [];
-	    // marks indicating we have a value in x for a given column
-	    var wa = [];
-	    var wb = [];
-
-	    // loop columns
-	    for (j = 0; j < columns; j++) {
-	      // columns mark
-	      var mark = j + 1;
-	      // scatter the values of A(:,j) into workspace
-	      _scatter(a, j, wa, xa, mark);
-	      // scatter the values of B(:,j) into workspace
-	      _scatter(b, j, wb, xb, mark);
-	      // loop rows
-	      for (i = 0; i < rows; i++) {
-	        // matrix values @ i,j
-	        var va = wa[i] === mark ? xa[i] : zero;
-	        var vb = wb[i] === mark ? xb[i] : zero;
-	        // invoke callback
-	        cdata[i][j] = cf(va, vb);
-	      }          
-	    }
-
-	    // return sparse matrix
-	    return c;
-	  };
-	  
-	  var _scatter = function (m, j, w, x, mark) {
-	    // a arrays
-	    var values = m._values;
-	    var index = m._index;
-	    var ptr = m._ptr;
-	    // loop values in column j
-	    for (var k = ptr[j], k1 = ptr[j + 1]; k < k1; k++) {
-	      // row
-	      var i = index[k];
-	      // update workspace
-	      w[i] = mark;
-	      x[i] = values[k];
-	    }
-	  };
-	  
-	  return algorithm07;
-	}
-
-	exports.name = 'algorithm07';
-	exports.factory = factory;
-
-
-/***/ },
-/* 62 */
-/***/ function(module, exports) {
-
-	'use strict';
-
-	function factory (type, config, load, typed) {
-
-	  var DenseMatrix = type.DenseMatrix;
-
-	  /**
-	   * Iterates over SparseMatrix S nonzero items and invokes the callback function f(Sij, b). 
-	   * Callback function invoked MxN times.
-	   *
-	   *
-	   *          ┌  f(Sij, b)  ; S(i,j) !== 0
-	   * C(i,j) = ┤  
-	   *          └  f(0, b)    ; otherwise
-	   *
-	   *
-	   * @param {Matrix}   s                 The SparseMatrix instance (S)
-	   * @param {Scalar}   b                 The Scalar value
-	   * @param {Function} callback          The f(Aij,b) operation to invoke
-	   * @param {boolean}  inverse           A true value indicates callback should be invoked f(b,Sij)
-	   *
-	   * @return {Matrix}                    DenseMatrix (C)
-	   *
-	   * https://github.com/josdejong/mathjs/pull/346#issuecomment-97626813
-	   */
-	  var algorithm12 = function (s, b, callback, inverse) {
-	    // sparse matrix arrays
-	    var avalues = s._values;
-	    var aindex = s._index;
-	    var aptr = s._ptr;
-	    var asize = s._size;
-	    var adt = s._datatype;
-
-	    // sparse matrix cannot be a Pattern matrix
-	    if (!avalues)
-	      throw new Error('Cannot perform operation on Pattern Sparse Matrix and Scalar value');
-
-	    // rows & columns
-	    var rows = asize[0];
-	    var columns = asize[1];
-
-	    // datatype
-	    var dt;
-	   

Follow ups