UNPKG

6.13 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.createInv = void 0;
7
8var _is = require("../../utils/is.js");
9
10var _array = require("../../utils/array.js");
11
12var _factory = require("../../utils/factory.js");
13
14var _string = require("../../utils/string.js");
15
16var name = 'inv';
17var dependencies = ['typed', 'matrix', 'divideScalar', 'addScalar', 'multiply', 'unaryMinus', 'det', 'identity', 'abs'];
18var 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});
213exports.createInv = createInv;
\No newline at end of file