| export function inspectMatrix() { | ||
| // noop | ||
| } |
| export function inspectMatrix() { | ||
| const indent = ' '.repeat(2); | ||
| const indentData = ' '.repeat(4); | ||
| return `${this.constructor.name} { | ||
| ${indent}[ | ||
| ${indentData}${inspectData(this, indentData)} | ||
| ${indent}] | ||
| ${indent}rows: ${this.rows} | ||
| ${indent}columns: ${this.columns} | ||
| }`; | ||
| } | ||
| const maxRows = 15; | ||
| const maxColumns = 10; | ||
| const maxNumSize = 8; | ||
| function inspectData(matrix, indent) { | ||
| const { rows, columns } = matrix; | ||
| const maxI = Math.min(rows, maxRows); | ||
| const maxJ = Math.min(columns, maxColumns); | ||
| const result = []; | ||
| for (var i = 0; i < maxI; i++) { | ||
| let line = []; | ||
| for (var j = 0; j < maxJ; j++) { | ||
| line.push(formatNumber(matrix.get(i, j))); | ||
| } | ||
| result.push(`${line.join(' ')}`); | ||
| } | ||
| if (maxJ !== columns) { | ||
| result[result.length - 1] += ` ... ${columns - maxColumns} more columns`; | ||
| } | ||
| if (maxI !== rows) { | ||
| result.push(`... ${rows - maxRows} more rows`); | ||
| } | ||
| return result.join(`\n${indent}`); | ||
| } | ||
| function formatNumber(num) { | ||
| const numStr = String(num); | ||
| if (numStr.length <= maxNumSize) { | ||
| return numStr.padEnd(maxNumSize, ' '); | ||
| } | ||
| const precise = num.toPrecision(maxNumSize - 2); | ||
| if (precise.length <= maxNumSize) { | ||
| return precise; | ||
| } | ||
| const exponential = num.toExponential(maxNumSize - 2); | ||
| const eIndex = exponential.indexOf('e'); | ||
| const e = exponential.substring(eIndex); | ||
| return exponential.substring(0, maxNumSize - e.length) + e; | ||
| } |
| export function installMathOperations(AbstractMatrix, Matrix) { | ||
| AbstractMatrix.prototype.add = function add(value) { | ||
| if (typeof value === 'number') return this.addS(value); | ||
| return this.addM(value); | ||
| }; | ||
| AbstractMatrix.prototype.addS = function addS(value) { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) + value); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.prototype.addM = function addM(matrix) { | ||
| matrix = Matrix.checkMatrix(matrix); | ||
| if (this.rows !== matrix.rows || | ||
| this.columns !== matrix.columns) { | ||
| throw new RangeError('Matrices dimensions must be equal'); | ||
| } | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) + matrix.get(i, j)); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.add = function add(matrix, value) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.add(value); | ||
| }; | ||
| AbstractMatrix.prototype.sub = function sub(value) { | ||
| if (typeof value === 'number') return this.subS(value); | ||
| return this.subM(value); | ||
| }; | ||
| AbstractMatrix.prototype.subS = function subS(value) { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) - value); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.prototype.subM = function subM(matrix) { | ||
| matrix = Matrix.checkMatrix(matrix); | ||
| if (this.rows !== matrix.rows || | ||
| this.columns !== matrix.columns) { | ||
| throw new RangeError('Matrices dimensions must be equal'); | ||
| } | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) - matrix.get(i, j)); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.sub = function sub(matrix, value) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.sub(value); | ||
| }; | ||
| AbstractMatrix.prototype.subtract = AbstractMatrix.prototype.sub; | ||
| AbstractMatrix.prototype.subtractS = AbstractMatrix.prototype.subS; | ||
| AbstractMatrix.prototype.subtractM = AbstractMatrix.prototype.subM; | ||
| AbstractMatrix.subtract = AbstractMatrix.sub; | ||
| AbstractMatrix.prototype.mul = function mul(value) { | ||
| if (typeof value === 'number') return this.mulS(value); | ||
| return this.mulM(value); | ||
| }; | ||
| AbstractMatrix.prototype.mulS = function mulS(value) { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) * value); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.prototype.mulM = function mulM(matrix) { | ||
| matrix = Matrix.checkMatrix(matrix); | ||
| if (this.rows !== matrix.rows || | ||
| this.columns !== matrix.columns) { | ||
| throw new RangeError('Matrices dimensions must be equal'); | ||
| } | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) * matrix.get(i, j)); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.mul = function mul(matrix, value) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.mul(value); | ||
| }; | ||
| AbstractMatrix.prototype.multiply = AbstractMatrix.prototype.mul; | ||
| AbstractMatrix.prototype.multiplyS = AbstractMatrix.prototype.mulS; | ||
| AbstractMatrix.prototype.multiplyM = AbstractMatrix.prototype.mulM; | ||
| AbstractMatrix.multiply = AbstractMatrix.mul; | ||
| AbstractMatrix.prototype.div = function div(value) { | ||
| if (typeof value === 'number') return this.divS(value); | ||
| return this.divM(value); | ||
| }; | ||
| AbstractMatrix.prototype.divS = function divS(value) { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) / value); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.prototype.divM = function divM(matrix) { | ||
| matrix = Matrix.checkMatrix(matrix); | ||
| if (this.rows !== matrix.rows || | ||
| this.columns !== matrix.columns) { | ||
| throw new RangeError('Matrices dimensions must be equal'); | ||
| } | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) / matrix.get(i, j)); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.div = function div(matrix, value) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.div(value); | ||
| }; | ||
| AbstractMatrix.prototype.divide = AbstractMatrix.prototype.div; | ||
| AbstractMatrix.prototype.divideS = AbstractMatrix.prototype.divS; | ||
| AbstractMatrix.prototype.divideM = AbstractMatrix.prototype.divM; | ||
| AbstractMatrix.divide = AbstractMatrix.div; | ||
| AbstractMatrix.prototype.mod = function mod(value) { | ||
| if (typeof value === 'number') return this.modS(value); | ||
| return this.modM(value); | ||
| }; | ||
| AbstractMatrix.prototype.modS = function modS(value) { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) % value); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.prototype.modM = function modM(matrix) { | ||
| matrix = Matrix.checkMatrix(matrix); | ||
| if (this.rows !== matrix.rows || | ||
| this.columns !== matrix.columns) { | ||
| throw new RangeError('Matrices dimensions must be equal'); | ||
| } | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) % matrix.get(i, j)); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.mod = function mod(matrix, value) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.mod(value); | ||
| }; | ||
| AbstractMatrix.prototype.modulus = AbstractMatrix.prototype.mod; | ||
| AbstractMatrix.prototype.modulusS = AbstractMatrix.prototype.modS; | ||
| AbstractMatrix.prototype.modulusM = AbstractMatrix.prototype.modM; | ||
| AbstractMatrix.modulus = AbstractMatrix.mod; | ||
| AbstractMatrix.prototype.and = function and(value) { | ||
| if (typeof value === 'number') return this.andS(value); | ||
| return this.andM(value); | ||
| }; | ||
| AbstractMatrix.prototype.andS = function andS(value) { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) & value); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.prototype.andM = function andM(matrix) { | ||
| matrix = Matrix.checkMatrix(matrix); | ||
| if (this.rows !== matrix.rows || | ||
| this.columns !== matrix.columns) { | ||
| throw new RangeError('Matrices dimensions must be equal'); | ||
| } | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) & matrix.get(i, j)); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.and = function and(matrix, value) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.and(value); | ||
| }; | ||
| AbstractMatrix.prototype.or = function or(value) { | ||
| if (typeof value === 'number') return this.orS(value); | ||
| return this.orM(value); | ||
| }; | ||
| AbstractMatrix.prototype.orS = function orS(value) { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) | value); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.prototype.orM = function orM(matrix) { | ||
| matrix = Matrix.checkMatrix(matrix); | ||
| if (this.rows !== matrix.rows || | ||
| this.columns !== matrix.columns) { | ||
| throw new RangeError('Matrices dimensions must be equal'); | ||
| } | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) | matrix.get(i, j)); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.or = function or(matrix, value) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.or(value); | ||
| }; | ||
| AbstractMatrix.prototype.xor = function xor(value) { | ||
| if (typeof value === 'number') return this.xorS(value); | ||
| return this.xorM(value); | ||
| }; | ||
| AbstractMatrix.prototype.xorS = function xorS(value) { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) ^ value); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.prototype.xorM = function xorM(matrix) { | ||
| matrix = Matrix.checkMatrix(matrix); | ||
| if (this.rows !== matrix.rows || | ||
| this.columns !== matrix.columns) { | ||
| throw new RangeError('Matrices dimensions must be equal'); | ||
| } | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) ^ matrix.get(i, j)); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.xor = function xor(matrix, value) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.xor(value); | ||
| }; | ||
| AbstractMatrix.prototype.leftShift = function leftShift(value) { | ||
| if (typeof value === 'number') return this.leftShiftS(value); | ||
| return this.leftShiftM(value); | ||
| }; | ||
| AbstractMatrix.prototype.leftShiftS = function leftShiftS(value) { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) << value); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.prototype.leftShiftM = function leftShiftM(matrix) { | ||
| matrix = Matrix.checkMatrix(matrix); | ||
| if (this.rows !== matrix.rows || | ||
| this.columns !== matrix.columns) { | ||
| throw new RangeError('Matrices dimensions must be equal'); | ||
| } | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) << matrix.get(i, j)); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.leftShift = function leftShift(matrix, value) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.leftShift(value); | ||
| }; | ||
| AbstractMatrix.prototype.signPropagatingRightShift = function signPropagatingRightShift(value) { | ||
| if (typeof value === 'number') return this.signPropagatingRightShiftS(value); | ||
| return this.signPropagatingRightShiftM(value); | ||
| }; | ||
| AbstractMatrix.prototype.signPropagatingRightShiftS = function signPropagatingRightShiftS(value) { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) >> value); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.prototype.signPropagatingRightShiftM = function signPropagatingRightShiftM(matrix) { | ||
| matrix = Matrix.checkMatrix(matrix); | ||
| if (this.rows !== matrix.rows || | ||
| this.columns !== matrix.columns) { | ||
| throw new RangeError('Matrices dimensions must be equal'); | ||
| } | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) >> matrix.get(i, j)); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.signPropagatingRightShift = function signPropagatingRightShift(matrix, value) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.signPropagatingRightShift(value); | ||
| }; | ||
| AbstractMatrix.prototype.rightShift = function rightShift(value) { | ||
| if (typeof value === 'number') return this.rightShiftS(value); | ||
| return this.rightShiftM(value); | ||
| }; | ||
| AbstractMatrix.prototype.rightShiftS = function rightShiftS(value) { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) >>> value); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.prototype.rightShiftM = function rightShiftM(matrix) { | ||
| matrix = Matrix.checkMatrix(matrix); | ||
| if (this.rows !== matrix.rows || | ||
| this.columns !== matrix.columns) { | ||
| throw new RangeError('Matrices dimensions must be equal'); | ||
| } | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) >>> matrix.get(i, j)); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.rightShift = function rightShift(matrix, value) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.rightShift(value); | ||
| }; | ||
| AbstractMatrix.prototype.zeroFillRightShift = AbstractMatrix.prototype.rightShift; | ||
| AbstractMatrix.prototype.zeroFillRightShiftS = AbstractMatrix.prototype.rightShiftS; | ||
| AbstractMatrix.prototype.zeroFillRightShiftM = AbstractMatrix.prototype.rightShiftM; | ||
| AbstractMatrix.zeroFillRightShift = AbstractMatrix.rightShift; | ||
| AbstractMatrix.prototype.not = function not() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, ~(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.not = function not(matrix) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.not(); | ||
| }; | ||
| AbstractMatrix.prototype.abs = function abs() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.abs(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.abs = function abs(matrix) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.abs(); | ||
| }; | ||
| AbstractMatrix.prototype.acos = function acos() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.acos(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.acos = function acos(matrix) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.acos(); | ||
| }; | ||
| AbstractMatrix.prototype.acosh = function acosh() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.acosh(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.acosh = function acosh(matrix) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.acosh(); | ||
| }; | ||
| AbstractMatrix.prototype.asin = function asin() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.asin(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.asin = function asin(matrix) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.asin(); | ||
| }; | ||
| AbstractMatrix.prototype.asinh = function asinh() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.asinh(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.asinh = function asinh(matrix) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.asinh(); | ||
| }; | ||
| AbstractMatrix.prototype.atan = function atan() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.atan(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.atan = function atan(matrix) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.atan(); | ||
| }; | ||
| AbstractMatrix.prototype.atanh = function atanh() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.atanh(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.atanh = function atanh(matrix) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.atanh(); | ||
| }; | ||
| AbstractMatrix.prototype.cbrt = function cbrt() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.cbrt(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.cbrt = function cbrt(matrix) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.cbrt(); | ||
| }; | ||
| AbstractMatrix.prototype.ceil = function ceil() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.ceil(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.ceil = function ceil(matrix) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.ceil(); | ||
| }; | ||
| AbstractMatrix.prototype.clz32 = function clz32() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.clz32(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.clz32 = function clz32(matrix) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.clz32(); | ||
| }; | ||
| AbstractMatrix.prototype.cos = function cos() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.cos(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.cos = function cos(matrix) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.cos(); | ||
| }; | ||
| AbstractMatrix.prototype.cosh = function cosh() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.cosh(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.cosh = function cosh(matrix) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.cosh(); | ||
| }; | ||
| AbstractMatrix.prototype.exp = function exp() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.exp(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.exp = function exp(matrix) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.exp(); | ||
| }; | ||
| AbstractMatrix.prototype.expm1 = function expm1() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.expm1(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.expm1 = function expm1(matrix) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.expm1(); | ||
| }; | ||
| AbstractMatrix.prototype.floor = function floor() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.floor(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.floor = function floor(matrix) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.floor(); | ||
| }; | ||
| AbstractMatrix.prototype.fround = function fround() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.fround(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.fround = function fround(matrix) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.fround(); | ||
| }; | ||
| AbstractMatrix.prototype.log = function log() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.log(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.log = function log(matrix) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.log(); | ||
| }; | ||
| AbstractMatrix.prototype.log1p = function log1p() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.log1p(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.log1p = function log1p(matrix) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.log1p(); | ||
| }; | ||
| AbstractMatrix.prototype.log10 = function log10() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.log10(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.log10 = function log10(matrix) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.log10(); | ||
| }; | ||
| AbstractMatrix.prototype.log2 = function log2() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.log2(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.log2 = function log2(matrix) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.log2(); | ||
| }; | ||
| AbstractMatrix.prototype.round = function round() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.round(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.round = function round(matrix) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.round(); | ||
| }; | ||
| AbstractMatrix.prototype.sign = function sign() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.sign(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.sign = function sign(matrix) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.sign(); | ||
| }; | ||
| AbstractMatrix.prototype.sin = function sin() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.sin(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.sin = function sin(matrix) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.sin(); | ||
| }; | ||
| AbstractMatrix.prototype.sinh = function sinh() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.sinh(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.sinh = function sinh(matrix) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.sinh(); | ||
| }; | ||
| AbstractMatrix.prototype.sqrt = function sqrt() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.sqrt(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.sqrt = function sqrt(matrix) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.sqrt(); | ||
| }; | ||
| AbstractMatrix.prototype.tan = function tan() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.tan(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.tan = function tan(matrix) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.tan(); | ||
| }; | ||
| AbstractMatrix.prototype.tanh = function tanh() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.tanh(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.tanh = function tanh(matrix) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.tanh(); | ||
| }; | ||
| AbstractMatrix.prototype.trunc = function trunc() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.trunc(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.trunc = function trunc(matrix) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.trunc(); | ||
| }; | ||
| AbstractMatrix.pow = function pow(matrix, arg0) { | ||
| var newMatrix = new Matrix(matrix); | ||
| return newMatrix.pow(arg0); | ||
| }; | ||
| AbstractMatrix.prototype.pow = function pow(value) { | ||
| if (typeof value === 'number') return this.powS(value); | ||
| return this.powM(value); | ||
| }; | ||
| AbstractMatrix.prototype.powS = function powS(value) { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.pow(this.get(i, j), value)); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| AbstractMatrix.prototype.powM = function powM(matrix) { | ||
| matrix = Matrix.checkMatrix(matrix); | ||
| if (this.rows !== matrix.rows || | ||
| this.columns !== matrix.columns) { | ||
| throw new RangeError('Matrices dimensions must be equal'); | ||
| } | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, Math.pow(this.get(i, j), matrix.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }; | ||
| } |
+0
-0
@@ -0,0 +0,0 @@ # [5.3.0](https://github.com/mljs/matrix/compare/v5.2.1...v5.3.0) (2019-03-23) |
+0
-0
@@ -0,0 +0,0 @@ The MIT License (MIT) |
+309
-237
| declare module 'ml-matrix' { | ||
| type MaybeMatrix = Matrix | number[][]; | ||
| type Rng = () => number; | ||
| type ScalarOrMatrix = number | Matrix; | ||
| type MaybeMatrix = AbstractMatrix | number[][]; | ||
| type ScalarOrMatrix = number | MaybeMatrix; | ||
| type MatrixDimension = 'row' | 'column'; | ||
| export class MatrixColumnView extends Matrix { | ||
| constructor(matrix: Matrix, column: number); | ||
| export interface IRandomOptions { | ||
| random: () => number; | ||
| } | ||
| export class MatrixColumnSelectionView extends Matrix { | ||
| constructor(matrix: Matrix, columnIndices: number[]); | ||
| export interface IRandomIntOptions { | ||
| min: number; | ||
| max: number; | ||
| random: () => number; | ||
| } | ||
| export class MatrixFlipColumnView extends Matrix { | ||
| constructor(matrix: Matrix); | ||
| export interface IRepeatOptions { | ||
| rows?: number; | ||
| columns?: number; | ||
| } | ||
| export class MatrixFlipRowView extends Matrix { | ||
| constructor(matrix: Matrix); | ||
| export interface IScaleOptions { | ||
| min?: number; | ||
| max?: number; | ||
| } | ||
| export class MatrixRowView extends Matrix { | ||
| constructor(matrix: Matrix, row: number); | ||
| export interface IVarianceOptions { | ||
| unbiased?: boolean; | ||
| mean?: number; | ||
| } | ||
| export class MatrixRowSelectionView extends Matrix { | ||
| constructor(matrix: Matrix, rowIndices: number[]); | ||
| export interface IVarianceByOptions { | ||
| unbiased?: boolean; | ||
| mean?: number[]; | ||
| } | ||
| export class MatrixSelectionView extends Matrix { | ||
| constructor(matrix: Matrix, rowIndices: number[], columnIndices: number[]); | ||
| } | ||
| export class MatrixSubView extends Matrix { | ||
| constructor( | ||
| matrix: Matrix, | ||
| startRow: number, | ||
| endRow: number, | ||
| startColumn: number, | ||
| endColumn: number | ||
| ); | ||
| } | ||
| export class MatrixTransposeView extends BaseView { | ||
| constructor(matrix: Matrix); | ||
| } | ||
| export class Matrix { | ||
| export abstract class AbstractMatrix { | ||
| readonly size: number; | ||
@@ -45,6 +36,2 @@ readonly rows: number; | ||
| constructor(nRows: number, nColumns: number); | ||
| constructor(data: number[][]); | ||
| constructor(otherMatrix: Matrix); | ||
| static from1DArray( | ||
@@ -59,9 +46,16 @@ newRows: number, | ||
| static ones(rows: number, columns: number): Matrix; | ||
| static rand(rows: number, columns: number, rng?: Rng): Matrix; | ||
| static random(rows: number, columns: number, rng?: Rng): Matrix; | ||
| static rand( | ||
| rows: number, | ||
| columns: number, | ||
| options?: IRandomOptions | ||
| ): Matrix; | ||
| static random( | ||
| rows: number, | ||
| columns: number, | ||
| options?: IRandomOptions | ||
| ): Matrix; | ||
| static randInt( | ||
| rows: number, | ||
| columns: number, | ||
| maxValue?: number, | ||
| rng?: Rng | ||
| options?: IRandomIntOptions | ||
| ): Matrix; | ||
@@ -72,10 +66,14 @@ static eye(rows: number, columns?: number, value?: number): Matrix; | ||
| static diagonal(data: number[], rows?: number, columns?: number): Matrix; | ||
| static min(matrix1: Matrix, matrix2: Matrix): Matrix; | ||
| static max(matrix1: Matrix, matrix2: Matrix): Matrix; | ||
| static min(matrix1: MaybeMatrix, matrix2: MaybeMatrix): Matrix; | ||
| static max(matrix1: MaybeMatrix, matrix2: MaybeMatrix): Matrix; | ||
| static checkMatrix(value: any): Matrix; | ||
| static isMatrix(value: any): value is Matrix; | ||
| static isMatrix(value: any): value is AbstractMatrix; | ||
| apply(callback: Function): this; | ||
| set(rowIndex: number, columnIndex: number, value: number): this; | ||
| get(rowIndex: number, columnIndex: number): number; | ||
| apply(callback: (row: number, column: number) => void): this; | ||
| to1DArray(): number[]; | ||
| to2DArray(): number[][]; | ||
| toJSON(): number[][]; | ||
| isRowVector(): boolean; | ||
@@ -88,43 +86,80 @@ isColumnVector(): boolean; | ||
| isReducedEchelonForm(): boolean; | ||
| set(rowIndex: number, columnIndex: number, value: number): this; | ||
| get(rowIndex: number, columnIndex: number): number; | ||
| repeat(rowRep: number, colRep: number): Matrix; | ||
| repeat(options?: IRepeatOptions): Matrix; | ||
| fill(value: number): this; | ||
| neg(): Matrix; | ||
| negate(): Matrix; | ||
| addRow(index: number, array: number[] | Matrix): this; | ||
| neg(): this; | ||
| negate(): this; | ||
| getRow(index: number): number[]; | ||
| getRowVector(index: number): Matrix; | ||
| setRow(index: number, array: number[] | Matrix): Matrix; | ||
| swapRows(row1: number, row2: number): Matrix; | ||
| addColumn(index: number, array: number[] | Matrix): this; | ||
| setRow(index: number, array: number[] | AbstractMatrix): this; | ||
| swapRows(row1: number, row2: number): this; | ||
| getColumn(index: number): number[]; | ||
| getColumnVector(index: number): Matrix; | ||
| setColumn(index: number, array: number[] | Matrix): Matrix; | ||
| swapColumns(column1: number, column2: number): Matrix; | ||
| addRowVector(vector: number[] | Matrix): Matrix; | ||
| subRowVector(vector: number[] | Matrix): Matrix; | ||
| mulRowVector(vector: number[] | Matrix): Matrix; | ||
| divRowVector(vector: number[] | Matrix): Matrix; | ||
| addColumnVector(vector: number[] | Matrix): Matrix; | ||
| subColumnVector(vector: number[] | Matrix): Matrix; | ||
| mulColumnVector(vector: number[] | Matrix): Matrix; | ||
| divColumnVector(vector: number[] | Matrix): Matrix; | ||
| mulRow(index: number, value: number): Matrix; | ||
| mulColumn(index: number, value: number): Matrix; | ||
| setColumn(index: number, array: number[] | AbstractMatrix): this; | ||
| swapColumns(column1: number, column2: number): this; | ||
| addRowVector(vector: number[] | AbstractMatrix): this; | ||
| subRowVector(vector: number[] | AbstractMatrix): this; | ||
| mulRowVector(vector: number[] | AbstractMatrix): this; | ||
| divRowVector(vector: number[] | AbstractMatrix): this; | ||
| addColumnVector(vector: number[] | AbstractMatrix): this; | ||
| subColumnVector(vector: number[] | AbstractMatrix): this; | ||
| mulColumnVector(vector: number[] | AbstractMatrix): this; | ||
| divColumnVector(vector: number[] | AbstractMatrix): this; | ||
| mulRow(index: number, value: number): this; | ||
| mulColumn(index: number, value: number): this; | ||
| max(): number; | ||
| maxIndex(): number[]; | ||
| maxIndex(): [number, number]; | ||
| min(): number; | ||
| minIndex(): number[]; | ||
| minIndex(): [number, number]; | ||
| maxRow(row: number): number; | ||
| maxRowIndex(row: number): number[]; | ||
| maxRowIndex(row: number): [number, number]; | ||
| minRow(row: number): number; | ||
| minRowIndex(row: number): number[]; | ||
| minRowIndex(row: number): [number, number]; | ||
| maxColumn(column: number): number; | ||
| maxColumnIndex(column: number): number[]; | ||
| maxColumnIndex(column: number): [number, number]; | ||
| minColumn(column: number): number; | ||
| minColumnIndex(column: number): number[]; | ||
| minColumnIndex(column: number): [number, number]; | ||
| diag(): number[]; | ||
| diagonal(): number[]; | ||
| norm(type: 'frobenius' | 'max'): number; | ||
| cumulativeSum(): this; | ||
| dot(vector: AbstractMatrix): number; | ||
| mmul(other: MaybeMatrix): Matrix; | ||
| strassen2x2(other: MaybeMatrix): Matrix; | ||
| strassen3x3(other: MaybeMatrix): Matrix; | ||
| mmulStrassen(y: MaybeMatrix): Matrix; | ||
| scaleRows(options?: IScaleOptions): Matrix; | ||
| scaleColumns(options?: IScaleOptions): Matrix; | ||
| flipRows(): this; | ||
| flipColumns(): this; | ||
| kroneckerProduct(other: MaybeMatrix): Matrix; | ||
| tensorProduct(other: MaybeMatrix): Matrix; | ||
| transpose(): Matrix; | ||
| sortRows(compareFunction?: (a: number, b: number) => number): this; | ||
| sortColumns(compareFunction?: (a: number, b: number) => number): this; | ||
| subMatrix( | ||
| startRow: number, | ||
| endRow: number, | ||
| startColumn: number, | ||
| endColumn: number | ||
| ): Matrix; | ||
| subMatrixRow( | ||
| indices: number[], | ||
| startColumn?: number, | ||
| endColumn?: number | ||
| ): Matrix; | ||
| subMatrixColumn( | ||
| indices: number[], | ||
| startRow?: number, | ||
| endRow?: number | ||
| ): Matrix; | ||
| setSubMatrix( | ||
| matrix: MaybeMatrix | number[], | ||
| startRow: number, | ||
| startColumn: number | ||
| ): Matrix; | ||
| selection(rowIndices: number[], columnIndices: number[]): Matrix; | ||
| trace(): number; | ||
| clone(): Matrix; | ||
| /** | ||
@@ -163,47 +198,11 @@ * Returns the sum of all elements of the matrix. | ||
| prod(): number; | ||
| norm(type: 'frobenius' | 'max'): number; | ||
| cumulativeSum(): this; | ||
| dot(vector2: Matrix): number; | ||
| mmul(other: Matrix): Matrix; | ||
| strassen2x2(other: Matrix): Matrix; | ||
| strassen3x3(other: Matrix): Matrix; | ||
| mmulStrassen(y: Matrix): Matrix; | ||
| scaleRows(min?: number, max?: number): Matrix; | ||
| scaleColumns(min?: number, max?: number): Matrix; | ||
| reverseRows(): this; | ||
| reverseColumns(): this; | ||
| kroneckerProduct(other: Matrix): Matrix; | ||
| tensorProduct(other: Matrix): Matrix; | ||
| transpose(): Matrix; | ||
| sortRows(compareFunction: Function): this; | ||
| sortColumns(compareFunction: Function): this; | ||
| subMatrix( | ||
| startRow: number, | ||
| endRow: number, | ||
| startColumn: number, | ||
| endColumn: number | ||
| ): Matrix; | ||
| subMatrixRow( | ||
| indices: number[], | ||
| startColumn?: number, | ||
| endColumn?: number | ||
| ): Matrix; | ||
| subMatrixColumn( | ||
| indices: number[], | ||
| startRow?: number, | ||
| endRow?: number | ||
| ): Matrix; | ||
| setSubMatrix( | ||
| matrix: Matrix | number[], | ||
| startRow: number, | ||
| startColumn: number | ||
| ): Matrix; | ||
| selection(rowIndices: number[], columnIndices: number[]): Matrix; | ||
| trace(): number; | ||
| clone(): Matrix; | ||
| entropy(eps?: number): number; | ||
| variance(unbiased?: boolean, means?: number[]): number[]; | ||
| standardDeviation(unbiased?: boolean, means?: number[]): number[]; | ||
| variance(options?: IVarianceOptions): number; | ||
| variance(by: MatrixDimension, options?: IVarianceByOptions): number[]; | ||
| standardDeviation(options?: IVarianceOptions): number; | ||
| standardDeviation( | ||
| by: MatrixDimension, | ||
| options?: IVarianceByOptions | ||
| ): number[]; | ||
| // From here we document methods dynamically generated from operators | ||
@@ -213,110 +212,203 @@ | ||
| // inplace | ||
| add(value: ScalarOrMatrix): Matrix; | ||
| sub(value: ScalarOrMatrix): Matrix; | ||
| subtract(value: ScalarOrMatrix): Matrix; | ||
| mul(value: ScalarOrMatrix): Matrix; | ||
| multiply(value: ScalarOrMatrix): Matrix; | ||
| div(value: ScalarOrMatrix): Matrix; | ||
| divide(value: ScalarOrMatrix): Matrix; | ||
| mod(value: ScalarOrMatrix): Matrix; | ||
| modulus(value: ScalarOrMatrix): Matrix; | ||
| and(value: ScalarOrMatrix): Matrix; | ||
| or(value: ScalarOrMatrix): Matrix; | ||
| xor(value: ScalarOrMatrix): Matrix; | ||
| leftShift(value: ScalarOrMatrix): Matrix; | ||
| signPropagatingRightShift(value: ScalarOrMatrix): Matrix; | ||
| rightShift(value: ScalarOrMatrix): Matrix; | ||
| zeroFillRightShift(value: ScalarOrMatrix): Matrix; | ||
| add(value: ScalarOrMatrix): this; | ||
| sub(value: ScalarOrMatrix): this; | ||
| subtract(value: ScalarOrMatrix): this; | ||
| mul(value: ScalarOrMatrix): this; | ||
| multiply(value: ScalarOrMatrix): this; | ||
| div(value: ScalarOrMatrix): this; | ||
| divide(value: ScalarOrMatrix): this; | ||
| mod(value: ScalarOrMatrix): this; | ||
| modulus(value: ScalarOrMatrix): this; | ||
| and(value: ScalarOrMatrix): this; | ||
| or(value: ScalarOrMatrix): this; | ||
| xor(value: ScalarOrMatrix): this; | ||
| leftShift(value: ScalarOrMatrix): this; | ||
| signPropagatingRightShift(value: ScalarOrMatrix): this; | ||
| rightShift(value: ScalarOrMatrix): this; | ||
| zeroFillRightShift(value: ScalarOrMatrix): this; | ||
| // new matrix | ||
| static add(matrix: Matrix, value: ScalarOrMatrix): Matrix; | ||
| static sub(matrix: Matrix, value: ScalarOrMatrix): Matrix; | ||
| static subtract(matrix: Matrix, value: ScalarOrMatrix): Matrix; | ||
| static mul(matrix: Matrix, value: ScalarOrMatrix): Matrix; | ||
| static multiply(matrix: Matrix, value: ScalarOrMatrix): Matrix; | ||
| static div(matrix: Matrix, value: ScalarOrMatrix): Matrix; | ||
| static divide(matrix: Matrix, value: ScalarOrMatrix): Matrix; | ||
| static mod(matrix: Matrix, value: ScalarOrMatrix): Matrix; | ||
| static modulus(matrix: Matrix, value: ScalarOrMatrix): Matrix; | ||
| static and(matrix: Matrix, value: ScalarOrMatrix): Matrix; | ||
| static or(matrix: Matrix, value: ScalarOrMatrix): Matrix; | ||
| static xor(matrix: Matrix, value: ScalarOrMatrix): Matrix; | ||
| static leftShift(matrix: Matrix, value: ScalarOrMatrix): Matrix; | ||
| static add(matrix: MaybeMatrix, value: ScalarOrMatrix): Matrix; | ||
| static sub(matrix: MaybeMatrix, value: ScalarOrMatrix): Matrix; | ||
| static subtract(matrix: MaybeMatrix, value: ScalarOrMatrix): Matrix; | ||
| static mul(matrix: MaybeMatrix, value: ScalarOrMatrix): Matrix; | ||
| static multiply(matrix: MaybeMatrix, value: ScalarOrMatrix): Matrix; | ||
| static div(matrix: MaybeMatrix, value: ScalarOrMatrix): Matrix; | ||
| static divide(matrix: MaybeMatrix, value: ScalarOrMatrix): Matrix; | ||
| static mod(matrix: MaybeMatrix, value: ScalarOrMatrix): Matrix; | ||
| static modulus(matrix: MaybeMatrix, value: ScalarOrMatrix): Matrix; | ||
| static and(matrix: MaybeMatrix, value: ScalarOrMatrix): Matrix; | ||
| static or(matrix: MaybeMatrix, value: ScalarOrMatrix): Matrix; | ||
| static xor(matrix: MaybeMatrix, value: ScalarOrMatrix): Matrix; | ||
| static leftShift(matrix: MaybeMatrix, value: ScalarOrMatrix): Matrix; | ||
| static signPropagatingRightShift( | ||
| matrix: Matrix, | ||
| matrix: MaybeMatrix, | ||
| value: ScalarOrMatrix | ||
| ): Matrix; | ||
| static rightShift(matrix: Matrix, value: ScalarOrMatrix): Matrix; | ||
| static zeroFillRightShift(matrix: Matrix, value: ScalarOrMatrix): Matrix; | ||
| static rightShift(matrix: MaybeMatrix, value: ScalarOrMatrix): Matrix; | ||
| static zeroFillRightShift( | ||
| matrix: MaybeMatrix, | ||
| value: ScalarOrMatrix | ||
| ): Matrix; | ||
| // Functional operators (one arg) | ||
| // inplace | ||
| not(): Matrix; | ||
| abs(): Matrix; | ||
| acos(): Matrix; | ||
| acosh(): Matrix; | ||
| asin(): Matrix; | ||
| asinh(): Matrix; | ||
| atan(): Matrix; | ||
| atanh(): Matrix; | ||
| cbrt(): Matrix; | ||
| ceil(): Matrix; | ||
| clz32(): Matrix; | ||
| cos(): Matrix; | ||
| cosh(): Matrix; | ||
| exp(): Matrix; | ||
| expm1(): Matrix; | ||
| floor(): Matrix; | ||
| fround(): Matrix; | ||
| log(): Matrix; | ||
| log1p(): Matrix; | ||
| log10(): Matrix; | ||
| log2(): Matrix; | ||
| round(): Matrix; | ||
| sign(): Matrix; | ||
| sin(): Matrix; | ||
| sinh(): Matrix; | ||
| sqrt(): Matrix; | ||
| tan(): Matrix; | ||
| tanh(): Matrix; | ||
| trunc(): Matrix; | ||
| not(): this; | ||
| abs(): this; | ||
| acos(): this; | ||
| acosh(): this; | ||
| asin(): this; | ||
| asinh(): this; | ||
| atan(): this; | ||
| atanh(): this; | ||
| cbrt(): this; | ||
| ceil(): this; | ||
| clz32(): this; | ||
| cos(): this; | ||
| cosh(): this; | ||
| exp(): this; | ||
| expm1(): this; | ||
| floor(): this; | ||
| fround(): this; | ||
| log(): this; | ||
| log1p(): this; | ||
| log10(): this; | ||
| log2(): this; | ||
| round(): this; | ||
| sign(): this; | ||
| sin(): this; | ||
| sinh(): this; | ||
| sqrt(): this; | ||
| tan(): this; | ||
| tanh(): this; | ||
| trunc(): this; | ||
| // new matrix | ||
| static not(value: Matrix): Matrix; | ||
| static abs(value: Matrix): Matrix; | ||
| static acos(value: Matrix): Matrix; | ||
| static acosh(value: Matrix): Matrix; | ||
| static asin(value: Matrix): Matrix; | ||
| static asinh(value: Matrix): Matrix; | ||
| static atan(value: Matrix): Matrix; | ||
| static atanh(value: Matrix): Matrix; | ||
| static cbrt(value: Matrix): Matrix; | ||
| static ceil(value: Matrix): Matrix; | ||
| static clz32(value: Matrix): Matrix; | ||
| static cos(value: Matrix): Matrix; | ||
| static cosh(value: Matrix): Matrix; | ||
| static exp(value: Matrix): Matrix; | ||
| static expm1(value: Matrix): Matrix; | ||
| static floor(value: Matrix): Matrix; | ||
| static fround(value: Matrix): Matrix; | ||
| static log(value: Matrix): Matrix; | ||
| static log1p(value: Matrix): Matrix; | ||
| static log10(value: Matrix): Matrix; | ||
| static log2(value: Matrix): Matrix; | ||
| static round(value: Matrix): Matrix; | ||
| static sign(value: Matrix): Matrix; | ||
| static sin(value: Matrix): Matrix; | ||
| static sinh(value: Matrix): Matrix; | ||
| static sqrt(value: Matrix): Matrix; | ||
| static tan(value: Matrix): Matrix; | ||
| static tanh(value: Matrix): Matrix; | ||
| static trunc(value: Matrix): Matrix; | ||
| static not(value: MaybeMatrix): Matrix; | ||
| static abs(value: MaybeMatrix): Matrix; | ||
| static acos(value: MaybeMatrix): Matrix; | ||
| static acosh(value: MaybeMatrix): Matrix; | ||
| static asin(value: MaybeMatrix): Matrix; | ||
| static asinh(value: MaybeMatrix): Matrix; | ||
| static atan(value: MaybeMatrix): Matrix; | ||
| static atanh(value: MaybeMatrix): Matrix; | ||
| static cbrt(value: MaybeMatrix): Matrix; | ||
| static ceil(value: MaybeMatrix): Matrix; | ||
| static clz32(value: MaybeMatrix): Matrix; | ||
| static cos(value: MaybeMatrix): Matrix; | ||
| static cosh(value: MaybeMatrix): Matrix; | ||
| static exp(value: MaybeMatrix): Matrix; | ||
| static expm1(value: MaybeMatrix): Matrix; | ||
| static floor(value: MaybeMatrix): Matrix; | ||
| static fround(value: MaybeMatrix): Matrix; | ||
| static log(value: MaybeMatrix): Matrix; | ||
| static log1p(value: MaybeMatrix): Matrix; | ||
| static log10(value: MaybeMatrix): Matrix; | ||
| static log2(value: MaybeMatrix): Matrix; | ||
| static round(value: MaybeMatrix): Matrix; | ||
| static sign(value: MaybeMatrix): Matrix; | ||
| static sin(value: MaybeMatrix): Matrix; | ||
| static sinh(value: MaybeMatrix): Matrix; | ||
| static sqrt(value: MaybeMatrix): Matrix; | ||
| static tan(value: MaybeMatrix): Matrix; | ||
| static tanh(value: MaybeMatrix): Matrix; | ||
| static trunc(value: MaybeMatrix): Matrix; | ||
| // Functional operators with one arg | ||
| // inplace | ||
| pow(value: ScalarOrMatrix): Matrix; | ||
| pow(value: ScalarOrMatrix): this; | ||
| // new matrix | ||
| static pow(matrix: Matrix, value: ScalarOrMatrix): Matrix; | ||
| static pow(matrix: MaybeMatrix, value: ScalarOrMatrix): Matrix; | ||
| } | ||
| export class Matrix extends AbstractMatrix { | ||
| constructor(nRows: number, nColumns: number); | ||
| constructor(data: number[][]); | ||
| constructor(otherMatrix: AbstractMatrix); | ||
| } | ||
| export default Matrix; | ||
| class SingularValueDecomposition { | ||
| export class MatrixColumnView extends AbstractMatrix { | ||
| constructor(matrix: AbstractMatrix, column: number); | ||
| } | ||
| export class MatrixColumnSelectionView extends AbstractMatrix { | ||
| constructor(matrix: AbstractMatrix, columnIndices: number[]); | ||
| } | ||
| export class MatrixFlipColumnView extends AbstractMatrix { | ||
| constructor(matrix: AbstractMatrix); | ||
| } | ||
| export class MatrixFlipRowView extends AbstractMatrix { | ||
| constructor(matrix: AbstractMatrix); | ||
| } | ||
| export class MatrixRowView extends AbstractMatrix { | ||
| constructor(matrix: AbstractMatrix, row: number); | ||
| } | ||
| export class MatrixRowSelectionView extends AbstractMatrix { | ||
| constructor(matrix: AbstractMatrix, rowIndices: number[]); | ||
| } | ||
| export class MatrixSelectionView extends AbstractMatrix { | ||
| constructor( | ||
| matrix: AbstractMatrix, | ||
| rowIndices: number[], | ||
| columnIndices: number[] | ||
| ); | ||
| } | ||
| export class MatrixSubView extends AbstractMatrix { | ||
| constructor( | ||
| matrix: AbstractMatrix, | ||
| startRow: number, | ||
| endRow: number, | ||
| startColumn: number, | ||
| endColumn: number | ||
| ); | ||
| } | ||
| export class MatrixTransposeView extends AbstractMatrix { | ||
| constructor(matrix: AbstractMatrix); | ||
| } | ||
| export interface IWrap1DOptions { | ||
| rows?: number; | ||
| } | ||
| export function wrap( | ||
| array: number[], | ||
| options?: IWrap1DOptions | ||
| ): WrapperMatrix1D; | ||
| export function wrap(twoDAray: number[][]): WrapperMatrix2D; | ||
| export class WrapperMatrix1D extends AbstractMatrix { | ||
| constructor(data: number[], options?: IWrap1DOptions); | ||
| } | ||
| export class WrapperMatrix2D extends AbstractMatrix { | ||
| constructor(data: number[][]); | ||
| } | ||
| export function solve( | ||
| leftHandSide: MaybeMatrix, | ||
| rightHandSide: MaybeMatrix, | ||
| useSVD?: boolean | ||
| ): Matrix; | ||
| export function inverse(matrix: MaybeMatrix, useSVD?: boolean): Matrix; | ||
| export function determinant(matrix: MaybeMatrix): number; | ||
| export interface ILinearDependenciesOptions { | ||
| thresholdValue?: number; | ||
| thresholdError?: number; | ||
| } | ||
| export function linearDependencies( | ||
| matrix: MaybeMatrix, | ||
| options?: ILinearDependenciesOptions | ||
| ): Matrix; | ||
| export function pseudoInverse( | ||
| matrix: MaybeMatrix, | ||
| threshold?: number | ||
| ): Matrix; | ||
| export interface ISVDOptions { | ||
| computeLeftSingularVectors?: boolean; | ||
| computeRightSingularVectors?: boolean; | ||
| autoTranspose?: boolean; | ||
| } | ||
| export class SingularValueDecomposition { | ||
| constructor(value: MaybeMatrix, options?: ISVDOptions); | ||
@@ -335,10 +427,8 @@ inverse(): Matrix; | ||
| } | ||
| export interface ISVDOptions { | ||
| computeLeftSingularVectors?: boolean; | ||
| computeRightSingularVectors?: boolean; | ||
| autoTranspose?: boolean; | ||
| export { SingularValueDecomposition as SVD }; | ||
| export interface IEVDOptions { | ||
| assumeSymmetric?: boolean; | ||
| } | ||
| export { SingularValueDecomposition, SingularValueDecomposition as SVD }; | ||
| class EigenvalueDecomposition { | ||
| export class EigenvalueDecomposition { | ||
| constructor(value: MaybeMatrix, options?: IEVDOptions); | ||
@@ -350,8 +440,5 @@ readonly diagonalMatrix: Matrix; | ||
| } | ||
| export interface IEVDOptions { | ||
| assumeSymmetric?: boolean; | ||
| } | ||
| export { EigenvalueDecomposition, EigenvalueDecomposition as EVD }; | ||
| export { EigenvalueDecomposition as EVD }; | ||
| class CholeskyDecomposition { | ||
| export class CholeskyDecomposition { | ||
| constructor(value: MaybeMatrix); | ||
@@ -361,5 +448,5 @@ solve(value: Matrix): Matrix; | ||
| } | ||
| export { CholeskyDecomposition, CholeskyDecomposition as CHO }; | ||
| export { CholeskyDecomposition as CHO }; | ||
| class LuDecomposition { | ||
| export class LuDecomposition { | ||
| constructor(value: MaybeMatrix); | ||
@@ -373,3 +460,3 @@ isSingular(): boolean; | ||
| } | ||
| export { LuDecomposition, LuDecomposition as LU }; | ||
| export { LuDecomposition as LU }; | ||
@@ -384,17 +471,2 @@ class QrDecomposition { | ||
| export { QrDecomposition, QrDecomposition as QR }; | ||
| export function solve( | ||
| leftHandSide: MaybeMatrix, | ||
| rightHandSide: MaybeMatrix, | ||
| useSVD?: boolean | ||
| ): Matrix; | ||
| export function inverse(matrix: MaybeMatrix, useSVD?: boolean): Matrix; | ||
| export function determinant(matrix: MaybeMatrix): number; | ||
| export function pseudoInverse( | ||
| matrix: MaybeMatrix, | ||
| threshold?: number | ||
| ): Matrix; | ||
| } |
+2
-1
| { | ||
| "name": "ml-matrix", | ||
| "version": "6.0.0-5", | ||
| "version": "6.0.0-6", | ||
| "description": "Matrix manipulation and computation library", | ||
@@ -8,2 +8,3 @@ "main": "matrix.js", | ||
| "types": "matrix.d.ts", | ||
| "sideEffects": false, | ||
| "files": [ | ||
@@ -10,0 +11,0 @@ "matrix.d.ts", |
+0
-0
@@ -0,0 +0,0 @@ # ml-matrix |
+0
-0
@@ -0,0 +0,0 @@ export function hypotenuse(a, b) { |
+3
-3
@@ -1,8 +0,7 @@ | ||
| export { default, default as Matrix } from './matrix'; | ||
| export { default as AbstractMatrix } from './abstractMatrix'; | ||
| export { AbstractMatrix, default, default as Matrix } from './matrix'; | ||
| export * from './views/index'; | ||
| export { wrap } from './wrap/wrap'; | ||
| export { default as WrapperMatrix1D } from './wrap/WrapperMatrix1D'; | ||
| export { default as WrapperMatrix2D } from './wrap/WrapperMatrix2D'; | ||
| export { default as WrapperMatrix1D } from './wrap/WrapperMatrix1D'; | ||
@@ -13,2 +12,3 @@ export { solve, inverse } from './decompositions'; | ||
| export { pseudoInverse } from './pseudoInverse'; | ||
| export { | ||
@@ -15,0 +15,0 @@ default as SingularValueDecomposition, |
@@ -49,2 +49,3 @@ import Matrix from './matrix'; | ||
| const { thresholdValue = 10e-10, thresholdError = 10e-10 } = options; | ||
| matrix = Matrix.checkMatrix(matrix); | ||
@@ -51,0 +52,0 @@ var n = matrix.rows; |
+1690
-3
@@ -1,9 +0,1694 @@ | ||
| import AbstractMatrix from './abstractMatrix'; | ||
| import rescale from 'ml-array-rescale'; | ||
| import { | ||
| checkRowVector, | ||
| checkRowIndex, | ||
| checkColumnIndex, | ||
| checkColumnVector, | ||
| checkRowIndex, | ||
| checkRowVector | ||
| checkRange, | ||
| checkIndices | ||
| } from './util'; | ||
| import { | ||
| sumByRow, | ||
| sumByColumn, | ||
| sumAll, | ||
| productByRow, | ||
| productByColumn, | ||
| productAll, | ||
| varianceByRow, | ||
| varianceByColumn, | ||
| varianceAll | ||
| } from './stat'; | ||
| import { inspectMatrix } from './inspect'; | ||
| import { installMathOperations } from './mathOperations'; | ||
| export class AbstractMatrix { | ||
| /** | ||
| * Constructs a Matrix with the chosen dimensions from a 1D array | ||
| * @param {number} newRows - Number of rows | ||
| * @param {number} newColumns - Number of columns | ||
| * @param {Array} newData - A 1D array containing data for the matrix | ||
| * @return {Matrix} - The new matrix | ||
| */ | ||
| static from1DArray(newRows, newColumns, newData) { | ||
| var length = newRows * newColumns; | ||
| if (length !== newData.length) { | ||
| throw new RangeError('data length does not match given dimensions'); | ||
| } | ||
| var newMatrix = new Matrix(newRows, newColumns); | ||
| for (var row = 0; row < newRows; row++) { | ||
| for (var column = 0; column < newColumns; column++) { | ||
| newMatrix.set(row, column, newData[row * newColumns + column]); | ||
| } | ||
| } | ||
| return newMatrix; | ||
| } | ||
| /** | ||
| * Creates a row vector, a matrix with only one row. | ||
| * @param {Array} newData - A 1D array containing data for the vector | ||
| * @return {Matrix} - The new matrix | ||
| */ | ||
| static rowVector(newData) { | ||
| var vector = new Matrix(1, newData.length); | ||
| for (var i = 0; i < newData.length; i++) { | ||
| vector.set(0, i, newData[i]); | ||
| } | ||
| return vector; | ||
| } | ||
| /** | ||
| * Creates a column vector, a matrix with only one column. | ||
| * @param {Array} newData - A 1D array containing data for the vector | ||
| * @return {Matrix} - The new matrix | ||
| */ | ||
| static columnVector(newData) { | ||
| var vector = new Matrix(newData.length, 1); | ||
| for (var i = 0; i < newData.length; i++) { | ||
| vector.set(i, 0, newData[i]); | ||
| } | ||
| return vector; | ||
| } | ||
| /** | ||
| * Creates a matrix with the given dimensions. Values will be set to zero. | ||
| * @param {number} rows - Number of rows | ||
| * @param {number} columns - Number of columns | ||
| * @return {Matrix} - The new matrix | ||
| */ | ||
| static zeros(rows, columns) { | ||
| return new Matrix(rows, columns); | ||
| } | ||
| /** | ||
| * Creates a matrix with the given dimensions. Values will be set to one. | ||
| * @param {number} rows - Number of rows | ||
| * @param {number} columns - Number of columns | ||
| * @return {Matrix} - The new matrix | ||
| */ | ||
| static ones(rows, columns) { | ||
| return new Matrix(rows, columns).fill(1); | ||
| } | ||
| /** | ||
| * Creates a matrix with the given dimensions. Values will be randomly set. | ||
| * @param {number} rows - Number of rows | ||
| * @param {number} columns - Number of columns | ||
| * @param {object} [options] | ||
| * @param {function} [options.random=Math.random] - Random number generator | ||
| * @return {Matrix} The new matrix | ||
| */ | ||
| static rand(rows, columns, options = {}) { | ||
| if (typeof options !== 'object') { | ||
| throw new TypeError('options must be an object'); | ||
| } | ||
| const { random = Math.random } = options; | ||
| var matrix = new Matrix(rows, columns); | ||
| for (var i = 0; i < rows; i++) { | ||
| for (var j = 0; j < columns; j++) { | ||
| matrix.set(i, j, random()); | ||
| } | ||
| } | ||
| return matrix; | ||
| } | ||
| /** | ||
| * Creates a matrix with the given dimensions. Values will be random integers. | ||
| * @param {number} rows - Number of rows | ||
| * @param {number} columns - Number of columns | ||
| * @param {object} [options] | ||
| * @param {number} [options.min=0] - Minimum value | ||
| * @param {number} [options.max=1000] - Maximum value | ||
| * @param {function} [options.random=Math.random] - Random number generator | ||
| * @return {Matrix} The new matrix | ||
| */ | ||
| static randInt(rows, columns, options = {}) { | ||
| if (typeof options !== 'object') { | ||
| throw new TypeError('options must be an object'); | ||
| } | ||
| const { min = 0, max = 1000, random = Math.random } = options; | ||
| if (!Number.isInteger(min)) throw new TypeError('min must be an integer'); | ||
| if (!Number.isInteger(max)) throw new TypeError('max must be an integer'); | ||
| if (min >= max) throw new RangeError('min must be smaller than max'); | ||
| var interval = max - min; | ||
| var matrix = new Matrix(rows, columns); | ||
| for (var i = 0; i < rows; i++) { | ||
| for (var j = 0; j < columns; j++) { | ||
| var value = min + Math.round(random() * interval); | ||
| matrix.set(i, j, value); | ||
| } | ||
| } | ||
| return matrix; | ||
| } | ||
| /** | ||
| * Creates an identity matrix with the given dimension. Values of the diagonal will be 1 and others will be 0. | ||
| * @param {number} rows - Number of rows | ||
| * @param {number} [columns=rows] - Number of columns | ||
| * @param {number} [value=1] - Value to fill the diagonal with | ||
| * @return {Matrix} - The new identity matrix | ||
| */ | ||
| static eye(rows, columns, value) { | ||
| if (columns === undefined) columns = rows; | ||
| if (value === undefined) value = 1; | ||
| var min = Math.min(rows, columns); | ||
| var matrix = this.zeros(rows, columns); | ||
| for (var i = 0; i < min; i++) { | ||
| matrix.set(i, i, value); | ||
| } | ||
| return matrix; | ||
| } | ||
| /** | ||
| * Creates a diagonal matrix based on the given array. | ||
| * @param {Array} data - Array containing the data for the diagonal | ||
| * @param {number} [rows] - Number of rows (Default: data.length) | ||
| * @param {number} [columns] - Number of columns (Default: rows) | ||
| * @return {Matrix} - The new diagonal matrix | ||
| */ | ||
| static diag(data, rows, columns) { | ||
| var l = data.length; | ||
| if (rows === undefined) rows = l; | ||
| if (columns === undefined) columns = rows; | ||
| var min = Math.min(l, rows, columns); | ||
| var matrix = this.zeros(rows, columns); | ||
| for (var i = 0; i < min; i++) { | ||
| matrix.set(i, i, data[i]); | ||
| } | ||
| return matrix; | ||
| } | ||
| /** | ||
| * Returns a matrix whose elements are the minimum between matrix1 and matrix2 | ||
| * @param {Matrix} matrix1 | ||
| * @param {Matrix} matrix2 | ||
| * @return {Matrix} | ||
| */ | ||
| static min(matrix1, matrix2) { | ||
| matrix1 = this.checkMatrix(matrix1); | ||
| matrix2 = this.checkMatrix(matrix2); | ||
| var rows = matrix1.rows; | ||
| var columns = matrix1.columns; | ||
| var result = new Matrix(rows, columns); | ||
| for (var i = 0; i < rows; i++) { | ||
| for (var j = 0; j < columns; j++) { | ||
| result.set(i, j, Math.min(matrix1.get(i, j), matrix2.get(i, j))); | ||
| } | ||
| } | ||
| return result; | ||
| } | ||
| /** | ||
| * Returns a matrix whose elements are the maximum between matrix1 and matrix2 | ||
| * @param {Matrix} matrix1 | ||
| * @param {Matrix} matrix2 | ||
| * @return {Matrix} | ||
| */ | ||
| static max(matrix1, matrix2) { | ||
| matrix1 = this.checkMatrix(matrix1); | ||
| matrix2 = this.checkMatrix(matrix2); | ||
| var rows = matrix1.rows; | ||
| var columns = matrix1.columns; | ||
| var result = new this(rows, columns); | ||
| for (var i = 0; i < rows; i++) { | ||
| for (var j = 0; j < columns; j++) { | ||
| result.set(i, j, Math.max(matrix1.get(i, j), matrix2.get(i, j))); | ||
| } | ||
| } | ||
| return result; | ||
| } | ||
| /** | ||
| * Check that the provided value is a Matrix and tries to instantiate one if not | ||
| * @param {*} value - The value to check | ||
| * @return {Matrix} | ||
| */ | ||
| static checkMatrix(value) { | ||
| return AbstractMatrix.isMatrix(value) ? value : new Matrix(value); | ||
| } | ||
| /** | ||
| * Returns true if the argument is a Matrix, false otherwise | ||
| * @param {*} value - The value to check | ||
| * @return {boolean} | ||
| */ | ||
| static isMatrix(value) { | ||
| return value != null && value.klass === 'Matrix'; | ||
| } | ||
| /** | ||
| * @prop {number} size - The number of elements in the matrix. | ||
| */ | ||
| get size() { | ||
| return this.rows * this.columns; | ||
| } | ||
| /** | ||
| * Applies a callback for each element of the matrix. The function is called in the matrix (this) context. | ||
| * @param {function} callback - Function that will be called with two parameters : i (row) and j (column) | ||
| * @return {Matrix} this | ||
| */ | ||
| apply(callback) { | ||
| if (typeof callback !== 'function') { | ||
| throw new TypeError('callback must be a function'); | ||
| } | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| callback.call(this, i, j); | ||
| } | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Returns a new 1D array filled row by row with the matrix values | ||
| * @return {Array} | ||
| */ | ||
| to1DArray() { | ||
| var array = []; | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| array.push(this.get(i, j)); | ||
| } | ||
| } | ||
| return array; | ||
| } | ||
| /** | ||
| * Returns a 2D array containing a copy of the data | ||
| * @return {Array} | ||
| */ | ||
| to2DArray() { | ||
| var copy = []; | ||
| for (var i = 0; i < this.rows; i++) { | ||
| copy.push([]); | ||
| for (var j = 0; j < this.columns; j++) { | ||
| copy[i].push(this.get(i, j)); | ||
| } | ||
| } | ||
| return copy; | ||
| } | ||
| toJSON() { | ||
| return this.to2DArray(); | ||
| } | ||
| /** | ||
| * @return {boolean} true if the matrix has one row | ||
| */ | ||
| isRowVector() { | ||
| return this.rows === 1; | ||
| } | ||
| /** | ||
| * @return {boolean} true if the matrix has one column | ||
| */ | ||
| isColumnVector() { | ||
| return this.columns === 1; | ||
| } | ||
| /** | ||
| * @return {boolean} true if the matrix has one row or one column | ||
| */ | ||
| isVector() { | ||
| return this.rows === 1 || this.columns === 1; | ||
| } | ||
| /** | ||
| * @return {boolean} true if the matrix has the same number of rows and columns | ||
| */ | ||
| isSquare() { | ||
| return this.rows === this.columns; | ||
| } | ||
| /** | ||
| * @return {boolean} true if the matrix is square and has the same values on both sides of the diagonal | ||
| */ | ||
| isSymmetric() { | ||
| if (this.isSquare()) { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j <= i; j++) { | ||
| if (this.get(i, j) !== this.get(j, i)) { | ||
| return false; | ||
| } | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
| return false; | ||
| } | ||
| /** | ||
| * @return true if the matrix is in echelon form | ||
| */ | ||
| isEchelonForm() { | ||
| let i = 0; | ||
| let j = 0; | ||
| let previousColumn = -1; | ||
| let isEchelonForm = true; | ||
| let checked = false; | ||
| while (i < this.rows && isEchelonForm) { | ||
| j = 0; | ||
| checked = false; | ||
| while (j < this.columns && checked === false) { | ||
| if (this.get(i, j) === 0) { | ||
| j++; | ||
| } else if (this.get(i, j) === 1 && j > previousColumn) { | ||
| checked = true; | ||
| previousColumn = j; | ||
| } else { | ||
| isEchelonForm = false; | ||
| checked = true; | ||
| } | ||
| } | ||
| i++; | ||
| } | ||
| return isEchelonForm; | ||
| } | ||
| /** | ||
| * @return true if the matrix is in reduced echelon form | ||
| */ | ||
| isReducedEchelonForm() { | ||
| let i = 0; | ||
| let j = 0; | ||
| let previousColumn = -1; | ||
| let isReducedEchelonForm = true; | ||
| let checked = false; | ||
| while (i < this.rows && isReducedEchelonForm) { | ||
| j = 0; | ||
| checked = false; | ||
| while (j < this.columns && checked === false) { | ||
| if (this.get(i, j) === 0) { | ||
| j++; | ||
| } else if (this.get(i, j) === 1 && j > previousColumn) { | ||
| checked = true; | ||
| previousColumn = j; | ||
| } else { | ||
| isReducedEchelonForm = false; | ||
| checked = true; | ||
| } | ||
| } | ||
| for (let k = j + 1; k < this.rows; k++) { | ||
| if (this.get(i, k) !== 0) { | ||
| isReducedEchelonForm = false; | ||
| } | ||
| } | ||
| i++; | ||
| } | ||
| return isReducedEchelonForm; | ||
| } | ||
| /** | ||
| * Sets a given element of the matrix. | ||
| * @abstract | ||
| * @param {number} rowIndex - Index of the row | ||
| * @param {number} columnIndex - Index of the column | ||
| * @param {number} value - The new value for the element | ||
| * @return {Matrix} this | ||
| */ | ||
| // eslint-disable-next-line no-unused-vars | ||
| set(rowIndex, columnIndex, value) { | ||
| throw new Error('set method is unimplemented'); | ||
| } | ||
| /** | ||
| * Returns the given element of the matrix. | ||
| * @abstract | ||
| * @param {number} rowIndex - Index of the row | ||
| * @param {number} columnIndex - Index of the column | ||
| * @return {number} | ||
| */ | ||
| // eslint-disable-next-line no-unused-vars | ||
| get(rowIndex, columnIndex) { | ||
| throw new Error('get method is unimplemented'); | ||
| } | ||
| /** | ||
| * Creates a new matrix that is a repetition of the current matrix. New matrix has rows times the number of | ||
| * rows of the original matrix, and columns times the number of columns of the original matrix. | ||
| * @param {object} [options] | ||
| * @param {number} [options.rows=1] - Number of times the rows should be repeated | ||
| * @param {number} [options.columns=1] - Number of times the columns should be repeated | ||
| * @return {Matrix} | ||
| * @example | ||
| * var matrix = new Matrix([[1,2]]); | ||
| * matrix.repeat({ rows: 2 }); // [[1,2],[1,2]] | ||
| */ | ||
| repeat(options = {}) { | ||
| if (typeof options !== 'object') { | ||
| throw new TypeError('options must be an object'); | ||
| } | ||
| const { rows = 1, columns = 1 } = options; | ||
| if (!Number.isInteger(rows) || rows <= 0) { | ||
| throw new TypeError('rows must be a positive integer'); | ||
| } | ||
| if (!Number.isInteger(columns) || columns <= 0) { | ||
| throw new TypeError('columns must be a positive integer'); | ||
| } | ||
| var matrix = new Matrix(this.rows * rows, this.columns * columns); | ||
| for (var i = 0; i < rows; i++) { | ||
| for (var j = 0; j < columns; j++) { | ||
| matrix.setSubMatrix(this, this.rows * i, this.columns * j); | ||
| } | ||
| } | ||
| return matrix; | ||
| } | ||
| /** | ||
| * Fills the matrix with a given value. All elements will be set to this value. | ||
| * @param {number} value - New value | ||
| * @return {Matrix} this | ||
| */ | ||
| fill(value) { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, value); | ||
| } | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Negates the matrix. All elements will be multiplied by (-1) | ||
| * @return {Matrix} this | ||
| */ | ||
| neg() { | ||
| return this.mulS(-1); | ||
| } | ||
| /** | ||
| * Returns a new array from the given row index | ||
| * @param {number} index - Row index | ||
| * @return {Array} | ||
| */ | ||
| getRow(index) { | ||
| checkRowIndex(this, index); | ||
| var row = []; | ||
| for (var i = 0; i < this.columns; i++) { | ||
| row.push(this.get(index, i)); | ||
| } | ||
| return row; | ||
| } | ||
| /** | ||
| * Returns a new row vector from the given row index | ||
| * @param {number} index - Row index | ||
| * @return {Matrix} | ||
| */ | ||
| getRowVector(index) { | ||
| return Matrix.rowVector(this.getRow(index)); | ||
| } | ||
| /** | ||
| * Sets a row at the given index | ||
| * @param {number} index - Row index | ||
| * @param {Array|Matrix} array - Array or vector | ||
| * @return {Matrix} this | ||
| */ | ||
| setRow(index, array) { | ||
| checkRowIndex(this, index); | ||
| array = checkRowVector(this, array); | ||
| for (var i = 0; i < this.columns; i++) { | ||
| this.set(index, i, array[i]); | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Swaps two rows | ||
| * @param {number} row1 - First row index | ||
| * @param {number} row2 - Second row index | ||
| * @return {Matrix} this | ||
| */ | ||
| swapRows(row1, row2) { | ||
| checkRowIndex(this, row1); | ||
| checkRowIndex(this, row2); | ||
| for (var i = 0; i < this.columns; i++) { | ||
| var temp = this.get(row1, i); | ||
| this.set(row1, i, this.get(row2, i)); | ||
| this.set(row2, i, temp); | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Returns a new array from the given column index | ||
| * @param {number} index - Column index | ||
| * @return {Array} | ||
| */ | ||
| getColumn(index) { | ||
| checkColumnIndex(this, index); | ||
| var column = []; | ||
| for (var i = 0; i < this.rows; i++) { | ||
| column.push(this.get(i, index)); | ||
| } | ||
| return column; | ||
| } | ||
| /** | ||
| * Returns a new column vector from the given column index | ||
| * @param {number} index - Column index | ||
| * @return {Matrix} | ||
| */ | ||
| getColumnVector(index) { | ||
| return Matrix.columnVector(this.getColumn(index)); | ||
| } | ||
| /** | ||
| * Sets a column at the given index | ||
| * @param {number} index - Column index | ||
| * @param {Array|Matrix} array - Array or vector | ||
| * @return {Matrix} this | ||
| */ | ||
| setColumn(index, array) { | ||
| checkColumnIndex(this, index); | ||
| array = checkColumnVector(this, array); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| this.set(i, index, array[i]); | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Swaps two columns | ||
| * @param {number} column1 - First column index | ||
| * @param {number} column2 - Second column index | ||
| * @return {Matrix} this | ||
| */ | ||
| swapColumns(column1, column2) { | ||
| checkColumnIndex(this, column1); | ||
| checkColumnIndex(this, column2); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| var temp = this.get(i, column1); | ||
| this.set(i, column1, this.get(i, column2)); | ||
| this.set(i, column2, temp); | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Adds the values of a vector to each row | ||
| * @param {Array|Matrix} vector - Array or vector | ||
| * @return {Matrix} this | ||
| */ | ||
| addRowVector(vector) { | ||
| vector = checkRowVector(this, vector); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) + vector[j]); | ||
| } | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Subtracts the values of a vector from each row | ||
| * @param {Array|Matrix} vector - Array or vector | ||
| * @return {Matrix} this | ||
| */ | ||
| subRowVector(vector) { | ||
| vector = checkRowVector(this, vector); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) - vector[j]); | ||
| } | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Multiplies the values of a vector with each row | ||
| * @param {Array|Matrix} vector - Array or vector | ||
| * @return {Matrix} this | ||
| */ | ||
| mulRowVector(vector) { | ||
| vector = checkRowVector(this, vector); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) * vector[j]); | ||
| } | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Divides the values of each row by those of a vector | ||
| * @param {Array|Matrix} vector - Array or vector | ||
| * @return {Matrix} this | ||
| */ | ||
| divRowVector(vector) { | ||
| vector = checkRowVector(this, vector); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) / vector[j]); | ||
| } | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Adds the values of a vector to each column | ||
| * @param {Array|Matrix} vector - Array or vector | ||
| * @return {Matrix} this | ||
| */ | ||
| addColumnVector(vector) { | ||
| vector = checkColumnVector(this, vector); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) + vector[i]); | ||
| } | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Subtracts the values of a vector from each column | ||
| * @param {Array|Matrix} vector - Array or vector | ||
| * @return {Matrix} this | ||
| */ | ||
| subColumnVector(vector) { | ||
| vector = checkColumnVector(this, vector); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) - vector[i]); | ||
| } | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Multiplies the values of a vector with each column | ||
| * @param {Array|Matrix} vector - Array or vector | ||
| * @return {Matrix} this | ||
| */ | ||
| mulColumnVector(vector) { | ||
| vector = checkColumnVector(this, vector); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) * vector[i]); | ||
| } | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Divides the values of each column by those of a vector | ||
| * @param {Array|Matrix} vector - Array or vector | ||
| * @return {Matrix} this | ||
| */ | ||
| divColumnVector(vector) { | ||
| vector = checkColumnVector(this, vector); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) / vector[i]); | ||
| } | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Multiplies the values of a row with a scalar | ||
| * @param {number} index - Row index | ||
| * @param {number} value | ||
| * @return {Matrix} this | ||
| */ | ||
| mulRow(index, value) { | ||
| checkRowIndex(this, index); | ||
| for (var i = 0; i < this.columns; i++) { | ||
| this.set(index, i, this.get(index, i) * value); | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Multiplies the values of a column with a scalar | ||
| * @param {number} index - Column index | ||
| * @param {number} value | ||
| * @return {Matrix} this | ||
| */ | ||
| mulColumn(index, value) { | ||
| checkColumnIndex(this, index); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| this.set(i, index, this.get(i, index) * value); | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Returns the maximum value of the matrix | ||
| * @return {number} | ||
| */ | ||
| max() { | ||
| var v = this.get(0, 0); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| if (this.get(i, j) > v) { | ||
| v = this.get(i, j); | ||
| } | ||
| } | ||
| } | ||
| return v; | ||
| } | ||
| /** | ||
| * Returns the index of the maximum value | ||
| * @return {Array} | ||
| */ | ||
| maxIndex() { | ||
| var v = this.get(0, 0); | ||
| var idx = [0, 0]; | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| if (this.get(i, j) > v) { | ||
| v = this.get(i, j); | ||
| idx[0] = i; | ||
| idx[1] = j; | ||
| } | ||
| } | ||
| } | ||
| return idx; | ||
| } | ||
| /** | ||
| * Returns the minimum value of the matrix | ||
| * @return {number} | ||
| */ | ||
| min() { | ||
| var v = this.get(0, 0); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| if (this.get(i, j) < v) { | ||
| v = this.get(i, j); | ||
| } | ||
| } | ||
| } | ||
| return v; | ||
| } | ||
| /** | ||
| * Returns the index of the minimum value | ||
| * @return {Array} | ||
| */ | ||
| minIndex() { | ||
| var v = this.get(0, 0); | ||
| var idx = [0, 0]; | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| if (this.get(i, j) < v) { | ||
| v = this.get(i, j); | ||
| idx[0] = i; | ||
| idx[1] = j; | ||
| } | ||
| } | ||
| } | ||
| return idx; | ||
| } | ||
| /** | ||
| * Returns the maximum value of one row | ||
| * @param {number} row - Row index | ||
| * @return {number} | ||
| */ | ||
| maxRow(row) { | ||
| checkRowIndex(this, row); | ||
| var v = this.get(row, 0); | ||
| for (var i = 1; i < this.columns; i++) { | ||
| if (this.get(row, i) > v) { | ||
| v = this.get(row, i); | ||
| } | ||
| } | ||
| return v; | ||
| } | ||
| /** | ||
| * Returns the index of the maximum value of one row | ||
| * @param {number} row - Row index | ||
| * @return {Array} | ||
| */ | ||
| maxRowIndex(row) { | ||
| checkRowIndex(this, row); | ||
| var v = this.get(row, 0); | ||
| var idx = [row, 0]; | ||
| for (var i = 1; i < this.columns; i++) { | ||
| if (this.get(row, i) > v) { | ||
| v = this.get(row, i); | ||
| idx[1] = i; | ||
| } | ||
| } | ||
| return idx; | ||
| } | ||
| /** | ||
| * Returns the minimum value of one row | ||
| * @param {number} row - Row index | ||
| * @return {number} | ||
| */ | ||
| minRow(row) { | ||
| checkRowIndex(this, row); | ||
| var v = this.get(row, 0); | ||
| for (var i = 1; i < this.columns; i++) { | ||
| if (this.get(row, i) < v) { | ||
| v = this.get(row, i); | ||
| } | ||
| } | ||
| return v; | ||
| } | ||
| /** | ||
| * Returns the index of the maximum value of one row | ||
| * @param {number} row - Row index | ||
| * @return {Array} | ||
| */ | ||
| minRowIndex(row) { | ||
| checkRowIndex(this, row); | ||
| var v = this.get(row, 0); | ||
| var idx = [row, 0]; | ||
| for (var i = 1; i < this.columns; i++) { | ||
| if (this.get(row, i) < v) { | ||
| v = this.get(row, i); | ||
| idx[1] = i; | ||
| } | ||
| } | ||
| return idx; | ||
| } | ||
| /** | ||
| * Returns the maximum value of one column | ||
| * @param {number} column - Column index | ||
| * @return {number} | ||
| */ | ||
| maxColumn(column) { | ||
| checkColumnIndex(this, column); | ||
| var v = this.get(0, column); | ||
| for (var i = 1; i < this.rows; i++) { | ||
| if (this.get(i, column) > v) { | ||
| v = this.get(i, column); | ||
| } | ||
| } | ||
| return v; | ||
| } | ||
| /** | ||
| * Returns the index of the maximum value of one column | ||
| * @param {number} column - Column index | ||
| * @return {Array} | ||
| */ | ||
| maxColumnIndex(column) { | ||
| checkColumnIndex(this, column); | ||
| var v = this.get(0, column); | ||
| var idx = [0, column]; | ||
| for (var i = 1; i < this.rows; i++) { | ||
| if (this.get(i, column) > v) { | ||
| v = this.get(i, column); | ||
| idx[0] = i; | ||
| } | ||
| } | ||
| return idx; | ||
| } | ||
| /** | ||
| * Returns the minimum value of one column | ||
| * @param {number} column - Column index | ||
| * @return {number} | ||
| */ | ||
| minColumn(column) { | ||
| checkColumnIndex(this, column); | ||
| var v = this.get(0, column); | ||
| for (var i = 1; i < this.rows; i++) { | ||
| if (this.get(i, column) < v) { | ||
| v = this.get(i, column); | ||
| } | ||
| } | ||
| return v; | ||
| } | ||
| /** | ||
| * Returns the index of the minimum value of one column | ||
| * @param {number} column - Column index | ||
| * @return {Array} | ||
| */ | ||
| minColumnIndex(column) { | ||
| checkColumnIndex(this, column); | ||
| var v = this.get(0, column); | ||
| var idx = [0, column]; | ||
| for (var i = 1; i < this.rows; i++) { | ||
| if (this.get(i, column) < v) { | ||
| v = this.get(i, column); | ||
| idx[0] = i; | ||
| } | ||
| } | ||
| return idx; | ||
| } | ||
| /** | ||
| * Returns an array containing the diagonal values of the matrix | ||
| * @return {Array} | ||
| */ | ||
| diag() { | ||
| var min = Math.min(this.rows, this.columns); | ||
| var diag = []; | ||
| for (var i = 0; i < min; i++) { | ||
| diag.push(this.get(i, i)); | ||
| } | ||
| return diag; | ||
| } | ||
| /** | ||
| * Returns the norm of a matrix. | ||
| * @param {string} type - "frobenius" (default) or "max" return resp. the Frobenius norm and the max norm. | ||
| * @return {number} | ||
| */ | ||
| norm(type = 'frobenius') { | ||
| var result = 0; | ||
| if (type === 'max') { | ||
| return this.max(); | ||
| } else if (type === 'frobenius') { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| result = result + this.get(i, j) * this.get(i, j); | ||
| } | ||
| } | ||
| return Math.sqrt(result); | ||
| } else { | ||
| throw new RangeError(`unknown norm type: ${type}`); | ||
| } | ||
| } | ||
| /** | ||
| * Computes the cumulative sum of the matrix elements (in place, row by row) | ||
| * @return {Matrix} this | ||
| */ | ||
| cumulativeSum() { | ||
| var sum = 0; | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| sum += this.get(i, j); | ||
| this.set(i, j, sum); | ||
| } | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Computes the dot (scalar) product between the matrix and another. | ||
| * @param {Matrix} vector2 vector | ||
| * @return {number} | ||
| */ | ||
| dot(vector2) { | ||
| if (AbstractMatrix.isMatrix(vector2)) vector2 = vector2.to1DArray(); | ||
| var vector1 = this.to1DArray(); | ||
| if (vector1.length !== vector2.length) { | ||
| throw new RangeError('vectors do not have the same size'); | ||
| } | ||
| var dot = 0; | ||
| for (var i = 0; i < vector1.length; i++) { | ||
| dot += vector1[i] * vector2[i]; | ||
| } | ||
| return dot; | ||
| } | ||
| /** | ||
| * Returns the matrix product between this and other | ||
| * @param {Matrix} other | ||
| * @return {Matrix} | ||
| */ | ||
| mmul(other) { | ||
| other = Matrix.checkMatrix(other); | ||
| if (this.columns !== other.rows) { | ||
| // eslint-disable-next-line no-console | ||
| console.warn( | ||
| 'Number of columns of left matrix are not equal to number of rows of right matrix.' | ||
| ); | ||
| } | ||
| var m = this.rows; | ||
| var n = this.columns; | ||
| var p = other.columns; | ||
| var result = new Matrix(m, p); | ||
| var Bcolj = new Array(n); | ||
| for (var j = 0; j < p; j++) { | ||
| for (var k = 0; k < n; k++) { | ||
| Bcolj[k] = other.get(k, j); | ||
| } | ||
| for (var i = 0; i < m; i++) { | ||
| var s = 0; | ||
| for (k = 0; k < n; k++) { | ||
| s += this.get(i, k) * Bcolj[k]; | ||
| } | ||
| result.set(i, j, s); | ||
| } | ||
| } | ||
| return result; | ||
| } | ||
| strassen2x2(other) { | ||
| other = Matrix.checkMatrix(other); | ||
| var result = new Matrix(2, 2); | ||
| const a11 = this.get(0, 0); | ||
| const b11 = other.get(0, 0); | ||
| const a12 = this.get(0, 1); | ||
| const b12 = other.get(0, 1); | ||
| const a21 = this.get(1, 0); | ||
| const b21 = other.get(1, 0); | ||
| const a22 = this.get(1, 1); | ||
| const b22 = other.get(1, 1); | ||
| // Compute intermediate values. | ||
| const m1 = (a11 + a22) * (b11 + b22); | ||
| const m2 = (a21 + a22) * b11; | ||
| const m3 = a11 * (b12 - b22); | ||
| const m4 = a22 * (b21 - b11); | ||
| const m5 = (a11 + a12) * b22; | ||
| const m6 = (a21 - a11) * (b11 + b12); | ||
| const m7 = (a12 - a22) * (b21 + b22); | ||
| // Combine intermediate values into the output. | ||
| const c00 = m1 + m4 - m5 + m7; | ||
| const c01 = m3 + m5; | ||
| const c10 = m2 + m4; | ||
| const c11 = m1 - m2 + m3 + m6; | ||
| result.set(0, 0, c00); | ||
| result.set(0, 1, c01); | ||
| result.set(1, 0, c10); | ||
| result.set(1, 1, c11); | ||
| return result; | ||
| } | ||
| strassen3x3(other) { | ||
| other = Matrix.checkMatrix(other); | ||
| var result = new Matrix(3, 3); | ||
| const a00 = this.get(0, 0); | ||
| const a01 = this.get(0, 1); | ||
| const a02 = this.get(0, 2); | ||
| const a10 = this.get(1, 0); | ||
| const a11 = this.get(1, 1); | ||
| const a12 = this.get(1, 2); | ||
| const a20 = this.get(2, 0); | ||
| const a21 = this.get(2, 1); | ||
| const a22 = this.get(2, 2); | ||
| const b00 = other.get(0, 0); | ||
| const b01 = other.get(0, 1); | ||
| const b02 = other.get(0, 2); | ||
| const b10 = other.get(1, 0); | ||
| const b11 = other.get(1, 1); | ||
| const b12 = other.get(1, 2); | ||
| const b20 = other.get(2, 0); | ||
| const b21 = other.get(2, 1); | ||
| const b22 = other.get(2, 2); | ||
| const m1 = (a00 + a01 + a02 - a10 - a11 - a21 - a22) * b11; | ||
| const m2 = (a00 - a10) * (-b01 + b11); | ||
| const m3 = a11 * (-b00 + b01 + b10 - b11 - b12 - b20 + b22); | ||
| const m4 = (-a00 + a10 + a11) * (b00 - b01 + b11); | ||
| const m5 = (a10 + a11) * (-b00 + b01); | ||
| const m6 = a00 * b00; | ||
| const m7 = (-a00 + a20 + a21) * (b00 - b02 + b12); | ||
| const m8 = (-a00 + a20) * (b02 - b12); | ||
| const m9 = (a20 + a21) * (-b00 + b02); | ||
| const m10 = (a00 + a01 + a02 - a11 - a12 - a20 - a21) * b12; | ||
| const m11 = a21 * (-b00 + b02 + b10 - b11 - b12 - b20 + b21); | ||
| const m12 = (-a02 + a21 + a22) * (b11 + b20 - b21); | ||
| const m13 = (a02 - a22) * (b11 - b21); | ||
| const m14 = a02 * b20; | ||
| const m15 = (a21 + a22) * (-b20 + b21); | ||
| const m16 = (-a02 + a11 + a12) * (b12 + b20 - b22); | ||
| const m17 = (a02 - a12) * (b12 - b22); | ||
| const m18 = (a11 + a12) * (-b20 + b22); | ||
| const m19 = a01 * b10; | ||
| const m20 = a12 * b21; | ||
| const m21 = a10 * b02; | ||
| const m22 = a20 * b01; | ||
| const m23 = a22 * b22; | ||
| const c00 = m6 + m14 + m19; | ||
| const c01 = m1 + m4 + m5 + m6 + m12 + m14 + m15; | ||
| const c02 = m6 + m7 + m9 + m10 + m14 + m16 + m18; | ||
| const c10 = m2 + m3 + m4 + m6 + m14 + m16 + m17; | ||
| const c11 = m2 + m4 + m5 + m6 + m20; | ||
| const c12 = m14 + m16 + m17 + m18 + m21; | ||
| const c20 = m6 + m7 + m8 + m11 + m12 + m13 + m14; | ||
| const c21 = m12 + m13 + m14 + m15 + m22; | ||
| const c22 = m6 + m7 + m8 + m9 + m23; | ||
| result.set(0, 0, c00); | ||
| result.set(0, 1, c01); | ||
| result.set(0, 2, c02); | ||
| result.set(1, 0, c10); | ||
| result.set(1, 1, c11); | ||
| result.set(1, 2, c12); | ||
| result.set(2, 0, c20); | ||
| result.set(2, 1, c21); | ||
| result.set(2, 2, c22); | ||
| return result; | ||
| } | ||
| /** | ||
| * Returns the matrix product between x and y. More efficient than mmul(other) only when we multiply squared matrix and when the size of the matrix is > 1000. | ||
| * @param {Matrix} y | ||
| * @return {Matrix} | ||
| */ | ||
| mmulStrassen(y) { | ||
| y = Matrix.checkMatrix(y); | ||
| var x = this.clone(); | ||
| var r1 = x.rows; | ||
| var c1 = x.columns; | ||
| var r2 = y.rows; | ||
| var c2 = y.columns; | ||
| if (c1 !== r2) { | ||
| // eslint-disable-next-line no-console | ||
| console.warn( | ||
| `Multiplying ${r1} x ${c1} and ${r2} x ${c2} matrix: dimensions do not match.` | ||
| ); | ||
| } | ||
| // Put a matrix into the top left of a matrix of zeros. | ||
| // `rows` and `cols` are the dimensions of the output matrix. | ||
| function embed(mat, rows, cols) { | ||
| var r = mat.rows; | ||
| var c = mat.columns; | ||
| if (r === rows && c === cols) { | ||
| return mat; | ||
| } else { | ||
| var resultat = AbstractMatrix.zeros(rows, cols); | ||
| resultat = resultat.setSubMatrix(mat, 0, 0); | ||
| return resultat; | ||
| } | ||
| } | ||
| // Make sure both matrices are the same size. | ||
| // This is exclusively for simplicity: | ||
| // this algorithm can be implemented with matrices of different sizes. | ||
| var r = Math.max(r1, r2); | ||
| var c = Math.max(c1, c2); | ||
| x = embed(x, r, c); | ||
| y = embed(y, r, c); | ||
| // Our recursive multiplication function. | ||
| function blockMult(a, b, rows, cols) { | ||
| // For small matrices, resort to naive multiplication. | ||
| if (rows <= 512 || cols <= 512) { | ||
| return a.mmul(b); // a is equivalent to this | ||
| } | ||
| // Apply dynamic padding. | ||
| if (rows % 2 === 1 && cols % 2 === 1) { | ||
| a = embed(a, rows + 1, cols + 1); | ||
| b = embed(b, rows + 1, cols + 1); | ||
| } else if (rows % 2 === 1) { | ||
| a = embed(a, rows + 1, cols); | ||
| b = embed(b, rows + 1, cols); | ||
| } else if (cols % 2 === 1) { | ||
| a = embed(a, rows, cols + 1); | ||
| b = embed(b, rows, cols + 1); | ||
| } | ||
| var halfRows = parseInt(a.rows / 2, 10); | ||
| var halfCols = parseInt(a.columns / 2, 10); | ||
| // Subdivide input matrices. | ||
| var a11 = a.subMatrix(0, halfRows - 1, 0, halfCols - 1); | ||
| var b11 = b.subMatrix(0, halfRows - 1, 0, halfCols - 1); | ||
| var a12 = a.subMatrix(0, halfRows - 1, halfCols, a.columns - 1); | ||
| var b12 = b.subMatrix(0, halfRows - 1, halfCols, b.columns - 1); | ||
| var a21 = a.subMatrix(halfRows, a.rows - 1, 0, halfCols - 1); | ||
| var b21 = b.subMatrix(halfRows, b.rows - 1, 0, halfCols - 1); | ||
| var a22 = a.subMatrix(halfRows, a.rows - 1, halfCols, a.columns - 1); | ||
| var b22 = b.subMatrix(halfRows, b.rows - 1, halfCols, b.columns - 1); | ||
| // Compute intermediate values. | ||
| var m1 = blockMult( | ||
| AbstractMatrix.add(a11, a22), | ||
| AbstractMatrix.add(b11, b22), | ||
| halfRows, | ||
| halfCols | ||
| ); | ||
| var m2 = blockMult(AbstractMatrix.add(a21, a22), b11, halfRows, halfCols); | ||
| var m3 = blockMult(a11, AbstractMatrix.sub(b12, b22), halfRows, halfCols); | ||
| var m4 = blockMult(a22, AbstractMatrix.sub(b21, b11), halfRows, halfCols); | ||
| var m5 = blockMult(AbstractMatrix.add(a11, a12), b22, halfRows, halfCols); | ||
| var m6 = blockMult( | ||
| AbstractMatrix.sub(a21, a11), | ||
| AbstractMatrix.add(b11, b12), | ||
| halfRows, | ||
| halfCols | ||
| ); | ||
| var m7 = blockMult( | ||
| AbstractMatrix.sub(a12, a22), | ||
| AbstractMatrix.add(b21, b22), | ||
| halfRows, | ||
| halfCols | ||
| ); | ||
| // Combine intermediate values into the output. | ||
| var c11 = AbstractMatrix.add(m1, m4); | ||
| c11.sub(m5); | ||
| c11.add(m7); | ||
| var c12 = AbstractMatrix.add(m3, m5); | ||
| var c21 = AbstractMatrix.add(m2, m4); | ||
| var c22 = AbstractMatrix.sub(m1, m2); | ||
| c22.add(m3); | ||
| c22.add(m6); | ||
| // Crop output to the desired size (undo dynamic padding). | ||
| var resultat = AbstractMatrix.zeros(2 * c11.rows, 2 * c11.columns); | ||
| resultat = resultat.setSubMatrix(c11, 0, 0); | ||
| resultat = resultat.setSubMatrix(c12, c11.rows, 0); | ||
| resultat = resultat.setSubMatrix(c21, 0, c11.columns); | ||
| resultat = resultat.setSubMatrix(c22, c11.rows, c11.columns); | ||
| return resultat.subMatrix(0, rows - 1, 0, cols - 1); | ||
| } | ||
| return blockMult(x, y, r, c); | ||
| } | ||
| /** | ||
| * Returns a row-by-row scaled matrix | ||
| * @param {object} [options] | ||
| * @param {number} [options.min=0] - Minimum scaled value | ||
| * @param {number} [optiens.max=1] - Maximum scaled value | ||
| * @return {Matrix} - The scaled matrix | ||
| */ | ||
| scaleRows(options = {}) { | ||
| if (typeof options !== 'object') { | ||
| throw new TypeError('options must be an object'); | ||
| } | ||
| const { min = 0, max = 1 } = options; | ||
| if (!Number.isFinite(min)) throw new TypeError('min must be a number'); | ||
| if (!Number.isFinite(max)) throw new TypeError('max must be a number'); | ||
| if (min >= max) throw new RangeError('min must be smaller than max'); | ||
| var newMatrix = new Matrix(this.rows, this.columns); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| const row = this.getRow(i); | ||
| rescale(row, { min, max, output: row }); | ||
| newMatrix.setRow(i, row); | ||
| } | ||
| return newMatrix; | ||
| } | ||
| /** | ||
| * Returns a new column-by-column scaled matrix | ||
| * @param {object} [options] | ||
| * @param {number} [options.min=0] - Minimum scaled value | ||
| * @param {number} [optiens.max=1] - Maximum scaled value | ||
| * @return {Matrix} - The new scaled matrix | ||
| * @example | ||
| * var matrix = new Matrix([[1,2],[-1,0]]); | ||
| * var scaledMatrix = matrix.scaleColumns(); // [[1,1],[0,0]] | ||
| */ | ||
| scaleColumns(options = {}) { | ||
| if (typeof options !== 'object') { | ||
| throw new TypeError('options must be an object'); | ||
| } | ||
| const { min = 0, max = 1 } = options; | ||
| if (!Number.isFinite(min)) throw new TypeError('min must be a number'); | ||
| if (!Number.isFinite(max)) throw new TypeError('max must be a number'); | ||
| if (min >= max) throw new RangeError('min must be smaller than max'); | ||
| var newMatrix = new Matrix(this.rows, this.columns); | ||
| for (var i = 0; i < this.columns; i++) { | ||
| const column = this.getColumn(i); | ||
| rescale(column, { | ||
| min: min, | ||
| max: max, | ||
| output: column | ||
| }); | ||
| newMatrix.setColumn(i, column); | ||
| } | ||
| return newMatrix; | ||
| } | ||
| flipRows() { | ||
| const middle = Math.ceil(this.columns / 2); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < middle; j++) { | ||
| var first = this.get(i, j); | ||
| var last = this.get(i, this.columns - 1 - j); | ||
| this.set(i, j, last); | ||
| this.set(i, this.columns - 1 - j, first); | ||
| } | ||
| } | ||
| return this; | ||
| } | ||
| flipColumns() { | ||
| const middle = Math.ceil(this.rows / 2); | ||
| for (var j = 0; j < this.columns; j++) { | ||
| for (var i = 0; i < middle; i++) { | ||
| var first = this.get(i, j); | ||
| var last = this.get(this.rows - 1 - i, j); | ||
| this.set(i, j, last); | ||
| this.set(this.rows - 1 - i, j, first); | ||
| } | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Returns the Kronecker product (also known as tensor product) between this and other | ||
| * See https://en.wikipedia.org/wiki/Kronecker_product | ||
| * @param {Matrix} other | ||
| * @return {Matrix} | ||
| */ | ||
| kroneckerProduct(other) { | ||
| other = Matrix.checkMatrix(other); | ||
| var m = this.rows; | ||
| var n = this.columns; | ||
| var p = other.rows; | ||
| var q = other.columns; | ||
| var result = new Matrix(m * p, n * q); | ||
| for (var i = 0; i < m; i++) { | ||
| for (var j = 0; j < n; j++) { | ||
| for (var k = 0; k < p; k++) { | ||
| for (var l = 0; l < q; l++) { | ||
| result.set(p * i + k, q * j + l, this.get(i, j) * other.get(k, l)); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| return result; | ||
| } | ||
| /** | ||
| * Transposes the matrix and returns a new one containing the result | ||
| * @return {Matrix} | ||
| */ | ||
| transpose() { | ||
| var result = new Matrix(this.columns, this.rows); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| result.set(j, i, this.get(i, j)); | ||
| } | ||
| } | ||
| return result; | ||
| } | ||
| /** | ||
| * Sorts the rows (in place) | ||
| * @param {function} [compareFunction] - usual Array.prototype.sort comparison function | ||
| * @return {Matrix} this | ||
| */ | ||
| sortRows(compareFunction = compareNumbers) { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| this.setRow(i, this.getRow(i).sort(compareFunction)); | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Sorts the columns (in place) | ||
| * @param {function} [compareFunction] - usual Array.prototype.sort comparison function | ||
| * @return {Matrix} this | ||
| */ | ||
| sortColumns(compareFunction = compareNumbers) { | ||
| for (var i = 0; i < this.columns; i++) { | ||
| this.setColumn(i, this.getColumn(i).sort(compareFunction)); | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Returns a subset of the matrix | ||
| * @param {number} startRow - First row index | ||
| * @param {number} endRow - Last row index | ||
| * @param {number} startColumn - First column index | ||
| * @param {number} endColumn - Last column index | ||
| * @return {Matrix} | ||
| */ | ||
| subMatrix(startRow, endRow, startColumn, endColumn) { | ||
| checkRange(this, startRow, endRow, startColumn, endColumn); | ||
| var newMatrix = new Matrix( | ||
| endRow - startRow + 1, | ||
| endColumn - startColumn + 1 | ||
| ); | ||
| for (var i = startRow; i <= endRow; i++) { | ||
| for (var j = startColumn; j <= endColumn; j++) { | ||
| newMatrix.set(i - startRow, j - startColumn, this.get(i, j)); | ||
| } | ||
| } | ||
| return newMatrix; | ||
| } | ||
| /** | ||
| * Returns a subset of the matrix based on an array of row indices | ||
| * @param {Array} indices - Array containing the row indices | ||
| * @param {number} [startColumn = 0] - First column index | ||
| * @param {number} [endColumn = this.columns-1] - Last column index | ||
| * @return {Matrix} | ||
| */ | ||
| subMatrixRow(indices, startColumn, endColumn) { | ||
| if (startColumn === undefined) startColumn = 0; | ||
| if (endColumn === undefined) endColumn = this.columns - 1; | ||
| if ( | ||
| startColumn > endColumn || | ||
| startColumn < 0 || | ||
| startColumn >= this.columns || | ||
| endColumn < 0 || | ||
| endColumn >= this.columns | ||
| ) { | ||
| throw new RangeError('Argument out of range'); | ||
| } | ||
| var newMatrix = new Matrix(indices.length, endColumn - startColumn + 1); | ||
| for (var i = 0; i < indices.length; i++) { | ||
| for (var j = startColumn; j <= endColumn; j++) { | ||
| if (indices[i] < 0 || indices[i] >= this.rows) { | ||
| throw new RangeError(`Row index out of range: ${indices[i]}`); | ||
| } | ||
| newMatrix.set(i, j - startColumn, this.get(indices[i], j)); | ||
| } | ||
| } | ||
| return newMatrix; | ||
| } | ||
| /** | ||
| * Returns a subset of the matrix based on an array of column indices | ||
| * @param {Array} indices - Array containing the column indices | ||
| * @param {number} [startRow = 0] - First row index | ||
| * @param {number} [endRow = this.rows-1] - Last row index | ||
| * @return {Matrix} | ||
| */ | ||
| subMatrixColumn(indices, startRow, endRow) { | ||
| if (startRow === undefined) startRow = 0; | ||
| if (endRow === undefined) endRow = this.rows - 1; | ||
| if ( | ||
| startRow > endRow || | ||
| startRow < 0 || | ||
| startRow >= this.rows || | ||
| endRow < 0 || | ||
| endRow >= this.rows | ||
| ) { | ||
| throw new RangeError('Argument out of range'); | ||
| } | ||
| var newMatrix = new Matrix(endRow - startRow + 1, indices.length); | ||
| for (var i = 0; i < indices.length; i++) { | ||
| for (var j = startRow; j <= endRow; j++) { | ||
| if (indices[i] < 0 || indices[i] >= this.columns) { | ||
| throw new RangeError(`Column index out of range: ${indices[i]}`); | ||
| } | ||
| newMatrix.set(j - startRow, i, this.get(j, indices[i])); | ||
| } | ||
| } | ||
| return newMatrix; | ||
| } | ||
| /** | ||
| * Set a part of the matrix to the given sub-matrix | ||
| * @param {Matrix|Array< Array >} matrix - The source matrix from which to extract values. | ||
| * @param {number} startRow - The index of the first row to set | ||
| * @param {number} startColumn - The index of the first column to set | ||
| * @return {Matrix} | ||
| */ | ||
| setSubMatrix(matrix, startRow, startColumn) { | ||
| matrix = Matrix.checkMatrix(matrix); | ||
| var endRow = startRow + matrix.rows - 1; | ||
| var endColumn = startColumn + matrix.columns - 1; | ||
| checkRange(this, startRow, endRow, startColumn, endColumn); | ||
| for (var i = 0; i < matrix.rows; i++) { | ||
| for (var j = 0; j < matrix.columns; j++) { | ||
| this.set(startRow + i, startColumn + j, matrix.get(i, j)); | ||
| } | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Return a new matrix based on a selection of rows and columns | ||
| * @param {Array<number>} rowIndices - The row indices to select. Order matters and an index can be more than once. | ||
| * @param {Array<number>} columnIndices - The column indices to select. Order matters and an index can be use more than once. | ||
| * @return {Matrix} The new matrix | ||
| */ | ||
| selection(rowIndices, columnIndices) { | ||
| var indices = checkIndices(this, rowIndices, columnIndices); | ||
| var newMatrix = new Matrix(rowIndices.length, columnIndices.length); | ||
| for (var i = 0; i < indices.row.length; i++) { | ||
| var rowIndex = indices.row[i]; | ||
| for (var j = 0; j < indices.column.length; j++) { | ||
| var columnIndex = indices.column[j]; | ||
| newMatrix.set(i, j, this.get(rowIndex, columnIndex)); | ||
| } | ||
| } | ||
| return newMatrix; | ||
| } | ||
| /** | ||
| * Returns the trace of the matrix (sum of the diagonal elements) | ||
| * @return {number} | ||
| */ | ||
| trace() { | ||
| var min = Math.min(this.rows, this.columns); | ||
| var trace = 0; | ||
| for (var i = 0; i < min; i++) { | ||
| trace += this.get(i, i); | ||
| } | ||
| return trace; | ||
| } | ||
| /** | ||
| * Creates an exact and independent copy of the matrix | ||
| * @return {Matrix} | ||
| */ | ||
| clone() { | ||
| var newMatrix = new Matrix(this.rows, this.columns); | ||
| for (var row = 0; row < this.rows; row++) { | ||
| for (var column = 0; column < this.columns; column++) { | ||
| newMatrix.set(row, column, this.get(row, column)); | ||
| } | ||
| } | ||
| return newMatrix; | ||
| } | ||
| sum(by) { | ||
| switch (by) { | ||
| case 'row': | ||
| return sumByRow(this); | ||
| case 'column': | ||
| return sumByColumn(this); | ||
| case undefined: | ||
| return sumAll(this); | ||
| default: | ||
| throw new Error(`invalid option: ${by}`); | ||
| } | ||
| } | ||
| product(by) { | ||
| switch (by) { | ||
| case 'row': | ||
| return productByRow(this); | ||
| case 'column': | ||
| return productByColumn(this); | ||
| case undefined: | ||
| return productAll(this); | ||
| default: | ||
| throw new Error(`invalid option: ${by}`); | ||
| } | ||
| } | ||
| mean(by) { | ||
| const sum = this.sum(by); | ||
| switch (by) { | ||
| case 'row': { | ||
| for (let i = 0; i < this.rows; i++) { | ||
| sum[i] /= this.columns; | ||
| } | ||
| return sum; | ||
| } | ||
| case 'column': { | ||
| for (let i = 0; i < this.columns; i++) { | ||
| sum[i] /= this.rows; | ||
| } | ||
| return sum; | ||
| } | ||
| case undefined: | ||
| return sum / this.size; | ||
| default: | ||
| throw new Error(`invalid option: ${by}`); | ||
| } | ||
| } | ||
| variance(by, options = {}) { | ||
| if (typeof by === 'object') { | ||
| options = by; | ||
| by = undefined; | ||
| } | ||
| if (typeof options !== 'object') { | ||
| throw new TypeError('options must be an object'); | ||
| } | ||
| const { unbiased = true, mean = this.mean(by) } = options; | ||
| if (typeof unbiased !== 'boolean') { | ||
| throw new TypeError('unbiased must be a boolean'); | ||
| } | ||
| switch (by) { | ||
| case 'row': { | ||
| if (!Array.isArray(mean)) { | ||
| throw new TypeError('mean must be an array'); | ||
| } | ||
| return varianceByRow(this, unbiased, mean); | ||
| } | ||
| case 'column': { | ||
| if (!Array.isArray(mean)) { | ||
| throw new TypeError('mean must be an array'); | ||
| } | ||
| return varianceByColumn(this, unbiased, mean); | ||
| } | ||
| case undefined: { | ||
| if (typeof mean !== 'number') { | ||
| throw new TypeError('mean must be a number'); | ||
| } | ||
| return varianceAll(this, unbiased, mean); | ||
| } | ||
| default: | ||
| throw new Error(`invalid option: ${by}`); | ||
| } | ||
| } | ||
| standardDeviation(by, options) { | ||
| if (typeof by === 'object') { | ||
| options = by; | ||
| by = undefined; | ||
| } | ||
| const variance = this.variance(by, options); | ||
| if (by === undefined) { | ||
| return Math.sqrt(variance); | ||
| } else { | ||
| for (var i = 0; i < variance.length; i++) { | ||
| variance[i] = Math.sqrt(variance[i]); | ||
| } | ||
| return variance; | ||
| } | ||
| } | ||
| } | ||
| AbstractMatrix.prototype.klass = 'Matrix'; | ||
| if (typeof Symbol !== 'undefined') { | ||
| AbstractMatrix.prototype[ | ||
| Symbol.for('nodejs.util.inspect.custom') | ||
| ] = inspectMatrix; | ||
| } | ||
| function compareNumbers(a, b) { | ||
| return a - b; | ||
| } | ||
| // Synonyms | ||
| AbstractMatrix.random = AbstractMatrix.rand; | ||
| AbstractMatrix.randomInt = AbstractMatrix.randInt; | ||
| AbstractMatrix.diagonal = AbstractMatrix.diag; | ||
| AbstractMatrix.prototype.diagonal = AbstractMatrix.prototype.diag; | ||
| AbstractMatrix.identity = AbstractMatrix.eye; | ||
| AbstractMatrix.prototype.negate = AbstractMatrix.prototype.neg; | ||
| AbstractMatrix.prototype.tensorProduct = | ||
| AbstractMatrix.prototype.kroneckerProduct; | ||
| export default class Matrix extends AbstractMatrix { | ||
@@ -133,1 +1818,3 @@ constructor(nRows, nColumns) { | ||
| } | ||
| installMathOperations(AbstractMatrix, Matrix); |
@@ -1,2 +0,2 @@ | ||
| import SvDecomposition from './dc/svd'; | ||
| import SVD from './dc/svd'; | ||
| import Matrix from './matrix'; | ||
@@ -11,3 +11,3 @@ | ||
| matrix = Matrix.checkMatrix(matrix); | ||
| var svdSolution = new SvDecomposition(matrix, { autoTranspose: true }); | ||
| var svdSolution = new SVD(matrix, { autoTranspose: true }); | ||
@@ -26,5 +26,3 @@ var U = svdSolution.leftSingularVectors; | ||
| // convert list to diagonal | ||
| s = matrix.constructor[Symbol.species].diag(s); | ||
| return V.mmul(s.mmul(U.transpose())); | ||
| return V.mmul(Matrix.diag(s).mmul(U.transpose())); | ||
| } |
+68
-0
@@ -62,1 +62,69 @@ import { newArray } from './util'; | ||
| } | ||
| export function varianceByRow(matrix, unbiased, mean) { | ||
| const rows = matrix.rows; | ||
| const cols = matrix.columns; | ||
| const variance = []; | ||
| for (var i = 0; i < rows; i++) { | ||
| var sum1 = 0; | ||
| var sum2 = 0; | ||
| var x = 0; | ||
| for (var j = 0; j < cols; j++) { | ||
| x = matrix.get(j, i) - mean[i]; | ||
| sum1 += x; | ||
| sum2 += x * x; | ||
| } | ||
| if (unbiased) { | ||
| variance.push((sum2 - (sum1 * sum1) / cols) / (cols - 1)); | ||
| } else { | ||
| variance.push((sum2 - (sum1 * sum1) / cols) / cols); | ||
| } | ||
| } | ||
| return variance; | ||
| } | ||
| export function varianceByColumn(matrix, unbiased, mean) { | ||
| const rows = matrix.rows; | ||
| const cols = matrix.columns; | ||
| const variance = []; | ||
| for (var j = 0; j < cols; j++) { | ||
| var sum1 = 0; | ||
| var sum2 = 0; | ||
| var x = 0; | ||
| for (var i = 0; i < rows; i++) { | ||
| x = matrix.get(i, j) - mean[j]; | ||
| sum1 += x; | ||
| sum2 += x * x; | ||
| } | ||
| if (unbiased) { | ||
| variance.push((sum2 - (sum1 * sum1) / rows) / (rows - 1)); | ||
| } else { | ||
| variance.push((sum2 - (sum1 * sum1) / rows) / rows); | ||
| } | ||
| } | ||
| return variance; | ||
| } | ||
| export function varianceAll(matrix, unbiased, mean) { | ||
| const rows = matrix.rows; | ||
| const cols = matrix.columns; | ||
| const size = rows * cols; | ||
| var sum1 = 0; | ||
| var sum2 = 0; | ||
| var x = 0; | ||
| for (var i = 0; i < rows; i++) { | ||
| for (var j = 0; j < cols; j++) { | ||
| x = matrix.get(i, j) - mean; | ||
| sum1 += x; | ||
| sum2 += x * x; | ||
| } | ||
| } | ||
| if (unbiased) { | ||
| return (sum2 - (sum1 * sum1) / size) / (size - 1); | ||
| } else { | ||
| return (sum2 - (sum1 * sum1) / size) / size; | ||
| } | ||
| } |
+0
-0
@@ -0,0 +0,0 @@ /** |
@@ -1,3 +0,2 @@ | ||
| import AbstractMatrix from '../abstractMatrix'; | ||
| import Matrix from '../matrix'; | ||
| import { AbstractMatrix } from '../matrix'; | ||
@@ -11,6 +10,2 @@ export default class BaseView extends AbstractMatrix { | ||
| } | ||
| static get [Symbol.species]() { | ||
| return Matrix; | ||
| } | ||
| } |
@@ -0,0 +0,0 @@ import { checkColumnIndices } from '../util'; |
@@ -0,0 +0,0 @@ import BaseView from './base'; |
@@ -0,0 +0,0 @@ import BaseView from './base'; |
@@ -1,9 +0,9 @@ | ||
| export { default as MatrixTransposeView } from './transpose'; | ||
| export { default as MatrixColumnView } from './column'; | ||
| export { default as MatrixColumnSelectionView } from './columnSelection'; | ||
| export { default as MatrixFlipColumnView } from './flipColumn'; | ||
| export { default as MatrixFlipRowView } from './flipRow'; | ||
| export { default as MatrixRowView } from './row'; | ||
| export { default as MatrixRowSelectionView } from './rowSelection'; | ||
| export { default as MatrixSelectionView } from './selection'; | ||
| export { default as MatrixSubView } from './sub'; | ||
| export { default as MatrixSelectionView } from './selection'; | ||
| export { default as MatrixRowSelectionView } from './rowSelection'; | ||
| export { default as MatrixColumnSelectionView } from './columnSelection'; | ||
| export { default as MatrixColumnView } from './column'; | ||
| export { default as MatrixFlipRowView } from './flipRow'; | ||
| export { default as MatrixFlipColumnView } from './flipColumn'; | ||
| export { default as MatrixTransposeView } from './transpose'; |
@@ -0,0 +0,0 @@ import { checkRowIndices } from '../util'; |
@@ -0,0 +0,0 @@ import { checkIndices } from '../util'; |
+0
-0
@@ -0,0 +0,0 @@ import { checkRange } from '../util'; |
@@ -0,0 +0,0 @@ import BaseView from './base'; |
+0
-0
@@ -0,0 +0,0 @@ import WrapperMatrix1D from './WrapperMatrix1D'; |
@@ -1,3 +0,2 @@ | ||
| import AbstractMatrix from '../abstractMatrix'; | ||
| import Matrix from '../matrix'; | ||
| import { AbstractMatrix } from '../matrix'; | ||
@@ -37,6 +36,2 @@ export default class WrapperMatrix1D extends AbstractMatrix { | ||
| } | ||
| static get [Symbol.species]() { | ||
| return Matrix; | ||
| } | ||
| } |
@@ -1,3 +0,2 @@ | ||
| import AbstractMatrix from '../abstractMatrix'; | ||
| import Matrix from '../matrix'; | ||
| import { AbstractMatrix } from '../matrix'; | ||
@@ -24,6 +23,2 @@ export default class WrapperMatrix2D extends AbstractMatrix { | ||
| } | ||
| static get [Symbol.species]() { | ||
| return Matrix; | ||
| } | ||
| } |
| import rescale from 'ml-array-rescale'; | ||
| import { | ||
| checkRowVector, | ||
| checkRowIndex, | ||
| checkColumnIndex, | ||
| checkColumnVector, | ||
| checkRange, | ||
| checkIndices | ||
| } from './util'; | ||
| import { | ||
| sumByRow, | ||
| sumByColumn, | ||
| sumAll, | ||
| productByRow, | ||
| productByColumn, | ||
| productAll | ||
| } from './stat'; | ||
| export default class AbstractMatrix { | ||
| static get [Symbol.species]() { | ||
| return this; | ||
| } | ||
| /** | ||
| * Constructs a Matrix with the chosen dimensions from a 1D array | ||
| * @param {number} newRows - Number of rows | ||
| * @param {number} newColumns - Number of columns | ||
| * @param {Array} newData - A 1D array containing data for the matrix | ||
| * @return {Matrix} - The new matrix | ||
| */ | ||
| static from1DArray(newRows, newColumns, newData) { | ||
| var length = newRows * newColumns; | ||
| if (length !== newData.length) { | ||
| throw new RangeError('Data length does not match given dimensions'); | ||
| } | ||
| var newMatrix = new this(newRows, newColumns); | ||
| for (var row = 0; row < newRows; row++) { | ||
| for (var column = 0; column < newColumns; column++) { | ||
| newMatrix.set(row, column, newData[row * newColumns + column]); | ||
| } | ||
| } | ||
| return newMatrix; | ||
| } | ||
| /** | ||
| * Creates a row vector, a matrix with only one row. | ||
| * @param {Array} newData - A 1D array containing data for the vector | ||
| * @return {Matrix} - The new matrix | ||
| */ | ||
| static rowVector(newData) { | ||
| var vector = new this(1, newData.length); | ||
| for (var i = 0; i < newData.length; i++) { | ||
| vector.set(0, i, newData[i]); | ||
| } | ||
| return vector; | ||
| } | ||
| /** | ||
| * Creates a column vector, a matrix with only one column. | ||
| * @param {Array} newData - A 1D array containing data for the vector | ||
| * @return {Matrix} - The new matrix | ||
| */ | ||
| static columnVector(newData) { | ||
| var vector = new this(newData.length, 1); | ||
| for (var i = 0; i < newData.length; i++) { | ||
| vector.set(i, 0, newData[i]); | ||
| } | ||
| return vector; | ||
| } | ||
| /** | ||
| * Creates a matrix with the given dimensions. Values will be set to zero. | ||
| * @param {number} rows - Number of rows | ||
| * @param {number} columns - Number of columns | ||
| * @return {Matrix} - The new matrix | ||
| */ | ||
| static zeros(rows, columns) { | ||
| return new this(rows, columns); | ||
| } | ||
| /** | ||
| * Creates a matrix with the given dimensions. Values will be set to one. | ||
| * @param {number} rows - Number of rows | ||
| * @param {number} columns - Number of columns | ||
| * @return {Matrix} - The new matrix | ||
| */ | ||
| static ones(rows, columns) { | ||
| return new this(rows, columns).fill(1); | ||
| } | ||
| /** | ||
| * Creates a matrix with the given dimensions. Values will be randomly set. | ||
| * @param {number} rows - Number of rows | ||
| * @param {number} columns - Number of columns | ||
| * @param {function} [rng=Math.random] - Random number generator | ||
| * @return {Matrix} The new matrix | ||
| */ | ||
| static rand(rows, columns, rng) { | ||
| if (rng === undefined) rng = Math.random; | ||
| var matrix = new this(rows, columns); | ||
| for (var i = 0; i < rows; i++) { | ||
| for (var j = 0; j < columns; j++) { | ||
| matrix.set(i, j, rng()); | ||
| } | ||
| } | ||
| return matrix; | ||
| } | ||
| /** | ||
| * Creates a matrix with the given dimensions. Values will be random integers. | ||
| * @param {number} rows - Number of rows | ||
| * @param {number} columns - Number of columns | ||
| * @param {number} [maxValue=1000] - Maximum value | ||
| * @param {function} [rng=Math.random] - Random number generator | ||
| * @return {Matrix} The new matrix | ||
| */ | ||
| static randInt(rows, columns, maxValue, rng) { | ||
| if (maxValue === undefined) maxValue = 1000; | ||
| if (rng === undefined) rng = Math.random; | ||
| var matrix = new this(rows, columns); | ||
| for (var i = 0; i < rows; i++) { | ||
| for (var j = 0; j < columns; j++) { | ||
| var value = Math.floor(rng() * maxValue); | ||
| matrix.set(i, j, value); | ||
| } | ||
| } | ||
| return matrix; | ||
| } | ||
| /** | ||
| * Creates an identity matrix with the given dimension. Values of the diagonal will be 1 and others will be 0. | ||
| * @param {number} rows - Number of rows | ||
| * @param {number} [columns=rows] - Number of columns | ||
| * @param {number} [value=1] - Value to fill the diagonal with | ||
| * @return {Matrix} - The new identity matrix | ||
| */ | ||
| static eye(rows, columns, value) { | ||
| if (columns === undefined) columns = rows; | ||
| if (value === undefined) value = 1; | ||
| var min = Math.min(rows, columns); | ||
| var matrix = this.zeros(rows, columns); | ||
| for (var i = 0; i < min; i++) { | ||
| matrix.set(i, i, value); | ||
| } | ||
| return matrix; | ||
| } | ||
| /** | ||
| * Creates a diagonal matrix based on the given array. | ||
| * @param {Array} data - Array containing the data for the diagonal | ||
| * @param {number} [rows] - Number of rows (Default: data.length) | ||
| * @param {number} [columns] - Number of columns (Default: rows) | ||
| * @return {Matrix} - The new diagonal matrix | ||
| */ | ||
| static diag(data, rows, columns) { | ||
| var l = data.length; | ||
| if (rows === undefined) rows = l; | ||
| if (columns === undefined) columns = rows; | ||
| var min = Math.min(l, rows, columns); | ||
| var matrix = this.zeros(rows, columns); | ||
| for (var i = 0; i < min; i++) { | ||
| matrix.set(i, i, data[i]); | ||
| } | ||
| return matrix; | ||
| } | ||
| /** | ||
| * Returns a matrix whose elements are the minimum between matrix1 and matrix2 | ||
| * @param {Matrix} matrix1 | ||
| * @param {Matrix} matrix2 | ||
| * @return {Matrix} | ||
| */ | ||
| static min(matrix1, matrix2) { | ||
| matrix1 = this.checkMatrix(matrix1); | ||
| matrix2 = this.checkMatrix(matrix2); | ||
| var rows = matrix1.rows; | ||
| var columns = matrix1.columns; | ||
| var result = new this(rows, columns); | ||
| for (var i = 0; i < rows; i++) { | ||
| for (var j = 0; j < columns; j++) { | ||
| result.set(i, j, Math.min(matrix1.get(i, j), matrix2.get(i, j))); | ||
| } | ||
| } | ||
| return result; | ||
| } | ||
| /** | ||
| * Returns a matrix whose elements are the maximum between matrix1 and matrix2 | ||
| * @param {Matrix} matrix1 | ||
| * @param {Matrix} matrix2 | ||
| * @return {Matrix} | ||
| */ | ||
| static max(matrix1, matrix2) { | ||
| matrix1 = this.checkMatrix(matrix1); | ||
| matrix2 = this.checkMatrix(matrix2); | ||
| var rows = matrix1.rows; | ||
| var columns = matrix1.columns; | ||
| var result = new this(rows, columns); | ||
| for (var i = 0; i < rows; i++) { | ||
| for (var j = 0; j < columns; j++) { | ||
| result.set(i, j, Math.max(matrix1.get(i, j), matrix2.get(i, j))); | ||
| } | ||
| } | ||
| return result; | ||
| } | ||
| /** | ||
| * Check that the provided value is a Matrix and tries to instantiate one if not | ||
| * @param {*} value - The value to check | ||
| * @return {Matrix} | ||
| */ | ||
| static checkMatrix(value) { | ||
| return AbstractMatrix.isMatrix(value) ? value : new this(value); | ||
| } | ||
| /** | ||
| * Returns true if the argument is a Matrix, false otherwise | ||
| * @param {*} value - The value to check | ||
| * @return {boolean} | ||
| */ | ||
| static isMatrix(value) { | ||
| return value != null && value.klass === 'Matrix'; | ||
| } | ||
| /** | ||
| * @prop {number} size - The number of elements in the matrix. | ||
| */ | ||
| get size() { | ||
| return this.rows * this.columns; | ||
| } | ||
| /** | ||
| * Applies a callback for each element of the matrix. The function is called in the matrix (this) context. | ||
| * @param {function} callback - Function that will be called with two parameters : i (row) and j (column) | ||
| * @return {Matrix} this | ||
| */ | ||
| apply(callback) { | ||
| if (typeof callback !== 'function') { | ||
| throw new TypeError('callback must be a function'); | ||
| } | ||
| var ii = this.rows; | ||
| var jj = this.columns; | ||
| for (var i = 0; i < ii; i++) { | ||
| for (var j = 0; j < jj; j++) { | ||
| callback.call(this, i, j); | ||
| } | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Returns a new 1D array filled row by row with the matrix values | ||
| * @return {Array} | ||
| */ | ||
| to1DArray() { | ||
| var array = new Array(this.size); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| array[i * this.columns + j] = this.get(i, j); | ||
| } | ||
| } | ||
| return array; | ||
| } | ||
| /** | ||
| * Returns a 2D array containing a copy of the data | ||
| * @return {Array} | ||
| */ | ||
| to2DArray() { | ||
| var copy = new Array(this.rows); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| copy[i] = new Array(this.columns); | ||
| for (var j = 0; j < this.columns; j++) { | ||
| copy[i][j] = this.get(i, j); | ||
| } | ||
| } | ||
| return copy; | ||
| } | ||
| toJSON() { | ||
| return this.to2DArray(); | ||
| } | ||
| /** | ||
| * @return {boolean} true if the matrix has one row | ||
| */ | ||
| isRowVector() { | ||
| return this.rows === 1; | ||
| } | ||
| /** | ||
| * @return {boolean} true if the matrix has one column | ||
| */ | ||
| isColumnVector() { | ||
| return this.columns === 1; | ||
| } | ||
| /** | ||
| * @return {boolean} true if the matrix has one row or one column | ||
| */ | ||
| isVector() { | ||
| return this.rows === 1 || this.columns === 1; | ||
| } | ||
| /** | ||
| * @return {boolean} true if the matrix has the same number of rows and columns | ||
| */ | ||
| isSquare() { | ||
| return this.rows === this.columns; | ||
| } | ||
| /** | ||
| * @return {boolean} true if the matrix is square and has the same values on both sides of the diagonal | ||
| */ | ||
| isSymmetric() { | ||
| if (this.isSquare()) { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j <= i; j++) { | ||
| if (this.get(i, j) !== this.get(j, i)) { | ||
| return false; | ||
| } | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
| return false; | ||
| } | ||
| /** | ||
| * @return true if the matrix is in echelon form | ||
| */ | ||
| isEchelonForm() { | ||
| let i = 0; | ||
| let j = 0; | ||
| let previousColumn = -1; | ||
| let isEchelonForm = true; | ||
| let checked = false; | ||
| while (i < this.rows && isEchelonForm) { | ||
| j = 0; | ||
| checked = false; | ||
| while (j < this.columns && checked === false) { | ||
| if (this.get(i, j) === 0) { | ||
| j++; | ||
| } else if (this.get(i, j) === 1 && j > previousColumn) { | ||
| checked = true; | ||
| previousColumn = j; | ||
| } else { | ||
| isEchelonForm = false; | ||
| checked = true; | ||
| } | ||
| } | ||
| i++; | ||
| } | ||
| return isEchelonForm; | ||
| } | ||
| /** | ||
| * @return true if the matrix is in reduced echelon form | ||
| */ | ||
| isReducedEchelonForm() { | ||
| let i = 0; | ||
| let j = 0; | ||
| let previousColumn = -1; | ||
| let isReducedEchelonForm = true; | ||
| let checked = false; | ||
| while (i < this.rows && isReducedEchelonForm) { | ||
| j = 0; | ||
| checked = false; | ||
| while (j < this.columns && checked === false) { | ||
| if (this.get(i, j) === 0) { | ||
| j++; | ||
| } else if (this.get(i, j) === 1 && j > previousColumn) { | ||
| checked = true; | ||
| previousColumn = j; | ||
| } else { | ||
| isReducedEchelonForm = false; | ||
| checked = true; | ||
| } | ||
| } | ||
| for (let k = j + 1; k < this.rows; k++) { | ||
| if (this.get(i, k) !== 0) { | ||
| isReducedEchelonForm = false; | ||
| } | ||
| } | ||
| i++; | ||
| } | ||
| return isReducedEchelonForm; | ||
| } | ||
| /** | ||
| * Sets a given element of the matrix. mat.set(3,4,1) is equivalent to mat[3][4]=1 | ||
| * @abstract | ||
| * @param {number} rowIndex - Index of the row | ||
| * @param {number} columnIndex - Index of the column | ||
| * @param {number} value - The new value for the element | ||
| * @return {Matrix} this | ||
| */ | ||
| // eslint-disable-next-line no-unused-vars | ||
| set(rowIndex, columnIndex, value) { | ||
| throw new Error('set method is unimplemented'); | ||
| } | ||
| /** | ||
| * Returns the given element of the matrix. mat.get(3,4) is equivalent to matrix[3][4] | ||
| * @abstract | ||
| * @param {number} rowIndex - Index of the row | ||
| * @param {number} columnIndex - Index of the column | ||
| * @return {number} | ||
| */ | ||
| // eslint-disable-next-line no-unused-vars | ||
| get(rowIndex, columnIndex) { | ||
| throw new Error('get method is unimplemented'); | ||
| } | ||
| /** | ||
| * Creates a new matrix that is a repetition of the current matrix. New matrix has rowRep times the number of | ||
| * rows of the matrix, and colRep times the number of columns of the matrix | ||
| * @param {number} rowRep - Number of times the rows should be repeated | ||
| * @param {number} colRep - Number of times the columns should be re | ||
| * @return {Matrix} | ||
| * @example | ||
| * var matrix = new Matrix([[1,2]]); | ||
| * matrix.repeat(2); // [[1,2],[1,2]] | ||
| */ | ||
| repeat(rowRep, colRep) { | ||
| rowRep = rowRep || 1; | ||
| colRep = colRep || 1; | ||
| var matrix = new this.constructor[Symbol.species]( | ||
| this.rows * rowRep, | ||
| this.columns * colRep | ||
| ); | ||
| for (var i = 0; i < rowRep; i++) { | ||
| for (var j = 0; j < colRep; j++) { | ||
| matrix.setSubMatrix(this, this.rows * i, this.columns * j); | ||
| } | ||
| } | ||
| return matrix; | ||
| } | ||
| /** | ||
| * Fills the matrix with a given value. All elements will be set to this value. | ||
| * @param {number} value - New value | ||
| * @return {Matrix} this | ||
| */ | ||
| fill(value) { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, value); | ||
| } | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Negates the matrix. All elements will be multiplied by (-1) | ||
| * @return {Matrix} this | ||
| */ | ||
| neg() { | ||
| return this.mulS(-1); | ||
| } | ||
| /** | ||
| * Returns a new array from the given row index | ||
| * @param {number} index - Row index | ||
| * @return {Array} | ||
| */ | ||
| getRow(index) { | ||
| checkRowIndex(this, index); | ||
| var row = new Array(this.columns); | ||
| for (var i = 0; i < this.columns; i++) { | ||
| row[i] = this.get(index, i); | ||
| } | ||
| return row; | ||
| } | ||
| /** | ||
| * Returns a new row vector from the given row index | ||
| * @param {number} index - Row index | ||
| * @return {Matrix} | ||
| */ | ||
| getRowVector(index) { | ||
| return this.constructor.rowVector(this.getRow(index)); | ||
| } | ||
| /** | ||
| * Sets a row at the given index | ||
| * @param {number} index - Row index | ||
| * @param {Array|Matrix} array - Array or vector | ||
| * @return {Matrix} this | ||
| */ | ||
| setRow(index, array) { | ||
| checkRowIndex(this, index); | ||
| array = checkRowVector(this, array); | ||
| for (var i = 0; i < this.columns; i++) { | ||
| this.set(index, i, array[i]); | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Swaps two rows | ||
| * @param {number} row1 - First row index | ||
| * @param {number} row2 - Second row index | ||
| * @return {Matrix} this | ||
| */ | ||
| swapRows(row1, row2) { | ||
| checkRowIndex(this, row1); | ||
| checkRowIndex(this, row2); | ||
| for (var i = 0; i < this.columns; i++) { | ||
| var temp = this.get(row1, i); | ||
| this.set(row1, i, this.get(row2, i)); | ||
| this.set(row2, i, temp); | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Returns a new array from the given column index | ||
| * @param {number} index - Column index | ||
| * @return {Array} | ||
| */ | ||
| getColumn(index) { | ||
| checkColumnIndex(this, index); | ||
| var column = new Array(this.rows); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| column[i] = this.get(i, index); | ||
| } | ||
| return column; | ||
| } | ||
| /** | ||
| * Returns a new column vector from the given column index | ||
| * @param {number} index - Column index | ||
| * @return {Matrix} | ||
| */ | ||
| getColumnVector(index) { | ||
| return this.constructor.columnVector(this.getColumn(index)); | ||
| } | ||
| /** | ||
| * Sets a column at the given index | ||
| * @param {number} index - Column index | ||
| * @param {Array|Matrix} array - Array or vector | ||
| * @return {Matrix} this | ||
| */ | ||
| setColumn(index, array) { | ||
| checkColumnIndex(this, index); | ||
| array = checkColumnVector(this, array); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| this.set(i, index, array[i]); | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Swaps two columns | ||
| * @param {number} column1 - First column index | ||
| * @param {number} column2 - Second column index | ||
| * @return {Matrix} this | ||
| */ | ||
| swapColumns(column1, column2) { | ||
| checkColumnIndex(this, column1); | ||
| checkColumnIndex(this, column2); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| var temp = this.get(i, column1); | ||
| this.set(i, column1, this.get(i, column2)); | ||
| this.set(i, column2, temp); | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Adds the values of a vector to each row | ||
| * @param {Array|Matrix} vector - Array or vector | ||
| * @return {Matrix} this | ||
| */ | ||
| addRowVector(vector) { | ||
| vector = checkRowVector(this, vector); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) + vector[j]); | ||
| } | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Subtracts the values of a vector from each row | ||
| * @param {Array|Matrix} vector - Array or vector | ||
| * @return {Matrix} this | ||
| */ | ||
| subRowVector(vector) { | ||
| vector = checkRowVector(this, vector); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) - vector[j]); | ||
| } | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Multiplies the values of a vector with each row | ||
| * @param {Array|Matrix} vector - Array or vector | ||
| * @return {Matrix} this | ||
| */ | ||
| mulRowVector(vector) { | ||
| vector = checkRowVector(this, vector); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) * vector[j]); | ||
| } | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Divides the values of each row by those of a vector | ||
| * @param {Array|Matrix} vector - Array or vector | ||
| * @return {Matrix} this | ||
| */ | ||
| divRowVector(vector) { | ||
| vector = checkRowVector(this, vector); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) / vector[j]); | ||
| } | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Adds the values of a vector to each column | ||
| * @param {Array|Matrix} vector - Array or vector | ||
| * @return {Matrix} this | ||
| */ | ||
| addColumnVector(vector) { | ||
| vector = checkColumnVector(this, vector); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) + vector[i]); | ||
| } | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Subtracts the values of a vector from each column | ||
| * @param {Array|Matrix} vector - Array or vector | ||
| * @return {Matrix} this | ||
| */ | ||
| subColumnVector(vector) { | ||
| vector = checkColumnVector(this, vector); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) - vector[i]); | ||
| } | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Multiplies the values of a vector with each column | ||
| * @param {Array|Matrix} vector - Array or vector | ||
| * @return {Matrix} this | ||
| */ | ||
| mulColumnVector(vector) { | ||
| vector = checkColumnVector(this, vector); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) * vector[i]); | ||
| } | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Divides the values of each column by those of a vector | ||
| * @param {Array|Matrix} vector - Array or vector | ||
| * @return {Matrix} this | ||
| */ | ||
| divColumnVector(vector) { | ||
| vector = checkColumnVector(this, vector); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) / vector[i]); | ||
| } | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Multiplies the values of a row with a scalar | ||
| * @param {number} index - Row index | ||
| * @param {number} value | ||
| * @return {Matrix} this | ||
| */ | ||
| mulRow(index, value) { | ||
| checkRowIndex(this, index); | ||
| for (var i = 0; i < this.columns; i++) { | ||
| this.set(index, i, this.get(index, i) * value); | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Multiplies the values of a column with a scalar | ||
| * @param {number} index - Column index | ||
| * @param {number} value | ||
| * @return {Matrix} this | ||
| */ | ||
| mulColumn(index, value) { | ||
| checkColumnIndex(this, index); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| this.set(i, index, this.get(i, index) * value); | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Returns the maximum value of the matrix | ||
| * @return {number} | ||
| */ | ||
| max() { | ||
| var v = this.get(0, 0); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| if (this.get(i, j) > v) { | ||
| v = this.get(i, j); | ||
| } | ||
| } | ||
| } | ||
| return v; | ||
| } | ||
| /** | ||
| * Returns the index of the maximum value | ||
| * @return {Array} | ||
| */ | ||
| maxIndex() { | ||
| var v = this.get(0, 0); | ||
| var idx = [0, 0]; | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| if (this.get(i, j) > v) { | ||
| v = this.get(i, j); | ||
| idx[0] = i; | ||
| idx[1] = j; | ||
| } | ||
| } | ||
| } | ||
| return idx; | ||
| } | ||
| /** | ||
| * Returns the minimum value of the matrix | ||
| * @return {number} | ||
| */ | ||
| min() { | ||
| var v = this.get(0, 0); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| if (this.get(i, j) < v) { | ||
| v = this.get(i, j); | ||
| } | ||
| } | ||
| } | ||
| return v; | ||
| } | ||
| /** | ||
| * Returns the index of the minimum value | ||
| * @return {Array} | ||
| */ | ||
| minIndex() { | ||
| var v = this.get(0, 0); | ||
| var idx = [0, 0]; | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| if (this.get(i, j) < v) { | ||
| v = this.get(i, j); | ||
| idx[0] = i; | ||
| idx[1] = j; | ||
| } | ||
| } | ||
| } | ||
| return idx; | ||
| } | ||
| /** | ||
| * Returns the maximum value of one row | ||
| * @param {number} row - Row index | ||
| * @return {number} | ||
| */ | ||
| maxRow(row) { | ||
| checkRowIndex(this, row); | ||
| var v = this.get(row, 0); | ||
| for (var i = 1; i < this.columns; i++) { | ||
| if (this.get(row, i) > v) { | ||
| v = this.get(row, i); | ||
| } | ||
| } | ||
| return v; | ||
| } | ||
| /** | ||
| * Returns the index of the maximum value of one row | ||
| * @param {number} row - Row index | ||
| * @return {Array} | ||
| */ | ||
| maxRowIndex(row) { | ||
| checkRowIndex(this, row); | ||
| var v = this.get(row, 0); | ||
| var idx = [row, 0]; | ||
| for (var i = 1; i < this.columns; i++) { | ||
| if (this.get(row, i) > v) { | ||
| v = this.get(row, i); | ||
| idx[1] = i; | ||
| } | ||
| } | ||
| return idx; | ||
| } | ||
| /** | ||
| * Returns the minimum value of one row | ||
| * @param {number} row - Row index | ||
| * @return {number} | ||
| */ | ||
| minRow(row) { | ||
| checkRowIndex(this, row); | ||
| var v = this.get(row, 0); | ||
| for (var i = 1; i < this.columns; i++) { | ||
| if (this.get(row, i) < v) { | ||
| v = this.get(row, i); | ||
| } | ||
| } | ||
| return v; | ||
| } | ||
| /** | ||
| * Returns the index of the maximum value of one row | ||
| * @param {number} row - Row index | ||
| * @return {Array} | ||
| */ | ||
| minRowIndex(row) { | ||
| checkRowIndex(this, row); | ||
| var v = this.get(row, 0); | ||
| var idx = [row, 0]; | ||
| for (var i = 1; i < this.columns; i++) { | ||
| if (this.get(row, i) < v) { | ||
| v = this.get(row, i); | ||
| idx[1] = i; | ||
| } | ||
| } | ||
| return idx; | ||
| } | ||
| /** | ||
| * Returns the maximum value of one column | ||
| * @param {number} column - Column index | ||
| * @return {number} | ||
| */ | ||
| maxColumn(column) { | ||
| checkColumnIndex(this, column); | ||
| var v = this.get(0, column); | ||
| for (var i = 1; i < this.rows; i++) { | ||
| if (this.get(i, column) > v) { | ||
| v = this.get(i, column); | ||
| } | ||
| } | ||
| return v; | ||
| } | ||
| /** | ||
| * Returns the index of the maximum value of one column | ||
| * @param {number} column - Column index | ||
| * @return {Array} | ||
| */ | ||
| maxColumnIndex(column) { | ||
| checkColumnIndex(this, column); | ||
| var v = this.get(0, column); | ||
| var idx = [0, column]; | ||
| for (var i = 1; i < this.rows; i++) { | ||
| if (this.get(i, column) > v) { | ||
| v = this.get(i, column); | ||
| idx[0] = i; | ||
| } | ||
| } | ||
| return idx; | ||
| } | ||
| /** | ||
| * Returns the minimum value of one column | ||
| * @param {number} column - Column index | ||
| * @return {number} | ||
| */ | ||
| minColumn(column) { | ||
| checkColumnIndex(this, column); | ||
| var v = this.get(0, column); | ||
| for (var i = 1; i < this.rows; i++) { | ||
| if (this.get(i, column) < v) { | ||
| v = this.get(i, column); | ||
| } | ||
| } | ||
| return v; | ||
| } | ||
| /** | ||
| * Returns the index of the minimum value of one column | ||
| * @param {number} column - Column index | ||
| * @return {Array} | ||
| */ | ||
| minColumnIndex(column) { | ||
| checkColumnIndex(this, column); | ||
| var v = this.get(0, column); | ||
| var idx = [0, column]; | ||
| for (var i = 1; i < this.rows; i++) { | ||
| if (this.get(i, column) < v) { | ||
| v = this.get(i, column); | ||
| idx[0] = i; | ||
| } | ||
| } | ||
| return idx; | ||
| } | ||
| /** | ||
| * Returns an array containing the diagonal values of the matrix | ||
| * @return {Array} | ||
| */ | ||
| diag() { | ||
| var min = Math.min(this.rows, this.columns); | ||
| var diag = new Array(min); | ||
| for (var i = 0; i < min; i++) { | ||
| diag[i] = this.get(i, i); | ||
| } | ||
| return diag; | ||
| } | ||
| sum(by) { | ||
| switch (by) { | ||
| case 'row': | ||
| return sumByRow(this); | ||
| case 'column': | ||
| return sumByColumn(this); | ||
| case undefined: | ||
| return sumAll(this); | ||
| default: | ||
| throw new Error(`invalid option: ${by}`); | ||
| } | ||
| } | ||
| product(by) { | ||
| switch (by) { | ||
| case 'row': | ||
| return productByRow(this); | ||
| case 'column': | ||
| return productByColumn(this); | ||
| case undefined: | ||
| return productAll(this); | ||
| default: | ||
| throw new Error(`invalid option: ${by}`); | ||
| } | ||
| } | ||
| mean(by) { | ||
| const sum = this.sum(by); | ||
| switch (by) { | ||
| case 'row': { | ||
| for (let i = 0; i < this.rows; i++) { | ||
| sum[i] /= this.columns; | ||
| } | ||
| return sum; | ||
| } | ||
| case 'column': { | ||
| for (let i = 0; i < this.columns; i++) { | ||
| sum[i] /= this.rows; | ||
| } | ||
| return sum; | ||
| } | ||
| case undefined: | ||
| return sum / this.size; | ||
| default: | ||
| throw new Error(`invalid option: ${by}`); | ||
| } | ||
| } | ||
| /** | ||
| * Returns the product of all elements of the matrix | ||
| * @return {number} | ||
| */ | ||
| prod() { | ||
| var prod = 1; | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| prod *= this.get(i, j); | ||
| } | ||
| } | ||
| return prod; | ||
| } | ||
| /** | ||
| * Returns the norm of a matrix. | ||
| * @param {string} type - "frobenius" (default) or "max" return resp. the Frobenius norm and the max norm. | ||
| * @return {number} | ||
| */ | ||
| norm(type = 'frobenius') { | ||
| var result = 0; | ||
| if (type === 'max') { | ||
| return this.max(); | ||
| } else if (type === 'frobenius') { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| result = result + this.get(i, j) * this.get(i, j); | ||
| } | ||
| } | ||
| return Math.sqrt(result); | ||
| } else { | ||
| throw new RangeError(`unknown norm type: ${type}`); | ||
| } | ||
| } | ||
| /** | ||
| * Computes the cumulative sum of the matrix elements (in place, row by row) | ||
| * @return {Matrix} this | ||
| */ | ||
| cumulativeSum() { | ||
| var sum = 0; | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| sum += this.get(i, j); | ||
| this.set(i, j, sum); | ||
| } | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Computes the dot (scalar) product between the matrix and another | ||
| * @param {Matrix} vector2 vector | ||
| * @return {number} | ||
| */ | ||
| dot(vector2) { | ||
| if (AbstractMatrix.isMatrix(vector2)) vector2 = vector2.to1DArray(); | ||
| var vector1 = this.to1DArray(); | ||
| if (vector1.length !== vector2.length) { | ||
| throw new RangeError('vectors do not have the same size'); | ||
| } | ||
| var dot = 0; | ||
| for (var i = 0; i < vector1.length; i++) { | ||
| dot += vector1[i] * vector2[i]; | ||
| } | ||
| return dot; | ||
| } | ||
| /** | ||
| * Returns the matrix product between this and other | ||
| * @param {Matrix} other | ||
| * @return {Matrix} | ||
| */ | ||
| mmul(other) { | ||
| other = this.constructor.checkMatrix(other); | ||
| if (this.columns !== other.rows) { | ||
| // eslint-disable-next-line no-console | ||
| console.warn( | ||
| 'Number of columns of left matrix are not equal to number of rows of right matrix.' | ||
| ); | ||
| } | ||
| var m = this.rows; | ||
| var n = this.columns; | ||
| var p = other.columns; | ||
| var result = new this.constructor[Symbol.species](m, p); | ||
| var Bcolj = new Array(n); | ||
| for (var j = 0; j < p; j++) { | ||
| for (var k = 0; k < n; k++) { | ||
| Bcolj[k] = other.get(k, j); | ||
| } | ||
| for (var i = 0; i < m; i++) { | ||
| var s = 0; | ||
| for (k = 0; k < n; k++) { | ||
| s += this.get(i, k) * Bcolj[k]; | ||
| } | ||
| result.set(i, j, s); | ||
| } | ||
| } | ||
| return result; | ||
| } | ||
| strassen2x2(other) { | ||
| var result = new this.constructor[Symbol.species](2, 2); | ||
| const a11 = this.get(0, 0); | ||
| const b11 = other.get(0, 0); | ||
| const a12 = this.get(0, 1); | ||
| const b12 = other.get(0, 1); | ||
| const a21 = this.get(1, 0); | ||
| const b21 = other.get(1, 0); | ||
| const a22 = this.get(1, 1); | ||
| const b22 = other.get(1, 1); | ||
| // Compute intermediate values. | ||
| const m1 = (a11 + a22) * (b11 + b22); | ||
| const m2 = (a21 + a22) * b11; | ||
| const m3 = a11 * (b12 - b22); | ||
| const m4 = a22 * (b21 - b11); | ||
| const m5 = (a11 + a12) * b22; | ||
| const m6 = (a21 - a11) * (b11 + b12); | ||
| const m7 = (a12 - a22) * (b21 + b22); | ||
| // Combine intermediate values into the output. | ||
| const c00 = m1 + m4 - m5 + m7; | ||
| const c01 = m3 + m5; | ||
| const c10 = m2 + m4; | ||
| const c11 = m1 - m2 + m3 + m6; | ||
| result.set(0, 0, c00); | ||
| result.set(0, 1, c01); | ||
| result.set(1, 0, c10); | ||
| result.set(1, 1, c11); | ||
| return result; | ||
| } | ||
| strassen3x3(other) { | ||
| var result = new this.constructor[Symbol.species](3, 3); | ||
| const a00 = this.get(0, 0); | ||
| const a01 = this.get(0, 1); | ||
| const a02 = this.get(0, 2); | ||
| const a10 = this.get(1, 0); | ||
| const a11 = this.get(1, 1); | ||
| const a12 = this.get(1, 2); | ||
| const a20 = this.get(2, 0); | ||
| const a21 = this.get(2, 1); | ||
| const a22 = this.get(2, 2); | ||
| const b00 = other.get(0, 0); | ||
| const b01 = other.get(0, 1); | ||
| const b02 = other.get(0, 2); | ||
| const b10 = other.get(1, 0); | ||
| const b11 = other.get(1, 1); | ||
| const b12 = other.get(1, 2); | ||
| const b20 = other.get(2, 0); | ||
| const b21 = other.get(2, 1); | ||
| const b22 = other.get(2, 2); | ||
| const m1 = (a00 + a01 + a02 - a10 - a11 - a21 - a22) * b11; | ||
| const m2 = (a00 - a10) * (-b01 + b11); | ||
| const m3 = a11 * (-b00 + b01 + b10 - b11 - b12 - b20 + b22); | ||
| const m4 = (-a00 + a10 + a11) * (b00 - b01 + b11); | ||
| const m5 = (a10 + a11) * (-b00 + b01); | ||
| const m6 = a00 * b00; | ||
| const m7 = (-a00 + a20 + a21) * (b00 - b02 + b12); | ||
| const m8 = (-a00 + a20) * (b02 - b12); | ||
| const m9 = (a20 + a21) * (-b00 + b02); | ||
| const m10 = (a00 + a01 + a02 - a11 - a12 - a20 - a21) * b12; | ||
| const m11 = a21 * (-b00 + b02 + b10 - b11 - b12 - b20 + b21); | ||
| const m12 = (-a02 + a21 + a22) * (b11 + b20 - b21); | ||
| const m13 = (a02 - a22) * (b11 - b21); | ||
| const m14 = a02 * b20; | ||
| const m15 = (a21 + a22) * (-b20 + b21); | ||
| const m16 = (-a02 + a11 + a12) * (b12 + b20 - b22); | ||
| const m17 = (a02 - a12) * (b12 - b22); | ||
| const m18 = (a11 + a12) * (-b20 + b22); | ||
| const m19 = a01 * b10; | ||
| const m20 = a12 * b21; | ||
| const m21 = a10 * b02; | ||
| const m22 = a20 * b01; | ||
| const m23 = a22 * b22; | ||
| const c00 = m6 + m14 + m19; | ||
| const c01 = m1 + m4 + m5 + m6 + m12 + m14 + m15; | ||
| const c02 = m6 + m7 + m9 + m10 + m14 + m16 + m18; | ||
| const c10 = m2 + m3 + m4 + m6 + m14 + m16 + m17; | ||
| const c11 = m2 + m4 + m5 + m6 + m20; | ||
| const c12 = m14 + m16 + m17 + m18 + m21; | ||
| const c20 = m6 + m7 + m8 + m11 + m12 + m13 + m14; | ||
| const c21 = m12 + m13 + m14 + m15 + m22; | ||
| const c22 = m6 + m7 + m8 + m9 + m23; | ||
| result.set(0, 0, c00); | ||
| result.set(0, 1, c01); | ||
| result.set(0, 2, c02); | ||
| result.set(1, 0, c10); | ||
| result.set(1, 1, c11); | ||
| result.set(1, 2, c12); | ||
| result.set(2, 0, c20); | ||
| result.set(2, 1, c21); | ||
| result.set(2, 2, c22); | ||
| return result; | ||
| } | ||
| /** | ||
| * Returns the matrix product between x and y. More efficient than mmul(other) only when we multiply squared matrix and when the size of the matrix is > 1000. | ||
| * @param {Matrix} y | ||
| * @return {Matrix} | ||
| */ | ||
| mmulStrassen(y) { | ||
| var x = this.clone(); | ||
| var r1 = x.rows; | ||
| var c1 = x.columns; | ||
| var r2 = y.rows; | ||
| var c2 = y.columns; | ||
| if (c1 !== r2) { | ||
| // eslint-disable-next-line no-console | ||
| console.warn( | ||
| `Multiplying ${r1} x ${c1} and ${r2} x ${c2} matrix: dimensions do not match.` | ||
| ); | ||
| } | ||
| // Put a matrix into the top left of a matrix of zeros. | ||
| // `rows` and `cols` are the dimensions of the output matrix. | ||
| function embed(mat, rows, cols) { | ||
| var r = mat.rows; | ||
| var c = mat.columns; | ||
| if (r === rows && c === cols) { | ||
| return mat; | ||
| } else { | ||
| var resultat = AbstractMatrix.zeros(rows, cols); | ||
| resultat = resultat.setSubMatrix(mat, 0, 0); | ||
| return resultat; | ||
| } | ||
| } | ||
| // Make sure both matrices are the same size. | ||
| // This is exclusively for simplicity: | ||
| // this algorithm can be implemented with matrices of different sizes. | ||
| var r = Math.max(r1, r2); | ||
| var c = Math.max(c1, c2); | ||
| x = embed(x, r, c); | ||
| y = embed(y, r, c); | ||
| // Our recursive multiplication function. | ||
| function blockMult(a, b, rows, cols) { | ||
| // For small matrices, resort to naive multiplication. | ||
| if (rows <= 512 || cols <= 512) { | ||
| return a.mmul(b); // a is equivalent to this | ||
| } | ||
| // Apply dynamic padding. | ||
| if (rows % 2 === 1 && cols % 2 === 1) { | ||
| a = embed(a, rows + 1, cols + 1); | ||
| b = embed(b, rows + 1, cols + 1); | ||
| } else if (rows % 2 === 1) { | ||
| a = embed(a, rows + 1, cols); | ||
| b = embed(b, rows + 1, cols); | ||
| } else if (cols % 2 === 1) { | ||
| a = embed(a, rows, cols + 1); | ||
| b = embed(b, rows, cols + 1); | ||
| } | ||
| var halfRows = parseInt(a.rows / 2, 10); | ||
| var halfCols = parseInt(a.columns / 2, 10); | ||
| // Subdivide input matrices. | ||
| var a11 = a.subMatrix(0, halfRows - 1, 0, halfCols - 1); | ||
| var b11 = b.subMatrix(0, halfRows - 1, 0, halfCols - 1); | ||
| var a12 = a.subMatrix(0, halfRows - 1, halfCols, a.columns - 1); | ||
| var b12 = b.subMatrix(0, halfRows - 1, halfCols, b.columns - 1); | ||
| var a21 = a.subMatrix(halfRows, a.rows - 1, 0, halfCols - 1); | ||
| var b21 = b.subMatrix(halfRows, b.rows - 1, 0, halfCols - 1); | ||
| var a22 = a.subMatrix(halfRows, a.rows - 1, halfCols, a.columns - 1); | ||
| var b22 = b.subMatrix(halfRows, b.rows - 1, halfCols, b.columns - 1); | ||
| // Compute intermediate values. | ||
| var m1 = blockMult( | ||
| AbstractMatrix.add(a11, a22), | ||
| AbstractMatrix.add(b11, b22), | ||
| halfRows, | ||
| halfCols | ||
| ); | ||
| var m2 = blockMult(AbstractMatrix.add(a21, a22), b11, halfRows, halfCols); | ||
| var m3 = blockMult(a11, AbstractMatrix.sub(b12, b22), halfRows, halfCols); | ||
| var m4 = blockMult(a22, AbstractMatrix.sub(b21, b11), halfRows, halfCols); | ||
| var m5 = blockMult(AbstractMatrix.add(a11, a12), b22, halfRows, halfCols); | ||
| var m6 = blockMult( | ||
| AbstractMatrix.sub(a21, a11), | ||
| AbstractMatrix.add(b11, b12), | ||
| halfRows, | ||
| halfCols | ||
| ); | ||
| var m7 = blockMult( | ||
| AbstractMatrix.sub(a12, a22), | ||
| AbstractMatrix.add(b21, b22), | ||
| halfRows, | ||
| halfCols | ||
| ); | ||
| // Combine intermediate values into the output. | ||
| var c11 = AbstractMatrix.add(m1, m4); | ||
| c11.sub(m5); | ||
| c11.add(m7); | ||
| var c12 = AbstractMatrix.add(m3, m5); | ||
| var c21 = AbstractMatrix.add(m2, m4); | ||
| var c22 = AbstractMatrix.sub(m1, m2); | ||
| c22.add(m3); | ||
| c22.add(m6); | ||
| // Crop output to the desired size (undo dynamic padding). | ||
| var resultat = AbstractMatrix.zeros(2 * c11.rows, 2 * c11.columns); | ||
| resultat = resultat.setSubMatrix(c11, 0, 0); | ||
| resultat = resultat.setSubMatrix(c12, c11.rows, 0); | ||
| resultat = resultat.setSubMatrix(c21, 0, c11.columns); | ||
| resultat = resultat.setSubMatrix(c22, c11.rows, c11.columns); | ||
| return resultat.subMatrix(0, rows - 1, 0, cols - 1); | ||
| } | ||
| return blockMult(x, y, r, c); | ||
| } | ||
| /** | ||
| * Returns a row-by-row scaled matrix | ||
| * @param {number} [min=0] - Minimum scaled value | ||
| * @param {number} [max=1] - Maximum scaled value | ||
| * @return {Matrix} - The scaled matrix | ||
| */ | ||
| scaleRows(min, max) { | ||
| min = min === undefined ? 0 : min; | ||
| max = max === undefined ? 1 : max; | ||
| if (min >= max) { | ||
| throw new RangeError('min should be strictly smaller than max'); | ||
| } | ||
| var newMatrix = new this.constructor(this.rows, this.columns); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| const row = this.getRow(i); | ||
| rescale(row, { min, max, output: row }); | ||
| newMatrix.setRow(i, row); | ||
| } | ||
| return newMatrix; | ||
| } | ||
| /** | ||
| * Returns a new column-by-column scaled matrix | ||
| * @param {number} [min=0] - Minimum scaled value | ||
| * @param {number} [max=1] - Maximum scaled value | ||
| * @return {Matrix} - The new scaled matrix | ||
| * @example | ||
| * var matrix = new Matrix([[1,2],[-1,0]]); | ||
| * var scaledMatrix = matrix.scaleColumns(); // [[1,1],[0,0]] | ||
| */ | ||
| scaleColumns(min, max) { | ||
| min = min === undefined ? 0 : min; | ||
| max = max === undefined ? 1 : max; | ||
| if (min >= max) { | ||
| throw new RangeError('min should be strictly smaller than max'); | ||
| } | ||
| var newMatrix = new this.constructor(this.rows, this.columns); | ||
| for (var i = 0; i < this.columns; i++) { | ||
| const column = this.getColumn(i); | ||
| rescale(column, { | ||
| min: min, | ||
| max: max, | ||
| output: column | ||
| }); | ||
| newMatrix.setColumn(i, column); | ||
| } | ||
| return newMatrix; | ||
| } | ||
| reverseRows() { | ||
| const middle = Math.ceil(this.columns / 2); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < middle; j++) { | ||
| var first = this.get(i, j); | ||
| var last = this.get(i, this.columns - 1 - j); | ||
| this.set(i, j, last); | ||
| this.set(i, this.columns - 1 - j, first); | ||
| } | ||
| } | ||
| return this; | ||
| } | ||
| reverseColumns() { | ||
| const middle = Math.ceil(this.rows / 2); | ||
| for (var j = 0; j < this.columns; j++) { | ||
| for (var i = 0; i < middle; i++) { | ||
| var first = this.get(i, j); | ||
| var last = this.get(this.rows - 1 - i, j); | ||
| this.set(i, j, last); | ||
| this.set(this.rows - 1 - i, j, first); | ||
| } | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Returns the Kronecker product (also known as tensor product) between this and other | ||
| * See https://en.wikipedia.org/wiki/Kronecker_product | ||
| * @param {Matrix} other | ||
| * @return {Matrix} | ||
| */ | ||
| kroneckerProduct(other) { | ||
| other = this.constructor.checkMatrix(other); | ||
| var m = this.rows; | ||
| var n = this.columns; | ||
| var p = other.rows; | ||
| var q = other.columns; | ||
| var result = new this.constructor[Symbol.species](m * p, n * q); | ||
| for (var i = 0; i < m; i++) { | ||
| for (var j = 0; j < n; j++) { | ||
| for (var k = 0; k < p; k++) { | ||
| for (var l = 0; l < q; l++) { | ||
| result.set(p * i + k, q * j + l, this.get(i, j) * other.get(k, l)); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| return result; | ||
| } | ||
| /** | ||
| * Transposes the matrix and returns a new one containing the result | ||
| * @return {Matrix} | ||
| */ | ||
| transpose() { | ||
| var result = new this.constructor[Symbol.species](this.columns, this.rows); | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| result.set(j, i, this.get(i, j)); | ||
| } | ||
| } | ||
| return result; | ||
| } | ||
| /** | ||
| * Sorts the rows (in place) | ||
| * @param {function} compareFunction - usual Array.prototype.sort comparison function | ||
| * @return {Matrix} this | ||
| */ | ||
| sortRows(compareFunction) { | ||
| if (compareFunction === undefined) compareFunction = compareNumbers; | ||
| for (var i = 0; i < this.rows; i++) { | ||
| this.setRow(i, this.getRow(i).sort(compareFunction)); | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Sorts the columns (in place) | ||
| * @param {function} compareFunction - usual Array.prototype.sort comparison function | ||
| * @return {Matrix} this | ||
| */ | ||
| sortColumns(compareFunction) { | ||
| if (compareFunction === undefined) compareFunction = compareNumbers; | ||
| for (var i = 0; i < this.columns; i++) { | ||
| this.setColumn(i, this.getColumn(i).sort(compareFunction)); | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Returns a subset of the matrix | ||
| * @param {number} startRow - First row index | ||
| * @param {number} endRow - Last row index | ||
| * @param {number} startColumn - First column index | ||
| * @param {number} endColumn - Last column index | ||
| * @return {Matrix} | ||
| */ | ||
| subMatrix(startRow, endRow, startColumn, endColumn) { | ||
| checkRange(this, startRow, endRow, startColumn, endColumn); | ||
| var newMatrix = new this.constructor[Symbol.species]( | ||
| endRow - startRow + 1, | ||
| endColumn - startColumn + 1 | ||
| ); | ||
| for (var i = startRow; i <= endRow; i++) { | ||
| for (var j = startColumn; j <= endColumn; j++) { | ||
| newMatrix.set(i - startRow, j - startColumn, this.get(i, j)); | ||
| } | ||
| } | ||
| return newMatrix; | ||
| } | ||
| /** | ||
| * Returns a subset of the matrix based on an array of row indices | ||
| * @param {Array} indices - Array containing the row indices | ||
| * @param {number} [startColumn = 0] - First column index | ||
| * @param {number} [endColumn = this.columns-1] - Last column index | ||
| * @return {Matrix} | ||
| */ | ||
| subMatrixRow(indices, startColumn, endColumn) { | ||
| if (startColumn === undefined) startColumn = 0; | ||
| if (endColumn === undefined) endColumn = this.columns - 1; | ||
| if ( | ||
| startColumn > endColumn || | ||
| startColumn < 0 || | ||
| startColumn >= this.columns || | ||
| endColumn < 0 || | ||
| endColumn >= this.columns | ||
| ) { | ||
| throw new RangeError('Argument out of range'); | ||
| } | ||
| var newMatrix = new this.constructor[Symbol.species]( | ||
| indices.length, | ||
| endColumn - startColumn + 1 | ||
| ); | ||
| for (var i = 0; i < indices.length; i++) { | ||
| for (var j = startColumn; j <= endColumn; j++) { | ||
| if (indices[i] < 0 || indices[i] >= this.rows) { | ||
| throw new RangeError(`Row index out of range: ${indices[i]}`); | ||
| } | ||
| newMatrix.set(i, j - startColumn, this.get(indices[i], j)); | ||
| } | ||
| } | ||
| return newMatrix; | ||
| } | ||
| /** | ||
| * Returns a subset of the matrix based on an array of column indices | ||
| * @param {Array} indices - Array containing the column indices | ||
| * @param {number} [startRow = 0] - First row index | ||
| * @param {number} [endRow = this.rows-1] - Last row index | ||
| * @return {Matrix} | ||
| */ | ||
| subMatrixColumn(indices, startRow, endRow) { | ||
| if (startRow === undefined) startRow = 0; | ||
| if (endRow === undefined) endRow = this.rows - 1; | ||
| if ( | ||
| startRow > endRow || | ||
| startRow < 0 || | ||
| startRow >= this.rows || | ||
| endRow < 0 || | ||
| endRow >= this.rows | ||
| ) { | ||
| throw new RangeError('Argument out of range'); | ||
| } | ||
| var newMatrix = new this.constructor[Symbol.species]( | ||
| endRow - startRow + 1, | ||
| indices.length | ||
| ); | ||
| for (var i = 0; i < indices.length; i++) { | ||
| for (var j = startRow; j <= endRow; j++) { | ||
| if (indices[i] < 0 || indices[i] >= this.columns) { | ||
| throw new RangeError(`Column index out of range: ${indices[i]}`); | ||
| } | ||
| newMatrix.set(j - startRow, i, this.get(j, indices[i])); | ||
| } | ||
| } | ||
| return newMatrix; | ||
| } | ||
| /** | ||
| * Set a part of the matrix to the given sub-matrix | ||
| * @param {Matrix|Array< Array >} matrix - The source matrix from which to extract values. | ||
| * @param {number} startRow - The index of the first row to set | ||
| * @param {number} startColumn - The index of the first column to set | ||
| * @return {Matrix} | ||
| */ | ||
| setSubMatrix(matrix, startRow, startColumn) { | ||
| matrix = this.constructor.checkMatrix(matrix); | ||
| var endRow = startRow + matrix.rows - 1; | ||
| var endColumn = startColumn + matrix.columns - 1; | ||
| checkRange(this, startRow, endRow, startColumn, endColumn); | ||
| for (var i = 0; i < matrix.rows; i++) { | ||
| for (var j = 0; j < matrix.columns; j++) { | ||
| this.set(startRow + i, startColumn + j, matrix.get(i, j)); | ||
| } | ||
| } | ||
| return this; | ||
| } | ||
| /** | ||
| * Return a new matrix based on a selection of rows and columns | ||
| * @param {Array<number>} rowIndices - The row indices to select. Order matters and an index can be more than once. | ||
| * @param {Array<number>} columnIndices - The column indices to select. Order matters and an index can be use more than once. | ||
| * @return {Matrix} The new matrix | ||
| */ | ||
| selection(rowIndices, columnIndices) { | ||
| var indices = checkIndices(this, rowIndices, columnIndices); | ||
| var newMatrix = new this.constructor[Symbol.species]( | ||
| rowIndices.length, | ||
| columnIndices.length | ||
| ); | ||
| for (var i = 0; i < indices.row.length; i++) { | ||
| var rowIndex = indices.row[i]; | ||
| for (var j = 0; j < indices.column.length; j++) { | ||
| var columnIndex = indices.column[j]; | ||
| newMatrix.set(i, j, this.get(rowIndex, columnIndex)); | ||
| } | ||
| } | ||
| return newMatrix; | ||
| } | ||
| /** | ||
| * Returns the trace of the matrix (sum of the diagonal elements) | ||
| * @return {number} | ||
| */ | ||
| trace() { | ||
| var min = Math.min(this.rows, this.columns); | ||
| var trace = 0; | ||
| for (var i = 0; i < min; i++) { | ||
| trace += this.get(i, i); | ||
| } | ||
| return trace; | ||
| } | ||
| /** | ||
| * Creates an exact and independent copy of the matrix | ||
| * @return {Matrix} | ||
| */ | ||
| clone() { | ||
| var newMatrix = new this.constructor[Symbol.species]( | ||
| this.rows, | ||
| this.columns | ||
| ); | ||
| for (var row = 0; row < this.rows; row++) { | ||
| for (var column = 0; column < this.columns; column++) { | ||
| newMatrix.set(row, column, this.get(row, column)); | ||
| } | ||
| } | ||
| return newMatrix; | ||
| } | ||
| entropy(eps = 0) { | ||
| var sum = 0; | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| sum += this.get(i, j) * Math.log(this.get(i, j) + eps); | ||
| } | ||
| } | ||
| return 0 - sum; | ||
| } | ||
| variance(unbiased = true, means = this.mean('column')) { | ||
| if (typeof unbiased !== 'boolean') { | ||
| throw new TypeError('unbiased must be a boolean'); | ||
| } | ||
| if (!Array.isArray(means)) { | ||
| throw new TypeError('means must be an array'); | ||
| } | ||
| const rows = this.rows; | ||
| const cols = this.columns; | ||
| const variance = []; | ||
| for (var j = 0; j < cols; j++) { | ||
| var sum1 = 0; | ||
| var sum2 = 0; | ||
| var x = 0; | ||
| for (var i = 0; i < rows; i++) { | ||
| x = this.get(i, j) - means[j]; | ||
| sum1 += x; | ||
| sum2 += x * x; | ||
| } | ||
| if (unbiased) { | ||
| variance.push((sum2 - (sum1 * sum1) / rows) / (rows - 1)); | ||
| } else { | ||
| variance.push((sum2 - (sum1 * sum1) / rows) / rows); | ||
| } | ||
| } | ||
| return variance; | ||
| } | ||
| standardDeviation(unbiased = true, means = this.mean('column')) { | ||
| if (typeof unbiased !== 'boolean') { | ||
| throw new TypeError('unbiased must be a boolean'); | ||
| } | ||
| if (!Array.isArray(means)) { | ||
| throw new TypeError('means must be an array'); | ||
| } | ||
| const variance = this.variance(unbiased, means); | ||
| for (var i = 0; i < variance.length; i++) { | ||
| variance[i] = Math.sqrt(variance[i]); | ||
| } | ||
| return variance; | ||
| } | ||
| } | ||
| AbstractMatrix.prototype.klass = 'Matrix'; | ||
| function compareNumbers(a, b) { | ||
| return a - b; | ||
| } | ||
| /* | ||
| Synonyms | ||
| */ | ||
| AbstractMatrix.random = AbstractMatrix.rand; | ||
| AbstractMatrix.diagonal = AbstractMatrix.diag; | ||
| AbstractMatrix.prototype.diagonal = AbstractMatrix.prototype.diag; | ||
| AbstractMatrix.identity = AbstractMatrix.eye; | ||
| AbstractMatrix.prototype.negate = AbstractMatrix.prototype.neg; | ||
| AbstractMatrix.prototype.tensorProduct = | ||
| AbstractMatrix.prototype.kroneckerProduct; | ||
| /* | ||
| Add dynamically instance and static methods for mathematical operations | ||
| */ | ||
| var inplaceOperator = ` | ||
| (function %name%(value) { | ||
| if (typeof value === 'number') return this.%name%S(value); | ||
| return this.%name%M(value); | ||
| }) | ||
| `; | ||
| var inplaceOperatorScalar = ` | ||
| (function %name%S(value) { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) %op% value); | ||
| } | ||
| } | ||
| return this; | ||
| }) | ||
| `; | ||
| var inplaceOperatorMatrix = ` | ||
| (function %name%M(matrix) { | ||
| matrix = this.constructor.checkMatrix(matrix); | ||
| if (this.rows !== matrix.rows || | ||
| this.columns !== matrix.columns) { | ||
| throw new RangeError('Matrices dimensions must be equal'); | ||
| } | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, this.get(i, j) %op% matrix.get(i, j)); | ||
| } | ||
| } | ||
| return this; | ||
| }) | ||
| `; | ||
| var staticOperator = ` | ||
| (function %name%(matrix, value) { | ||
| var newMatrix = new this[Symbol.species](matrix); | ||
| return newMatrix.%name%(value); | ||
| }) | ||
| `; | ||
| var inplaceMethod = ` | ||
| (function %name%() { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, %method%(this.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }) | ||
| `; | ||
| var staticMethod = ` | ||
| (function %name%(matrix) { | ||
| var newMatrix = new this[Symbol.species](matrix); | ||
| return newMatrix.%name%(); | ||
| }) | ||
| `; | ||
| var inplaceMethodWithArgs = ` | ||
| (function %name%(%args%) { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, %method%(this.get(i, j), %args%)); | ||
| } | ||
| } | ||
| return this; | ||
| }) | ||
| `; | ||
| var staticMethodWithArgs = ` | ||
| (function %name%(matrix, %args%) { | ||
| var newMatrix = new this[Symbol.species](matrix); | ||
| return newMatrix.%name%(%args%); | ||
| }) | ||
| `; | ||
| var inplaceMethodWithOneArgScalar = ` | ||
| (function %name%S(value) { | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, %method%(this.get(i, j), value)); | ||
| } | ||
| } | ||
| return this; | ||
| }) | ||
| `; | ||
| var inplaceMethodWithOneArgMatrix = ` | ||
| (function %name%M(matrix) { | ||
| matrix = this.constructor.checkMatrix(matrix); | ||
| if (this.rows !== matrix.rows || | ||
| this.columns !== matrix.columns) { | ||
| throw new RangeError('Matrices dimensions must be equal'); | ||
| } | ||
| for (var i = 0; i < this.rows; i++) { | ||
| for (var j = 0; j < this.columns; j++) { | ||
| this.set(i, j, %method%(this.get(i, j), matrix.get(i, j))); | ||
| } | ||
| } | ||
| return this; | ||
| }) | ||
| `; | ||
| var inplaceMethodWithOneArg = ` | ||
| (function %name%(value) { | ||
| if (typeof value === 'number') return this.%name%S(value); | ||
| return this.%name%M(value); | ||
| }) | ||
| `; | ||
| var staticMethodWithOneArg = staticMethodWithArgs; | ||
| var operators = [ | ||
| // Arithmetic operators | ||
| ['+', 'add'], | ||
| ['-', 'sub', 'subtract'], | ||
| ['*', 'mul', 'multiply'], | ||
| ['/', 'div', 'divide'], | ||
| ['%', 'mod', 'modulus'], | ||
| // Bitwise operators | ||
| ['&', 'and'], | ||
| ['|', 'or'], | ||
| ['^', 'xor'], | ||
| ['<<', 'leftShift'], | ||
| ['>>', 'signPropagatingRightShift'], | ||
| ['>>>', 'rightShift', 'zeroFillRightShift'] | ||
| ]; | ||
| var i; | ||
| var eval2 = eval; // eslint-disable-line no-eval | ||
| for (var operator of operators) { | ||
| var inplaceOp = eval2( | ||
| fillTemplateFunction(inplaceOperator, { | ||
| name: operator[1], | ||
| op: operator[0] | ||
| }) | ||
| ); | ||
| var inplaceOpS = eval2( | ||
| fillTemplateFunction(inplaceOperatorScalar, { | ||
| name: `${operator[1]}S`, | ||
| op: operator[0] | ||
| }) | ||
| ); | ||
| var inplaceOpM = eval2( | ||
| fillTemplateFunction(inplaceOperatorMatrix, { | ||
| name: `${operator[1]}M`, | ||
| op: operator[0] | ||
| }) | ||
| ); | ||
| var staticOp = eval2( | ||
| fillTemplateFunction(staticOperator, { name: operator[1] }) | ||
| ); | ||
| for (i = 1; i < operator.length; i++) { | ||
| AbstractMatrix.prototype[operator[i]] = inplaceOp; | ||
| AbstractMatrix.prototype[`${operator[i]}S`] = inplaceOpS; | ||
| AbstractMatrix.prototype[`${operator[i]}M`] = inplaceOpM; | ||
| AbstractMatrix[operator[i]] = staticOp; | ||
| } | ||
| } | ||
| var methods = [['~', 'not']]; | ||
| [ | ||
| 'abs', | ||
| 'acos', | ||
| 'acosh', | ||
| 'asin', | ||
| 'asinh', | ||
| 'atan', | ||
| 'atanh', | ||
| 'cbrt', | ||
| 'ceil', | ||
| 'clz32', | ||
| 'cos', | ||
| 'cosh', | ||
| 'exp', | ||
| 'expm1', | ||
| 'floor', | ||
| 'fround', | ||
| 'log', | ||
| 'log1p', | ||
| 'log10', | ||
| 'log2', | ||
| 'round', | ||
| 'sign', | ||
| 'sin', | ||
| 'sinh', | ||
| 'sqrt', | ||
| 'tan', | ||
| 'tanh', | ||
| 'trunc' | ||
| ].forEach(function (mathMethod) { | ||
| methods.push([`Math.${mathMethod}`, mathMethod]); | ||
| }); | ||
| for (var method of methods) { | ||
| var inplaceMeth = eval2( | ||
| fillTemplateFunction(inplaceMethod, { | ||
| name: method[1], | ||
| method: method[0] | ||
| }) | ||
| ); | ||
| var staticMeth = eval2( | ||
| fillTemplateFunction(staticMethod, { name: method[1] }) | ||
| ); | ||
| for (i = 1; i < method.length; i++) { | ||
| AbstractMatrix.prototype[method[i]] = inplaceMeth; | ||
| AbstractMatrix[method[i]] = staticMeth; | ||
| } | ||
| } | ||
| var methodsWithArgs = [['Math.pow', 1, 'pow']]; | ||
| for (var methodWithArg of methodsWithArgs) { | ||
| var args = 'arg0'; | ||
| for (i = 1; i < methodWithArg[1]; i++) { | ||
| args += `, arg${i}`; | ||
| } | ||
| if (methodWithArg[1] !== 1) { | ||
| var inplaceMethWithArgs = eval2( | ||
| fillTemplateFunction(inplaceMethodWithArgs, { | ||
| name: methodWithArg[2], | ||
| method: methodWithArg[0], | ||
| args: args | ||
| }) | ||
| ); | ||
| var staticMethWithArgs = eval2( | ||
| fillTemplateFunction(staticMethodWithArgs, { | ||
| name: methodWithArg[2], | ||
| args: args | ||
| }) | ||
| ); | ||
| for (i = 2; i < methodWithArg.length; i++) { | ||
| AbstractMatrix.prototype[methodWithArg[i]] = inplaceMethWithArgs; | ||
| AbstractMatrix[methodWithArg[i]] = staticMethWithArgs; | ||
| } | ||
| } else { | ||
| var tmplVar = { | ||
| name: methodWithArg[2], | ||
| args: args, | ||
| method: methodWithArg[0] | ||
| }; | ||
| var inplaceMethod2 = eval2( | ||
| fillTemplateFunction(inplaceMethodWithOneArg, tmplVar) | ||
| ); | ||
| var inplaceMethodS = eval2( | ||
| fillTemplateFunction(inplaceMethodWithOneArgScalar, tmplVar) | ||
| ); | ||
| var inplaceMethodM = eval2( | ||
| fillTemplateFunction(inplaceMethodWithOneArgMatrix, tmplVar) | ||
| ); | ||
| var staticMethod2 = eval2( | ||
| fillTemplateFunction(staticMethodWithOneArg, tmplVar) | ||
| ); | ||
| for (i = 2; i < methodWithArg.length; i++) { | ||
| AbstractMatrix.prototype[methodWithArg[i]] = inplaceMethod2; | ||
| AbstractMatrix.prototype[`${methodWithArg[i]}M`] = inplaceMethodM; | ||
| AbstractMatrix.prototype[`${methodWithArg[i]}S`] = inplaceMethodS; | ||
| AbstractMatrix[methodWithArg[i]] = staticMethod2; | ||
| } | ||
| } | ||
| } | ||
| function fillTemplateFunction(template, values) { | ||
| for (var value in values) { | ||
| template = template.replace(new RegExp(`%${value}%`, 'g'), values[value]); | ||
| } | ||
| return template; | ||
| } |
Sorry, the diff of this file is too big to display
311813
16.17%37
5.71%10011
13.49%