UNPKG

qics

Version:

A Javascript Idealistic Quantum Computer Simulation Library

1,744 lines (1,516 loc) 1.6 MB
var qics = /******/ (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__) { 'use strict'; var gates = __webpack_require__(80); var Register = __webpack_require__(138); // Exports the Gates class and the Register Class module.exports = { gates: gates, Register: Register }; /***/ }, /* 1 */ /***/ 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); } }; /***/ }, /* 2 */ /***/ 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; /***/ }, /* 3 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; var NumberFormatter = __webpack_require__(505); /** * 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 = Math.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' * 'engineering' Always use engineering notation. * For example '123.4e+0' and '14.0e+6' * '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' * format(12345678, {notation: 'engineering'}); // '12.345678e+6' * * @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 'engineering': return exports.toEngineering(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 in engineering notation. Like '1.23e+6', '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.toEngineering = function(value, precision) { return new NumberFormatter(value).toEngineering(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 nearly 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; }; /***/ }, /* 4 */ /***/ 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; }; /***/ }, /* 5 */ /***/ 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'; }; /***/ }, /* 6 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; var clone = __webpack_require__(5).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; /***/ }, /* 7 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; var util = __webpack_require__(24); var DimensionError = __webpack_require__(10); 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; /***/ }, /* 8 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; var number = __webpack_require__(3); var string = __webpack_require__(20); var object = __webpack_require__(5); var types = __webpack_require__(61); var DimensionError = __webpack_require__(10); 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 * when length is provided * @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 || (typeof length === 'number' && 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] = 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 * * Paramter `size` will be mutated to match the new, unqueezed matrix size. * * @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; /***/ }, /* 9 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; var nearlyEqual = __webpack_require__(3).nearlyEqual; var bigNearlyEqual = __webpack_require__(32); 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) || bigNearlyEqual(x, y, config.epsilon); }, 'Fraction, Fraction': function (x, y) { return x.equals(y); }, 'Complex, Complex': function (x, y) { return x.equals(y); }, 'Unit, Unit': function (x, y) { if (!x.equalBase(y)) { throw new Error('Cannot compare units with different base'); } return equalScalar(x.value, y.value); }, 'string, string': function (x, y) { return x === y; } }); return equalScalar; } exports.factory = factory; /***/ }, /* 10 */ /***/ 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; /***/ }, /* 11 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; var extend = __webpack_require__(5).extend; var array = __webpack_require__(8); function factory (type, config, load, typed) { var latex = __webpack_require__(4); var matrix = load(__webpack_require__(2)); var addScalar = load(__webpack_require__(18)); var multiplyScalar = load(__webpack_require__(21)); var equalScalar = load(__webpack_require__(9)); var algorithm11 = load(__webpack_require__(14)); var algorithm14 = load(__webpack_require__(6)); var DenseMatrix = type.DenseMatrix; var SparseMatrix = type.SparseMatrix; /** * Multiply two or more values, `x * y`. * For matrices, the matrix product is calculated. * * Syntax: * * math.multiply(x, y) * math.multiply(x, y, z, ...) * * Examples: * * math.multiply(4, 5.2); // returns number 20.8 * math.multiply(2, 3, 4); // returns number 24 * * var a = math.complex(2, 3); * var b = math.complex(4, 1); * math.multiply(a, b); // returns Complex 5 + 14i * * var c = [[1, 2], [4, 3]]; * var d = [[1, 2, 3], [3, -4, 7]]; * math.multiply(c, d); // returns Array [[7, -6, 17], [13, -4, 33]] * * var e = math.unit('2.1 km'); * math.multiply(3, e); // returns Unit 6.3 km * * See also: * * divide, prod, cross, dot * * @param {number | BigNumber | Fraction | Complex | Unit | Array | Matrix} x First value to multiply * @param {number | BigNumber | Fraction | Complex | Unit | Array | Matrix} y Second value to multiply * @return {number | BigNumber | Fraction | Complex | Unit | Array | Matrix} Multiplication of `x` and `y` */ var multiply = typed('multiply', extend({ // we extend the signatures of multiplyScalar with signatures dealing with matrices 'Array, Array': function (x, y) { // check dimensions _validateMatrixDimensions(array.size(x), array.size(y)); // use dense matrix implementation var m = multiply(matrix(x), matrix(y)); // return array or scalar return (m && m.isMatrix === true) ? m.valueOf() : m; }, 'Matrix, Matrix': function (x, y) { // dimensions var xsize = x.size(); var ysize = y.size(); // check dimensions _validateMatrixDimensions(xsize, ysize); // process dimensions if (xsize.length === 1) { // process y dimensions if (ysize.length === 1) { // Vector * Vector return _multiplyVectorVector(x, y, xsize[0]); } // Vector * Matrix return _multiplyVectorMatrix(x, y); } // process y dimensions if (ysize.length === 1) { // Matrix * Vector return _multiplyMatrixVector(x, y); } // Matrix * Matrix return _multiplyMatrixMatrix(x, y); }, 'Matrix, Array': function (x, y) { // use Matrix * Matrix implementation return multiply(x, matrix(y)); }, 'Array, Matrix': function (x, y) { // use Matrix * Matrix implementation return multiply(matrix(x, y.storage()), y); }, 'Matrix, any': function (x, y) { // result var c; // process storage format switch (x.storage()) { case 'sparse': c = algorithm11(x, y, multiplyScalar, false); break; case 'dense': c = algorithm14(x, y, multiplyScalar, false); break; } return c; }, 'any, Matrix': function (x, y) { // result var c; // check storage format switch (y.storage()) { case 'sparse': c = algorithm11(y, x, multiplyScalar, true); break; case 'dense': c = algorithm14(y, x, multiplyScalar, true); break; } return c; }, 'Array, any': function (x, y) { // use matrix implementation return algorithm14(matrix(x), y, multiplyScalar, false).valueOf(); }, 'any, Array': function (x, y) { // use matrix implementation return algorithm14(matrix(y), x, multiplyScalar, true).valueOf(); }, 'any, any': multiplyScalar, 'any, any, ...any': function (x, y, rest) { var result = multiply(x, y); for (var i = 0; i < rest.length; i++) { result = multiply(result, rest[i]); } return result; } }, multiplyScalar.signatures)); var _validateMatrixDimensions = function (size1, size2) { // check left operand dimensions switch (size1.length) { case 1: // check size2 switch (size2.length) { case 1: // Vector x Vector if (size1[0] !== size2[0]) { // throw error throw new RangeError('Dimension mismatch in multiplication. Vectors must have the same length'); } break; case 2: // Vector x Matrix if (size1[0] !== size2[0]) { // throw error throw new RangeError('Dimension mismatch in multiplication. Vector length (' + size1[0] + ') must match Matrix rows (' + size2[0] + ')'); } break; default: throw new Error('Can only multiply a 1 or 2 dimensional matrix (Matrix B has ' + size2.length + ' dimensions)'); } break; case 2: // check size2 switch (size2.length) { case 1: // Matrix x Vector if (size1[1] !== size2[0]) { // throw error throw new RangeError('Dimension mismatch in multiplication. Matrix columns (' + size1[1] + ') must match Vector length (' + size2[0] + ')'); } break; case 2: // Matrix x Matrix if (size1[1] !== size2[0]) { // throw error throw new RangeError('Dimension mismatch in multiplication. Matrix A columns (' + size1[1] + ') must match Matrix B rows (' + size2[0] + ')'); } break; default: throw new Error('Can only multiply a 1 or 2 dimensional matrix (Matrix B has ' + size2.length + ' dimensions)'); } break; default: throw new Error('Can only multiply a 1 or 2 dimensional matrix (Matrix A has ' + size1.length + ' dimensions)'); } }; /** * C = A * B * * @param {Matrix} a Dense Vector (N) * @param {Matrix} b Dense Vector (N) * * @return {number} Scalar value */ var _multiplyVectorVector = function (a, b, n) { // check empty vector if (n === 0) throw new Error('Cannot multiply two empty vectors'); // a dense var adata = a._data; var adt = a._datatype; // b dense var bdata = b._data; var bdt = b._datatype; // datatype var dt; // addScalar signature to use var af = addScalar; // multiplyScalar signature to use var mf = multiplyScalar; // process data types if (adt && bdt && adt === bdt && typeof adt === 'string') { // datatype dt = adt; // find signatures that matches (dt, dt) af = typed.find(addScalar, [dt, dt]); mf = typed.find(multiplyScalar, [dt, dt]); } // result (do not initialize it with zero) var c = mf(adata[0], bdata[0]); // loop data for (var i = 1; i < n; i++) { // multiply and accumulate c = af(c, mf(adata[i], bdata[i])); } return c; }; /** * C = A * B * * @param {Matrix} a Dense Vector (M) * @param {Matrix} b Matrix (MxN)