simple-squiggle

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

transpose.js (4243B)


      1 import { clone } from '../../utils/object.js';
      2 import { format } from '../../utils/string.js';
      3 import { factory } from '../../utils/factory.js';
      4 var name = 'transpose';
      5 var dependencies = ['typed', 'matrix'];
      6 export var createTranspose = /* #__PURE__ */factory(name, dependencies, _ref => {
      7   var {
      8     typed,
      9     matrix
     10   } = _ref;
     11 
     12   /**
     13    * Transpose a matrix. All values of the matrix are reflected over its
     14    * main diagonal. Only applicable to two dimensional matrices containing
     15    * a vector (i.e. having size `[1,n]` or `[n,1]`). One dimensional
     16    * vectors and scalars return the input unchanged.
     17    *
     18    * Syntax:
     19    *
     20    *     math.transpose(x)
     21    *
     22    * Examples:
     23    *
     24    *     const A = [[1, 2, 3], [4, 5, 6]]
     25    *     math.transpose(A)               // returns [[1, 4], [2, 5], [3, 6]]
     26    *
     27    * See also:
     28    *
     29    *     diag, inv, subset, squeeze
     30    *
     31    * @param {Array | Matrix} x  Matrix to be transposed
     32    * @return {Array | Matrix}   The transposed matrix
     33    */
     34   return typed('transpose', {
     35     Array: function Array(x) {
     36       // use dense matrix implementation
     37       return this(matrix(x)).valueOf();
     38     },
     39     Matrix: function Matrix(x) {
     40       // matrix size
     41       var size = x.size(); // result
     42 
     43       var c; // process dimensions
     44 
     45       switch (size.length) {
     46         case 1:
     47           // vector
     48           c = x.clone();
     49           break;
     50 
     51         case 2:
     52           {
     53             // rows and columns
     54             var rows = size[0];
     55             var columns = size[1]; // check columns
     56 
     57             if (columns === 0) {
     58               // throw exception
     59               throw new RangeError('Cannot transpose a 2D matrix with no columns (size: ' + format(size) + ')');
     60             } // process storage format
     61 
     62 
     63             switch (x.storage()) {
     64               case 'dense':
     65                 c = _denseTranspose(x, rows, columns);
     66                 break;
     67 
     68               case 'sparse':
     69                 c = _sparseTranspose(x, rows, columns);
     70                 break;
     71             }
     72           }
     73           break;
     74 
     75         default:
     76           // multi dimensional
     77           throw new RangeError('Matrix must be a vector or two dimensional (size: ' + format(this._size) + ')');
     78       }
     79 
     80       return c;
     81     },
     82     // scalars
     83     any: function any(x) {
     84       return clone(x);
     85     }
     86   });
     87 
     88   function _denseTranspose(m, rows, columns) {
     89     // matrix array
     90     var data = m._data; // transposed matrix data
     91 
     92     var transposed = [];
     93     var transposedRow; // loop columns
     94 
     95     for (var j = 0; j < columns; j++) {
     96       // initialize row
     97       transposedRow = transposed[j] = []; // loop rows
     98 
     99       for (var i = 0; i < rows; i++) {
    100         // set data
    101         transposedRow[i] = clone(data[i][j]);
    102       }
    103     } // return matrix
    104 
    105 
    106     return m.createDenseMatrix({
    107       data: transposed,
    108       size: [columns, rows],
    109       datatype: m._datatype
    110     });
    111   }
    112 
    113   function _sparseTranspose(m, rows, columns) {
    114     // matrix arrays
    115     var values = m._values;
    116     var index = m._index;
    117     var ptr = m._ptr; // result matrices
    118 
    119     var cvalues = values ? [] : undefined;
    120     var cindex = [];
    121     var cptr = []; // row counts
    122 
    123     var w = [];
    124 
    125     for (var x = 0; x < rows; x++) {
    126       w[x] = 0;
    127     } // vars
    128 
    129 
    130     var p, l, j; // loop values in matrix
    131 
    132     for (p = 0, l = index.length; p < l; p++) {
    133       // number of values in row
    134       w[index[p]]++;
    135     } // cumulative sum
    136 
    137 
    138     var sum = 0; // initialize cptr with the cummulative sum of row counts
    139 
    140     for (var i = 0; i < rows; i++) {
    141       // update cptr
    142       cptr.push(sum); // update sum
    143 
    144       sum += w[i]; // update w
    145 
    146       w[i] = cptr[i];
    147     } // update cptr
    148 
    149 
    150     cptr.push(sum); // loop columns
    151 
    152     for (j = 0; j < columns; j++) {
    153       // values & index in column
    154       for (var k0 = ptr[j], k1 = ptr[j + 1], k = k0; k < k1; k++) {
    155         // C values & index
    156         var q = w[index[k]]++; // C[j, i] = A[i, j]
    157 
    158         cindex[q] = j; // check we need to process values (pattern matrix)
    159 
    160         if (values) {
    161           cvalues[q] = clone(values[k]);
    162         }
    163       }
    164     } // return matrix
    165 
    166 
    167     return m.createSparseMatrix({
    168       values: cvalues,
    169       index: cindex,
    170       ptr: cptr,
    171       size: [columns, rows],
    172       datatype: m._datatype
    173     });
    174   }
    175 });