UNPKG

3.86 kBJavaScriptView Raw
1import { isMatrix } from '../../utils/is';
2import { clone } from '../../utils/object';
3import { format } from '../../utils/string';
4import { factory } from '../../utils/factory';
5var name = 'det';
6var dependencies = ['typed', 'matrix', 'subtract', 'multiply', 'unaryMinus', 'lup'];
7export var createDet = /* #__PURE__ */factory(name, dependencies, function (_ref) {
8 var typed = _ref.typed,
9 matrix = _ref.matrix,
10 subtract = _ref.subtract,
11 multiply = _ref.multiply,
12 unaryMinus = _ref.unaryMinus,
13 lup = _ref.lup;
14
15 /**
16 * Calculate the determinant of a matrix.
17 *
18 * Syntax:
19 *
20 * math.det(x)
21 *
22 * Examples:
23 *
24 * math.det([[1, 2], [3, 4]]) // returns -2
25 *
26 * const A = [
27 * [-2, 2, 3],
28 * [-1, 1, 3],
29 * [2, 0, -1]
30 * ]
31 * math.det(A) // returns 6
32 *
33 * See also:
34 *
35 * inv
36 *
37 * @param {Array | Matrix} x A matrix
38 * @return {number} The determinant of `x`
39 */
40 return typed(name, {
41 any: function any(x) {
42 return clone(x);
43 },
44 'Array | Matrix': function det(x) {
45 var size;
46
47 if (isMatrix(x)) {
48 size = x.size();
49 } else if (Array.isArray(x)) {
50 x = matrix(x);
51 size = x.size();
52 } else {
53 // a scalar
54 size = [];
55 }
56
57 switch (size.length) {
58 case 0:
59 // scalar
60 return clone(x);
61
62 case 1:
63 // vector
64 if (size[0] === 1) {
65 return clone(x.valueOf()[0]);
66 } else {
67 throw new RangeError('Matrix must be square ' + '(size: ' + format(size) + ')');
68 }
69
70 case 2:
71 {
72 // two dimensional array
73 var rows = size[0];
74 var cols = size[1];
75
76 if (rows === cols) {
77 return _det(x.clone().valueOf(), rows, cols);
78 } else {
79 throw new RangeError('Matrix must be square ' + '(size: ' + format(size) + ')');
80 }
81 }
82
83 default:
84 // multi dimensional array
85 throw new RangeError('Matrix must be two dimensional ' + '(size: ' + format(size) + ')');
86 }
87 }
88 });
89 /**
90 * Calculate the determinant of a matrix
91 * @param {Array[]} matrix A square, two dimensional matrix
92 * @param {number} rows Number of rows of the matrix (zero-based)
93 * @param {number} cols Number of columns of the matrix (zero-based)
94 * @returns {number} det
95 * @private
96 */
97
98 function _det(matrix, rows, cols) {
99 if (rows === 1) {
100 // this is a 1 x 1 matrix
101 return clone(matrix[0][0]);
102 } else if (rows === 2) {
103 // this is a 2 x 2 matrix
104 // the determinant of [a11,a12;a21,a22] is det = a11*a22-a21*a12
105 return subtract(multiply(matrix[0][0], matrix[1][1]), multiply(matrix[1][0], matrix[0][1]));
106 } else {
107 // Compute the LU decomposition
108 var decomp = lup(matrix); // The determinant is the product of the diagonal entries of U (and those of L, but they are all 1)
109
110 var det = decomp.U[0][0];
111
112 for (var _i = 1; _i < rows; _i++) {
113 det = multiply(det, decomp.U[_i][_i]);
114 } // The determinant will be multiplied by 1 or -1 depending on the parity of the permutation matrix.
115 // This can be determined by counting the cycles. This is roughly a linear time algorithm.
116
117
118 var evenCycles = 0;
119 var i = 0;
120 var visited = [];
121
122 while (true) {
123 while (visited[i]) {
124 i++;
125 }
126
127 if (i >= rows) break;
128 var j = i;
129 var cycleLen = 0;
130
131 while (!visited[decomp.p[j]]) {
132 visited[decomp.p[j]] = true;
133 j = decomp.p[j];
134 cycleLen++;
135 }
136
137 if (cycleLen % 2 === 0) {
138 evenCycles++;
139 }
140 }
141
142 return evenCycles % 2 === 0 ? det : unaryMinus(det);
143 }
144 }
145});
\No newline at end of file