From Jason Turner

[linalg.transp]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp6gybzde3/{from.md → to.md} +258 -0
tmp/tmp6gybzde3/{from.md → to.md} RENAMED
@@ -0,0 +1,258 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### Transpose in-place transformation <a id="linalg.transp">[[linalg.transp]]</a>
2
+
3
+ #### Introduction <a id="linalg.transp.intro">[[linalg.transp.intro]]</a>
4
+
5
+ `layout_transpose` is an `mdspan` layout mapping policy that swaps the
6
+ two indices, extents, and strides of any unique `mdspan` layout mapping
7
+ policy.
8
+
9
+ The `transposed` function takes an `mdspan` representing a matrix, and
10
+ returns a new `mdspan` representing the transpose of the input matrix.
11
+
12
+ #### Exposition-only helpers for `layout_transpose` and `transposed` <a id="linalg.transp.helpers">[[linalg.transp.helpers]]</a>
13
+
14
+ The exposition-only *`transpose-extents`* function takes an `extents`
15
+ object representing the extents of a matrix, and returns a new `extents`
16
+ object representing the extents of the transpose of the matrix.
17
+
18
+ The exposition-only alias template `transpose-extents-t<InputExtents>`
19
+ gives the type of `transpose-extents(e)` for a given `extents` object
20
+ `e` of type `InputExtents`.
21
+
22
+ ``` cpp
23
+ template<class IndexType, size_t InputExtent0, size_t InputExtent1>
24
+ constexpr extents<IndexType, InputExtent1, InputExtent0>
25
+ transpose-extents(const extents<IndexType, InputExtent0, InputExtent1>& in); // exposition only
26
+ ```
27
+
28
+ *Returns:*
29
+ `extents<IndexType, InputExtent1, InputExtent0>(in.extent(1), in.extent(0))`
30
+
31
+ ``` cpp
32
+ template<class InputExtents>
33
+ using transpose-extents-t =
34
+ decltype(transpose-extents(declval<InputExtents>())); // exposition only
35
+ ```
36
+
37
+ #### Class template `layout_transpose` <a id="linalg.transp.layout.transpose">[[linalg.transp.layout.transpose]]</a>
38
+
39
+ `layout_transpose` is an `mdspan` layout mapping policy that swaps the
40
+ two indices, extents, and strides of any `mdspan` layout mapping policy.
41
+
42
+ ``` cpp
43
+ namespace std::linalg {
44
+ template<class Layout>
45
+ class layout_transpose {
46
+ public:
47
+ using nested_layout_type = Layout;
48
+
49
+ template<class Extents>
50
+ struct mapping {
51
+ private:
52
+ using nested-mapping-type =
53
+ Layout::template mapping<transpose-extents-t<Extents>>; // exposition only
54
+
55
+ public:
56
+ using extents_type = Extents;
57
+ using index_type = extents_type::index_type;
58
+ using size_type = extents_type::size_type;
59
+ using rank_type = extents_type::rank_type;
60
+ using layout_type = layout_transpose;
61
+
62
+ constexpr explicit mapping(const nested-mapping-type&);
63
+
64
+ constexpr const extents_type& extents() const noexcept { return extents_; }
65
+
66
+ constexpr index_type required_span_size() const
67
+ { return nested-mapping_.required_span_size(); }
68
+
69
+ template<class Index0, class Index1>
70
+ constexpr index_type operator()(Index0 ind0, Index1 ind1) const
71
+ { return nested-mapping_(ind1, ind0); }
72
+
73
+ constexpr const nested-mapping-type& nested_mapping() const noexcept
74
+ { return nested-mapping_; }
75
+
76
+ static constexpr bool is_always_unique() noexcept
77
+ { return nested-mapping-type::is_always_unique(); }
78
+ static constexpr bool is_always_exhaustive() noexcept
79
+ { return nested-mapping-type::is_always_exhaustive(); }
80
+ static constexpr bool is_always_strided() noexcept
81
+ { return nested-mapping-type::is_always_strided(); }
82
+
83
+ constexpr bool is_unique() const { return nested-mapping_.is_unique(); }
84
+ constexpr bool is_exhaustive() const { return nested-mapping_.is_exhaustive(); }
85
+ constexpr bool is_strided() const { return nested-mapping_.is_strided(); }
86
+
87
+ constexpr index_type stride(size_t r) const;
88
+
89
+ template<class OtherExtents>
90
+ friend constexpr bool operator==(const mapping& x, const mapping<OtherExtents>& y);
91
+
92
+ private:
93
+ nested-mapping-type nested-mapping_; // exposition only
94
+ extents_type extents_; // exposition only
95
+ };
96
+ };
97
+ }
98
+ ```
99
+
100
+ `Layout` shall meet the layout mapping policy requirements
101
+ [[mdspan.layout.policy.reqmts]].
102
+
103
+ *Mandates:*
104
+
105
+ - `Extents` is a specialization of `std::extents`, and
106
+ - `Extents::rank()` equals 2.
107
+
108
+ ``` cpp
109
+ constexpr explicit mapping(const nested-mapping-type& map);
110
+ ```
111
+
112
+ *Effects:*
113
+
114
+ - Initializes *nested-mapping\_* with `map`, and
115
+ - initializes *extents\_* with *`transpose-extents`*`(map.extents())`.
116
+
117
+ ``` cpp
118
+ constexpr index_type stride(size_t r) const;
119
+ ```
120
+
121
+ *Preconditions:*
122
+
123
+ - `is_strided()` is `true`, and
124
+ - `r < 2` is `true`.
125
+
126
+ *Returns:* *`nested-mapping_`*`.stride(r == 0 ? 1 : 0)`
127
+
128
+ ``` cpp
129
+ template<class OtherExtents>
130
+ friend constexpr bool operator==(const mapping& x, const mapping<OtherExtents>& y);
131
+ ```
132
+
133
+ *Constraints:* The expression
134
+ `x.`*`nested-mapping_`*` == y.`*`nested-mapping_`* is well-formed and
135
+ its result is convertible to `bool`.
136
+
137
+ *Returns:* `x.`*`nested-mapping_`*` == y.`*`nested-mapping_`*.
138
+
139
+ #### Function template `transposed` <a id="linalg.transp.transposed">[[linalg.transp.transposed]]</a>
140
+
141
+ The `transposed` function takes a rank-2 `mdspan` representing a matrix,
142
+ and returns a new `mdspan` representing the input matrix’s transpose.
143
+ The input matrix’s data are not modified, and the returned `mdspan`
144
+ accesses the input matrix’s data in place.
145
+
146
+ ``` cpp
147
+ template<class ElementType, class Extents, class Layout, class Accessor>
148
+ constexpr auto transposed(mdspan<ElementType, Extents, Layout, Accessor> a);
149
+ ```
150
+
151
+ *Mandates:* `Extents::rank() == 2` is `true`.
152
+
153
+ Let `ReturnExtents` be *`transpose-extents-t`*`<Extents>`. Let `R` be
154
+ `mdspan<ElementType, ReturnExtents, ReturnLayout, Accessor>`, where
155
+ `ReturnLayout` is:
156
+
157
+ - `layout_right` if `Layout` is `layout_left`;
158
+ - otherwise, `layout_left` if `Layout` is `layout_right`;
159
+ - otherwise, `layout_right_padded<PaddingValue>` if `Layout` is
160
+ `layout_left_padded<PaddingValue>` for some `size_t` value
161
+ `PaddingValue`;
162
+ - otherwise, `layout_left_padded<PaddingValue>` if `Layout` is
163
+ `layout_right_padded<PaddingValue>` for some `size_t` value
164
+ `PaddingValue`;
165
+ - otherwise, `layout_stride` if `Layout` is `layout_stride`;
166
+ - otherwise,
167
+ `layout_blas_packed<OppositeTriangle, OppositeStorageOrder>`, if
168
+ `Layout` is `layout_blas_packed<Triangle, StorageOrder>` for some
169
+ `Triangle` and `StorageOrder`, where
170
+ - `OppositeTriangle` is
171
+ ``` cpp
172
+ conditional_t<is_same_v<Triangle, upper_triangle_t>,
173
+ lower_triangle_t, upper_triangle_t>
174
+ ```
175
+
176
+ and
177
+ - `OppositeStorageOrder` is
178
+ ``` cpp
179
+ conditional_t<is_same_v<StorageOrder, column_major_t>, row_major_t, column_major_t>
180
+ ```
181
+ - otherwise, `NestedLayout` if `Layout` is
182
+ `layout_transpose<NestedLayout>` for some `NestedLayout`;
183
+ - otherwise, `layout_transpose<Layout>`.
184
+
185
+ *Returns:* With `ReturnMapping` being the type
186
+ `typename ReturnLayout::template mapping<ReturnExtents>`:
187
+
188
+ - if `Layout` is `layout_left`, `layout_right`, or a specialization of
189
+ `layout_blas_packed`,
190
+ ``` cpp
191
+ R(a.data_handle(), ReturnMapping(transpose-extents(a.mapping().extents())),
192
+ a.accessor())
193
+ ```
194
+ - otherwise,
195
+ ``` cpp
196
+ R(a.data_handle(), ReturnMapping(transpose-extents(a.mapping().extents()),
197
+ a.mapping().stride(1)), a.accessor())
198
+ ```
199
+
200
+ if `Layout` is `layout_left_padded<PaddingValue>` for some `size_t`
201
+ value `PaddingValue`;
202
+ - otherwise,
203
+ ``` cpp
204
+ R(a.data_handle(), ReturnMapping(transpose-extents(a.mapping().extents()),
205
+ a.mapping().stride(0)), a.accessor())
206
+ ```
207
+
208
+ if `Layout` is `layout_right_padded<PaddingValue>` for some `size_t`
209
+ value `PaddingValue`;
210
+ - otherwise, if `Layout` is `layout_stride`,
211
+ ``` cpp
212
+ R(a.data_handle(), ReturnMapping(transpose-extents(a.mapping().extents()),
213
+ array{a.mapping().stride(1), a.mapping().stride(0)}), a.accessor())
214
+ ```
215
+ - otherwise, if `Layout` is a specialization of `layout_transpose`,
216
+ ``` cpp
217
+ R(a.data_handle(), a.mapping().nested_mapping(), a.accessor())
218
+ ```
219
+ - otherwise,
220
+ ``` cpp
221
+ R(a.data_handle(), ReturnMapping(a.mapping()), a.accessor())
222
+ ```
223
+
224
+ [*Example 1*:
225
+
226
+ ``` cpp
227
+ void test_transposed(mdspan<double, extents<size_t, 3, 4>> a) {
228
+ const auto num_rows = a.extent(0);
229
+ const auto num_cols = a.extent(1);
230
+
231
+ auto a_t = transposed(a);
232
+ assert(num_rows == a_t.extent(1));
233
+ assert(num_cols == a_t.extent(0));
234
+ assert(a.stride(0) == a_t.stride(1));
235
+ assert(a.stride(1) == a_t.stride(0));
236
+
237
+ for (size_t row = 0; row < num_rows; ++row) {
238
+ for (size_t col = 0; col < num_rows; ++col) {
239
+ assert(a[row, col] == a_t[col, row]);
240
+ }
241
+ }
242
+
243
+ auto a_t_t = transposed(a_t);
244
+ assert(num_rows == a_t_t.extent(0));
245
+ assert(num_cols == a_t_t.extent(1));
246
+ assert(a.stride(0) == a_t_t.stride(0));
247
+ assert(a.stride(1) == a_t_t.stride(1));
248
+
249
+ for (size_t row = 0; row < num_rows; ++row) {
250
+ for (size_t col = 0; col < num_rows; ++col) {
251
+ assert(a[row, col] == a_t_t[row, col]);
252
+ }
253
+ }
254
+ }
255
+ ```
256
+
257
+ — *end example*]
258
+