ubuntu-touch-coreapps-reviewers team mailing list archive
-
ubuntu-touch-coreapps-reviewers team
-
Mailing list archive
-
Message #06241
[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