inv.js (6132B)
1 "use strict"; 2 3 Object.defineProperty(exports, "__esModule", { 4 value: true 5 }); 6 exports.createInv = void 0; 7 8 var _is = require("../../utils/is.js"); 9 10 var _array = require("../../utils/array.js"); 11 12 var _factory = require("../../utils/factory.js"); 13 14 var _string = require("../../utils/string.js"); 15 16 var name = 'inv'; 17 var dependencies = ['typed', 'matrix', 'divideScalar', 'addScalar', 'multiply', 'unaryMinus', 'det', 'identity', 'abs']; 18 var createInv = /* #__PURE__ */(0, _factory.factory)(name, dependencies, function (_ref) { 19 var typed = _ref.typed, 20 matrix = _ref.matrix, 21 divideScalar = _ref.divideScalar, 22 addScalar = _ref.addScalar, 23 multiply = _ref.multiply, 24 unaryMinus = _ref.unaryMinus, 25 det = _ref.det, 26 identity = _ref.identity, 27 abs = _ref.abs; 28 29 /** 30 * Calculate the inverse of a square matrix. 31 * 32 * Syntax: 33 * 34 * math.inv(x) 35 * 36 * Examples: 37 * 38 * math.inv([[1, 2], [3, 4]]) // returns [[-2, 1], [1.5, -0.5]] 39 * math.inv(4) // returns 0.25 40 * 1 / 4 // returns 0.25 41 * 42 * See also: 43 * 44 * det, transpose 45 * 46 * @param {number | Complex | Array | Matrix} x Matrix to be inversed 47 * @return {number | Complex | Array | Matrix} The inverse of `x`. 48 */ 49 return typed(name, { 50 'Array | Matrix': function ArrayMatrix(x) { 51 var size = (0, _is.isMatrix)(x) ? x.size() : (0, _array.arraySize)(x); 52 53 switch (size.length) { 54 case 1: 55 // vector 56 if (size[0] === 1) { 57 if ((0, _is.isMatrix)(x)) { 58 return matrix([divideScalar(1, x.valueOf()[0])]); 59 } else { 60 return [divideScalar(1, x[0])]; 61 } 62 } else { 63 throw new RangeError('Matrix must be square ' + '(size: ' + (0, _string.format)(size) + ')'); 64 } 65 66 case 2: 67 // two dimensional array 68 { 69 var rows = size[0]; 70 var cols = size[1]; 71 72 if (rows === cols) { 73 if ((0, _is.isMatrix)(x)) { 74 return matrix(_inv(x.valueOf(), rows, cols), x.storage()); 75 } else { 76 // return an Array 77 return _inv(x, rows, cols); 78 } 79 } else { 80 throw new RangeError('Matrix must be square ' + '(size: ' + (0, _string.format)(size) + ')'); 81 } 82 } 83 84 default: 85 // multi dimensional array 86 throw new RangeError('Matrix must be two dimensional ' + '(size: ' + (0, _string.format)(size) + ')'); 87 } 88 }, 89 any: function any(x) { 90 // scalar 91 return divideScalar(1, x); // FIXME: create a BigNumber one when configured for bignumbers 92 } 93 }); 94 /** 95 * Calculate the inverse of a square matrix 96 * @param {Array[]} mat A square matrix 97 * @param {number} rows Number of rows 98 * @param {number} cols Number of columns, must equal rows 99 * @return {Array[]} inv Inverse matrix 100 * @private 101 */ 102 103 function _inv(mat, rows, cols) { 104 var r, s, f, value, temp; 105 106 if (rows === 1) { 107 // this is a 1 x 1 matrix 108 value = mat[0][0]; 109 110 if (value === 0) { 111 throw Error('Cannot calculate inverse, determinant is zero'); 112 } 113 114 return [[divideScalar(1, value)]]; 115 } else if (rows === 2) { 116 // this is a 2 x 2 matrix 117 var d = det(mat); 118 119 if (d === 0) { 120 throw Error('Cannot calculate inverse, determinant is zero'); 121 } 122 123 return [[divideScalar(mat[1][1], d), divideScalar(unaryMinus(mat[0][1]), d)], [divideScalar(unaryMinus(mat[1][0]), d), divideScalar(mat[0][0], d)]]; 124 } else { 125 // this is a matrix of 3 x 3 or larger 126 // calculate inverse using gauss-jordan elimination 127 // https://en.wikipedia.org/wiki/Gaussian_elimination 128 // http://mathworld.wolfram.com/MatrixInverse.html 129 // http://math.uww.edu/~mcfarlat/inverse.htm 130 // make a copy of the matrix (only the arrays, not of the elements) 131 var A = mat.concat(); 132 133 for (r = 0; r < rows; r++) { 134 A[r] = A[r].concat(); 135 } // create an identity matrix which in the end will contain the 136 // matrix inverse 137 138 139 var B = identity(rows).valueOf(); // loop over all columns, and perform row reductions 140 141 for (var c = 0; c < cols; c++) { 142 // Pivoting: Swap row c with row r, where row r contains the largest element A[r][c] 143 var ABig = abs(A[c][c]); 144 var rBig = c; 145 r = c + 1; 146 147 while (r < rows) { 148 if (abs(A[r][c]) > ABig) { 149 ABig = abs(A[r][c]); 150 rBig = r; 151 } 152 153 r++; 154 } 155 156 if (ABig === 0) { 157 throw Error('Cannot calculate inverse, determinant is zero'); 158 } 159 160 r = rBig; 161 162 if (r !== c) { 163 temp = A[c]; 164 A[c] = A[r]; 165 A[r] = temp; 166 temp = B[c]; 167 B[c] = B[r]; 168 B[r] = temp; 169 } // eliminate non-zero values on the other rows at column c 170 171 172 var Ac = A[c]; 173 var Bc = B[c]; 174 175 for (r = 0; r < rows; r++) { 176 var Ar = A[r]; 177 var Br = B[r]; 178 179 if (r !== c) { 180 // eliminate value at column c and row r 181 if (Ar[c] !== 0) { 182 f = divideScalar(unaryMinus(Ar[c]), Ac[c]); // add (f * row c) to row r to eliminate the value 183 // at column c 184 185 for (s = c; s < cols; s++) { 186 Ar[s] = addScalar(Ar[s], multiply(f, Ac[s])); 187 } 188 189 for (s = 0; s < cols; s++) { 190 Br[s] = addScalar(Br[s], multiply(f, Bc[s])); 191 } 192 } 193 } else { 194 // normalize value at Acc to 1, 195 // divide each value on row r with the value at Acc 196 f = Ac[c]; 197 198 for (s = c; s < cols; s++) { 199 Ar[s] = divideScalar(Ar[s], f); 200 } 201 202 for (s = 0; s < cols; s++) { 203 Br[s] = divideScalar(Br[s], f); 204 } 205 } 206 } 207 } 208 209 return B; 210 } 211 } 212 }); 213 exports.createInv = createInv;