simple-squiggle

A restricted subset of Squiggle
Log | Files | Refs | README

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 });