1 | 'use strict'
|
2 |
|
3 | const clone = require('../../utils/object').clone
|
4 | const format = require('../../utils/string').format
|
5 |
|
6 | function 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 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 | const transpose = typed('transpose', {
|
37 |
|
38 | 'Array': function (x) {
|
39 |
|
40 | return transpose(matrix(x)).valueOf()
|
41 | },
|
42 |
|
43 | 'Matrix': function (x) {
|
44 |
|
45 | const size = x.size()
|
46 |
|
47 |
|
48 | let c
|
49 |
|
50 |
|
51 | switch (size.length) {
|
52 | case 1:
|
53 |
|
54 | c = x.clone()
|
55 | break
|
56 |
|
57 | case 2:
|
58 |
|
59 | const rows = size[0]
|
60 | const columns = size[1]
|
61 |
|
62 |
|
63 | if (columns === 0) {
|
64 |
|
65 | throw new RangeError('Cannot transpose a 2D matrix with no columns (size: ' + format(size) + ')')
|
66 | }
|
67 |
|
68 |
|
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 |
|
81 | throw new RangeError('Matrix must be a vector or two dimensional (size: ' + format(this._size) + ')')
|
82 | }
|
83 | return c
|
84 | },
|
85 |
|
86 |
|
87 | 'any': function (x) {
|
88 | return clone(x)
|
89 | }
|
90 | })
|
91 |
|
92 | function _denseTranspose (m, rows, columns) {
|
93 |
|
94 | const data = m._data
|
95 |
|
96 | const transposed = []
|
97 | let transposedRow
|
98 |
|
99 | for (let j = 0; j < columns; j++) {
|
100 |
|
101 | transposedRow = transposed[j] = []
|
102 |
|
103 | for (let i = 0; i < rows; i++) {
|
104 |
|
105 | transposedRow[i] = clone(data[i][j])
|
106 | }
|
107 | }
|
108 |
|
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 |
|
118 | const values = m._values
|
119 | const index = m._index
|
120 | const ptr = m._ptr
|
121 |
|
122 | const cvalues = values ? [] : undefined
|
123 | const cindex = []
|
124 | const cptr = []
|
125 |
|
126 | const w = []
|
127 | for (let x = 0; x < rows; x++) { w[x] = 0 }
|
128 |
|
129 | let p, l, j
|
130 |
|
131 | for (p = 0, l = index.length; p < l; p++) {
|
132 |
|
133 | w[index[p]]++
|
134 | }
|
135 |
|
136 | let sum = 0
|
137 |
|
138 | for (let i = 0; i < rows; i++) {
|
139 |
|
140 | cptr.push(sum)
|
141 |
|
142 | sum += w[i]
|
143 |
|
144 | w[i] = cptr[i]
|
145 | }
|
146 |
|
147 | cptr.push(sum)
|
148 |
|
149 | for (j = 0; j < columns; j++) {
|
150 |
|
151 | for (let k0 = ptr[j], k1 = ptr[j + 1], k = k0; k < k1; k++) {
|
152 |
|
153 | const q = w[index[k]]++
|
154 |
|
155 | cindex[q] = j
|
156 |
|
157 | if (values) { cvalues[q] = clone(values[k]) }
|
158 | }
|
159 | }
|
160 |
|
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 |
|
175 | exports.name = 'transpose'
|
176 | exports.factory = factory
|