"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createDet = void 0; var _is = require("../../utils/is.js"); var _object = require("../../utils/object.js"); var _string = require("../../utils/string.js"); var _factory = require("../../utils/factory.js"); const name = 'det'; const dependencies = ['typed', 'matrix', 'subtractScalar', 'multiply', 'divideScalar', 'isZero', 'unaryMinus']; const createDet = exports.createDet = /* #__PURE__ */(0, _factory.factory)(name, dependencies, _ref => { let { typed, matrix, subtractScalar, multiply, divideScalar, isZero, unaryMinus } = _ref; /** * Calculate the determinant of a matrix. * * Syntax: * * math.det(x) * * Examples: * * math.det([[1, 2], [3, 4]]) // returns -2 * * const A = [ * [-2, 2, 3], * [-1, 1, 3], * [2, 0, -1] * ] * math.det(A) // returns 6 * * See also: * * inv * * @param {Array | Matrix} x A matrix * @return {number} The determinant of `x` */ return typed(name, { any: function (x) { return (0, _object.clone)(x); }, 'Array | Matrix': function det(x) { let size; if ((0, _is.isMatrix)(x)) { size = x.size(); } else if (Array.isArray(x)) { x = matrix(x); size = x.size(); } else { // a scalar size = []; } switch (size.length) { case 0: // scalar return (0, _object.clone)(x); case 1: // vector if (size[0] === 1) { return (0, _object.clone)(x.valueOf()[0]); } if (size[0] === 0) { return 1; // det of an empty matrix is per definition 1 } else { throw new RangeError('Matrix must be square ' + '(size: ' + (0, _string.format)(size) + ')'); } case 2: { // two-dimensional array const rows = size[0]; const cols = size[1]; if (rows === cols) { return _det(x.clone().valueOf(), rows, cols); } if (cols === 0) { return 1; // det of an empty matrix is per definition 1 } else { throw new RangeError('Matrix must be square ' + '(size: ' + (0, _string.format)(size) + ')'); } } default: // multi dimensional array throw new RangeError('Matrix must be two dimensional ' + '(size: ' + (0, _string.format)(size) + ')'); } } }); /** * Calculate the determinant of a matrix * @param {Array[]} matrix A square, two dimensional matrix * @param {number} rows Number of rows of the matrix (zero-based) * @param {number} cols Number of columns of the matrix (zero-based) * @returns {number} det * @private */ function _det(matrix, rows, cols) { if (rows === 1) { // this is a 1 x 1 matrix return (0, _object.clone)(matrix[0][0]); } else if (rows === 2) { // this is a 2 x 2 matrix // the determinant of [a11,a12;a21,a22] is det = a11*a22-a21*a12 return subtractScalar(multiply(matrix[0][0], matrix[1][1]), multiply(matrix[1][0], matrix[0][1])); } else { // Bareiss algorithm // this algorithm have same complexity as LUP decomposition (O(n^3)) // but it preserve precision of floating point more relative to the LUP decomposition let negated = false; const rowIndices = new Array(rows).fill(0).map((_, i) => i); // matrix index of row i for (let k = 0; k < rows; k++) { let k_ = rowIndices[k]; if (isZero(matrix[k_][k])) { let _k; for (_k = k + 1; _k < rows; _k++) { if (!isZero(matrix[rowIndices[_k]][k])) { k_ = rowIndices[_k]; rowIndices[_k] = rowIndices[k]; rowIndices[k] = k_; negated = !negated; break; } } if (_k === rows) return matrix[k_][k]; // some zero of the type } const piv = matrix[k_][k]; const piv_ = k === 0 ? 1 : matrix[rowIndices[k - 1]][k - 1]; for (let i = k + 1; i < rows; i++) { const i_ = rowIndices[i]; for (let j = k + 1; j < rows; j++) { matrix[i_][j] = divideScalar(subtractScalar(multiply(matrix[i_][j], piv), multiply(matrix[i_][k], matrix[k_][j])), piv_); } } } const det = matrix[rowIndices[rows - 1]][rows - 1]; return negated ? unaryMinus(det) : det; } } });