det.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.createDet = void 0;
  6. var _is = require("../../utils/is.js");
  7. var _object = require("../../utils/object.js");
  8. var _string = require("../../utils/string.js");
  9. var _factory = require("../../utils/factory.js");
  10. var name = 'det';
  11. var dependencies = ['typed', 'matrix', 'subtract', 'multiply', 'divideScalar', 'isZero', 'unaryMinus'];
  12. var createDet = /* #__PURE__ */(0, _factory.factory)(name, dependencies, function (_ref) {
  13. var typed = _ref.typed,
  14. matrix = _ref.matrix,
  15. subtract = _ref.subtract,
  16. multiply = _ref.multiply,
  17. divideScalar = _ref.divideScalar,
  18. isZero = _ref.isZero,
  19. unaryMinus = _ref.unaryMinus;
  20. /**
  21. * Calculate the determinant of a matrix.
  22. *
  23. * Syntax:
  24. *
  25. * math.det(x)
  26. *
  27. * Examples:
  28. *
  29. * math.det([[1, 2], [3, 4]]) // returns -2
  30. *
  31. * const A = [
  32. * [-2, 2, 3],
  33. * [-1, 1, 3],
  34. * [2, 0, -1]
  35. * ]
  36. * math.det(A) // returns 6
  37. *
  38. * See also:
  39. *
  40. * inv
  41. *
  42. * @param {Array | Matrix} x A matrix
  43. * @return {number} The determinant of `x`
  44. */
  45. return typed(name, {
  46. any: function any(x) {
  47. return (0, _object.clone)(x);
  48. },
  49. 'Array | Matrix': function det(x) {
  50. var size;
  51. if ((0, _is.isMatrix)(x)) {
  52. size = x.size();
  53. } else if (Array.isArray(x)) {
  54. x = matrix(x);
  55. size = x.size();
  56. } else {
  57. // a scalar
  58. size = [];
  59. }
  60. switch (size.length) {
  61. case 0:
  62. // scalar
  63. return (0, _object.clone)(x);
  64. case 1:
  65. // vector
  66. if (size[0] === 1) {
  67. return (0, _object.clone)(x.valueOf()[0]);
  68. }
  69. if (size[0] === 0) {
  70. return 1; // det of an empty matrix is per definition 1
  71. } else {
  72. throw new RangeError('Matrix must be square ' + '(size: ' + (0, _string.format)(size) + ')');
  73. }
  74. case 2:
  75. {
  76. // two-dimensional array
  77. var rows = size[0];
  78. var cols = size[1];
  79. if (rows === cols) {
  80. return _det(x.clone().valueOf(), rows, cols);
  81. }
  82. if (cols === 0) {
  83. return 1; // det of an empty matrix is per definition 1
  84. } else {
  85. throw new RangeError('Matrix must be square ' + '(size: ' + (0, _string.format)(size) + ')');
  86. }
  87. }
  88. default:
  89. // multi dimensional array
  90. throw new RangeError('Matrix must be two dimensional ' + '(size: ' + (0, _string.format)(size) + ')');
  91. }
  92. }
  93. });
  94. /**
  95. * Calculate the determinant of a matrix
  96. * @param {Array[]} matrix A square, two dimensional matrix
  97. * @param {number} rows Number of rows of the matrix (zero-based)
  98. * @param {number} cols Number of columns of the matrix (zero-based)
  99. * @returns {number} det
  100. * @private
  101. */
  102. function _det(matrix, rows, cols) {
  103. if (rows === 1) {
  104. // this is a 1 x 1 matrix
  105. return (0, _object.clone)(matrix[0][0]);
  106. } else if (rows === 2) {
  107. // this is a 2 x 2 matrix
  108. // the determinant of [a11,a12;a21,a22] is det = a11*a22-a21*a12
  109. return subtract(multiply(matrix[0][0], matrix[1][1]), multiply(matrix[1][0], matrix[0][1]));
  110. } else {
  111. // Bareiss algorithm
  112. // this algorithm have same complexity as LUP decomposition (O(n^3))
  113. // but it preserve precision of floating point more relative to the LUP decomposition
  114. var negated = false;
  115. var rowIndices = new Array(rows).fill(0).map(function (_, i) {
  116. return i;
  117. }); // matrix index of row i
  118. for (var k = 0; k < rows; k++) {
  119. var k_ = rowIndices[k];
  120. if (isZero(matrix[k_][k])) {
  121. var _k = void 0;
  122. for (_k = k + 1; _k < rows; _k++) {
  123. if (!isZero(matrix[rowIndices[_k]][k])) {
  124. k_ = rowIndices[_k];
  125. rowIndices[_k] = rowIndices[k];
  126. rowIndices[k] = k_;
  127. negated = !negated;
  128. break;
  129. }
  130. }
  131. if (_k === rows) return matrix[k_][k]; // some zero of the type
  132. }
  133. var piv = matrix[k_][k];
  134. var piv_ = k === 0 ? 1 : matrix[rowIndices[k - 1]][k - 1];
  135. for (var i = k + 1; i < rows; i++) {
  136. var i_ = rowIndices[i];
  137. for (var j = k + 1; j < rows; j++) {
  138. matrix[i_][j] = divideScalar(subtract(multiply(matrix[i_][j], piv), multiply(matrix[i_][k], matrix[k_][j])), piv_);
  139. }
  140. }
  141. }
  142. var det = matrix[rowIndices[rows - 1]][rows - 1];
  143. return negated ? unaryMinus(det) : det;
  144. }
  145. }
  146. });
  147. exports.createDet = createDet;