@rayyamhk/matrix
Version:
A professional, comprehensive and high-performance library for you to manipulate matrices.
145 lines (106 loc) • 4.71 kB
JavaScript
"use strict";
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
var _require = require('../../Error'),
INVALID_MATRIX = _require.INVALID_MATRIX;
/**
* Calculates the QR decomposition of the Matrix
* where Q is orthogonal matrix, R is upper triangular matrix.<br><br>
*
* The algorithm is implemented using Householder Transform instead of Gram–Schmidt process
* because the Householder Transform is more numerically stable.
* @memberof Matrix
* @static
* @param {Matrix} A - Any matrix
* @returns {Matrix[]} The QR decomposition of matrix in the form of [Q, R]
*/
function QR(A) {
if (!(A instanceof this)) {
throw new Error(INVALID_MATRIX);
}
var _A$size = A.size(),
_A$size2 = _slicedToArray(_A$size, 2),
row = _A$size2[0],
col = _A$size2[1];
var size = Math.min(row, col);
var EPSILON = 1 / (Math.pow(10, A._digit) * 2);
var matrixR = this.clone(A)._matrix;
var matrixQ = this.identity(row)._matrix;
for (var j = 0; j < size; j++) {
// if all entries below main diagonal are considered as zero, skip this round
var skip = true;
for (var i = j + 1; i < row; i++) {
if (Math.abs(matrixR[i][j]) >= EPSILON) {
skip = false;
break;
}
}
if (!skip) {
// Apply Householder transform
var norm = 0;
for (var _i2 = j; _i2 < row; _i2++) {
norm += Math.pow(matrixR[_i2][j], 2);
}
norm = Math.sqrt(norm); // reduce floating point arithmatic error
var s = -1;
if (matrixR[j][j] < 0) {
s = 1;
}
var u1 = matrixR[j][j] - s * norm;
var w = new Array(row - j);
for (var _i3 = 0; _i3 < row - j; _i3++) {
w[_i3] = matrixR[_i3 + j][j] / u1;
}
w[0] = 1;
var tau = -1 * s * u1 / norm;
var subR = new Array(row - j);
for (var _i4 = 0; _i4 < row - j; _i4++) {
var newRow = new Array(col);
for (var k = 0; k < col; k++) {
newRow[k] = matrixR[j + _i4][k];
}
subR[_i4] = newRow;
}
for (var _i5 = j; _i5 < row; _i5++) {
for (var _k = 0; _k < col; _k++) {
var summation = 0;
for (var m = 0; m < row - j; m++) {
summation += subR[m][_k] * w[m];
}
matrixR[_i5][_k] = subR[_i5 - j][_k] - tau * w[_i5 - j] * summation;
}
}
var subQ = new Array(row);
for (var _i6 = 0; _i6 < row; _i6++) {
var _newRow = new Array(row - j);
for (var _k2 = 0; _k2 < row - j; _k2++) {
_newRow[_k2] = matrixQ[_i6][j + _k2];
}
subQ[_i6] = _newRow;
}
for (var _i7 = 0; _i7 < row; _i7++) {
for (var _k3 = j; _k3 < row; _k3++) {
var _summation = 0;
for (var _m = 0; _m < row - j; _m++) {
_summation += subQ[_i7][_m] * w[_m];
}
matrixQ[_i7][_k3] = subQ[_i7][_k3 - j] - tau * w[_k3 - j] * _summation;
}
}
}
}
for (var _i8 = 0; _i8 < row; _i8++) {
for (var _j = 0; _j < col; _j++) {
if (_i8 > _j) {
matrixR[_i8][_j] = 0;
}
}
}
return [new this(matrixQ), new this(matrixR)];
}
;
module.exports = QR;