diag.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. import { isMatrix } from '../../utils/is.js';
  2. import { arraySize } from '../../utils/array.js';
  3. import { isInteger } from '../../utils/number.js';
  4. import { factory } from '../../utils/factory.js';
  5. var name = 'diag';
  6. var dependencies = ['typed', 'matrix', 'DenseMatrix', 'SparseMatrix'];
  7. export var createDiag = /* #__PURE__ */factory(name, dependencies, _ref => {
  8. var {
  9. typed,
  10. matrix,
  11. DenseMatrix,
  12. SparseMatrix
  13. } = _ref;
  14. /**
  15. * Create a diagonal matrix or retrieve the diagonal of a matrix
  16. *
  17. * When `x` is a vector, a matrix with vector `x` on the diagonal will be returned.
  18. * When `x` is a two dimensional matrix, the matrixes `k`th diagonal will be returned as vector.
  19. * When k is positive, the values are placed on the super diagonal.
  20. * When k is negative, the values are placed on the sub diagonal.
  21. *
  22. * Syntax:
  23. *
  24. * math.diag(X)
  25. * math.diag(X, format)
  26. * math.diag(X, k)
  27. * math.diag(X, k, format)
  28. *
  29. * Examples:
  30. *
  31. * // create a diagonal matrix
  32. * math.diag([1, 2, 3]) // returns [[1, 0, 0], [0, 2, 0], [0, 0, 3]]
  33. * math.diag([1, 2, 3], 1) // returns [[0, 1, 0, 0], [0, 0, 2, 0], [0, 0, 0, 3]]
  34. * math.diag([1, 2, 3], -1) // returns [[0, 0, 0], [1, 0, 0], [0, 2, 0], [0, 0, 3]]
  35. *
  36. * // retrieve the diagonal from a matrix
  37. * const a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
  38. * math.diag(a) // returns [1, 5, 9]
  39. *
  40. * See also:
  41. *
  42. * ones, zeros, identity
  43. *
  44. * @param {Matrix | Array} x A two dimensional matrix or a vector
  45. * @param {number | BigNumber} [k=0] The diagonal where the vector will be filled
  46. * in or retrieved.
  47. * @param {string} [format='dense'] The matrix storage format.
  48. *
  49. * @returns {Matrix | Array} Diagonal matrix from input vector, or diagonal from input matrix.
  50. */
  51. return typed(name, {
  52. // FIXME: simplify this huge amount of signatures as soon as typed-function supports optional arguments
  53. Array: function Array(x) {
  54. return _diag(x, 0, arraySize(x), null);
  55. },
  56. 'Array, number': function ArrayNumber(x, k) {
  57. return _diag(x, k, arraySize(x), null);
  58. },
  59. 'Array, BigNumber': function ArrayBigNumber(x, k) {
  60. return _diag(x, k.toNumber(), arraySize(x), null);
  61. },
  62. 'Array, string': function ArrayString(x, format) {
  63. return _diag(x, 0, arraySize(x), format);
  64. },
  65. 'Array, number, string': function ArrayNumberString(x, k, format) {
  66. return _diag(x, k, arraySize(x), format);
  67. },
  68. 'Array, BigNumber, string': function ArrayBigNumberString(x, k, format) {
  69. return _diag(x, k.toNumber(), arraySize(x), format);
  70. },
  71. Matrix: function Matrix(x) {
  72. return _diag(x, 0, x.size(), x.storage());
  73. },
  74. 'Matrix, number': function MatrixNumber(x, k) {
  75. return _diag(x, k, x.size(), x.storage());
  76. },
  77. 'Matrix, BigNumber': function MatrixBigNumber(x, k) {
  78. return _diag(x, k.toNumber(), x.size(), x.storage());
  79. },
  80. 'Matrix, string': function MatrixString(x, format) {
  81. return _diag(x, 0, x.size(), format);
  82. },
  83. 'Matrix, number, string': function MatrixNumberString(x, k, format) {
  84. return _diag(x, k, x.size(), format);
  85. },
  86. 'Matrix, BigNumber, string': function MatrixBigNumberString(x, k, format) {
  87. return _diag(x, k.toNumber(), x.size(), format);
  88. }
  89. });
  90. /**
  91. * Creeate diagonal matrix from a vector or vice versa
  92. * @param {Array | Matrix} x
  93. * @param {number} k
  94. * @param {string} format Storage format for matrix. If null,
  95. * an Array is returned
  96. * @returns {Array | Matrix}
  97. * @private
  98. */
  99. function _diag(x, k, size, format) {
  100. if (!isInteger(k)) {
  101. throw new TypeError('Second parameter in function diag must be an integer');
  102. }
  103. var kSuper = k > 0 ? k : 0;
  104. var kSub = k < 0 ? -k : 0;
  105. // check dimensions
  106. switch (size.length) {
  107. case 1:
  108. return _createDiagonalMatrix(x, k, format, size[0], kSub, kSuper);
  109. case 2:
  110. return _getDiagonal(x, k, format, size, kSub, kSuper);
  111. }
  112. throw new RangeError('Matrix for function diag must be 2 dimensional');
  113. }
  114. function _createDiagonalMatrix(x, k, format, l, kSub, kSuper) {
  115. // matrix size
  116. var ms = [l + kSub, l + kSuper];
  117. if (format && format !== 'sparse' && format !== 'dense') {
  118. throw new TypeError("Unknown matrix type ".concat(format, "\""));
  119. }
  120. // create diagonal matrix
  121. var m = format === 'sparse' ? SparseMatrix.diagonal(ms, x, k) : DenseMatrix.diagonal(ms, x, k);
  122. // check we need to return a matrix
  123. return format !== null ? m : m.valueOf();
  124. }
  125. function _getDiagonal(x, k, format, s, kSub, kSuper) {
  126. // check x is a Matrix
  127. if (isMatrix(x)) {
  128. // get diagonal matrix
  129. var dm = x.diagonal(k);
  130. // check we need to return a matrix
  131. if (format !== null) {
  132. // check we need to change matrix format
  133. if (format !== dm.storage()) {
  134. return matrix(dm, format);
  135. }
  136. return dm;
  137. }
  138. return dm.valueOf();
  139. }
  140. // vector size
  141. var n = Math.min(s[0] - kSub, s[1] - kSuper);
  142. // diagonal values
  143. var vector = [];
  144. // loop diagonal
  145. for (var i = 0; i < n; i++) {
  146. vector[i] = x[i + kSub][i + kSuper];
  147. }
  148. // check we need to return a matrix
  149. return format !== null ? matrix(vector) : vector;
  150. }
  151. });