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