UNPKG

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