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