UNPKG

@rayyamhk/matrix

Version:

A professional, comprehensive and high-performance library for you to manipulate matrices.

145 lines (106 loc) 4.71 kB
"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;