From Jason Turner

[linalg.helpers]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp1vsrf1dj/{from.md → to.md} +242 -0
tmp/tmp1vsrf1dj/{from.md → to.md} RENAMED
@@ -0,0 +1,242 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### Exposition-only helpers <a id="linalg.helpers">[[linalg.helpers]]</a>
2
+
3
+ #### *`abs-if-needed`* <a id="linalg.helpers.abs">[[linalg.helpers.abs]]</a>
4
+
5
+ The name *`abs-if-needed`* denotes an exposition-only function object.
6
+ The expression `abs-if-needed(E)` for a subexpression `E` whose type is
7
+ `T` is expression-equivalent to:
8
+
9
+ - `E` if `T` is an unsigned integer;
10
+ - otherwise, `std::abs(E)` if `T` is an arithmetic type,
11
+ - otherwise, `abs(E)`, if that expression is valid, with overload
12
+ resolution performed in a context that includes the declaration
13
+ ``` cpp
14
+ template<class U> U abs(U) = delete;
15
+ ```
16
+
17
+ If the function selected by overload resolution does not return the
18
+ absolute value of its input, the program is ill-formed, no diagnostic
19
+ required.
20
+
21
+ #### *`conj-if-needed`* <a id="linalg.helpers.conj">[[linalg.helpers.conj]]</a>
22
+
23
+ The name *`conj-if-needed`* denotes an exposition-only function object.
24
+ The expression `conj-if-needed(E)` for a subexpression `E` whose type is
25
+ `T` is expression-equivalent to:
26
+
27
+ - `conj(E)`, if `T` is not an arithmetic type and the expression
28
+ `conj(E)` is valid, with overload resolution performed in a context
29
+ that includes the declaration
30
+ ``` cpp
31
+ template<class U> U conj(const U&) = delete;
32
+ ```
33
+
34
+ If the function selected by overload resolution does not return the
35
+ complex conjugate of its input, the program is ill-formed, no
36
+ diagnostic required;
37
+ - otherwise, `E`.
38
+
39
+ #### *`real-if-needed`* <a id="linalg.helpers.real">[[linalg.helpers.real]]</a>
40
+
41
+ The name *`real-if-needed`* denotes an exposition-only function object.
42
+ The expression `real-if-needed(E)` for a subexpression `E` whose type is
43
+ `T` is expression-equivalent to:
44
+
45
+ - `real(E)`, if `T` is not an arithmetic type and the expression
46
+ `real(E)` is valid, with overload resolution performed in a context
47
+ that includes the declaration
48
+ ``` cpp
49
+ template<class U> U real(const U&) = delete;
50
+ ```
51
+
52
+ If the function selected by overload resolution does not return the
53
+ real part of its input, the program is ill-formed, no diagnostic
54
+ required;
55
+ - otherwise, `E`.
56
+
57
+ #### *`imag-if-needed`* <a id="linalg.helpers.imag">[[linalg.helpers.imag]]</a>
58
+
59
+ The name *`imag-if-needed`* denotes an exposition-only function object.
60
+ The expression `imag-if-needed(E)` for a subexpression `E` whose type is
61
+ `T` is expression-equivalent to:
62
+
63
+ - `imag(E)`, if `T` is not an arithmetic type and the expression
64
+ `imag(E)` is valid, with overload resolution performed in a context
65
+ that includes the declaration
66
+ ``` cpp
67
+ template<class U> U imag(const U&) = delete;
68
+ ```
69
+
70
+ If the function selected by overload resolution does not return the
71
+ imaginary part of its input, the program is ill-formed, no diagnostic
72
+ required;
73
+ - otherwise, `((void)E, T{})`.
74
+
75
+ #### Argument concepts <a id="linalg.helpers.concepts">[[linalg.helpers.concepts]]</a>
76
+
77
+ The exposition-only concepts defined in this section constrain the
78
+ algorithms in [[linalg]].
79
+
80
+ ``` cpp
81
+ template<class T>
82
+ constexpr bool is-mdspan = false;
83
+
84
+ template<class ElementType, class Extents, class Layout, class Accessor>
85
+ constexpr bool is-mdspan<mdspan<ElementType, Extents, Layout, Accessor>> = true;
86
+
87
+ template<class T>
88
+ concept in-vector =
89
+ is-mdspan<T> && T::rank() == 1;
90
+
91
+ template<class T>
92
+ concept out-vector =
93
+ is-mdspan<T> && T::rank() == 1 &&
94
+ is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();
95
+
96
+ template<class T>
97
+ concept inout-vector =
98
+ is-mdspan<T> && T::rank() == 1 &&
99
+ is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();
100
+
101
+ template<class T>
102
+ concept in-matrix =
103
+ is-mdspan<T> && T::rank() == 2;
104
+
105
+ template<class T>
106
+ concept out-matrix =
107
+ is-mdspan<T> && T::rank() == 2 &&
108
+ is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();
109
+
110
+ template<class T>
111
+ concept inout-matrix =
112
+ is-mdspan<T> && T::rank() == 2 &&
113
+ is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();
114
+
115
+ template<class T>
116
+ constexpr bool is-layout-blas-packed = false; // exposition only
117
+
118
+ template<class Triangle, class StorageOrder>
119
+ constexpr bool is-layout-blas-packed<layout_blas_packed<Triangle, StorageOrder>> = true;
120
+
121
+ template<class T>
122
+ concept possibly-packed-inout-matrix =
123
+ is-mdspan<T> && T::rank() == 2 &&
124
+ is_assignable_v<typename T::reference, typename T::element_type> &&
125
+ (T::is_always_unique() || is-layout-blas-packed<typename T::layout_type>);
126
+
127
+ template<class T>
128
+ concept in-object =
129
+ is-mdspan<T> && (T::rank() == 1 || T::rank() == 2);
130
+
131
+ template<class T>
132
+ concept out-object =
133
+ is-mdspan<T> && (T::rank() == 1 || T::rank() == 2) &&
134
+ is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();
135
+
136
+ template<class T>
137
+ concept inout-object =
138
+ is-mdspan<T> && (T::rank() == 1 || T::rank() == 2) &&
139
+ is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();
140
+ ```
141
+
142
+ If a function in [[linalg]] accesses the elements of a parameter
143
+ constrained by `in-vector`, `in-matrix`, or `in-object`, those accesses
144
+ will not modify the elements.
145
+
146
+ Unless explicitly permitted, any `inout-vector`, `inout-matrix`,
147
+ `inout-object`, `out-vector`, `out-matrix`, `out-object`, or
148
+ `possibly-packed-inout-matrix` parameter of a function in [[linalg]]
149
+ shall not overlap any other `mdspan` parameter of the function.
150
+
151
+ #### Mandates <a id="linalg.helpers.mandates">[[linalg.helpers.mandates]]</a>
152
+
153
+ [*Note 1*: These exposition-only helper functions use the less
154
+ constraining input concepts even for the output arguments, because the
155
+ additional constraint for assignability of elements is not necessary,
156
+ and they are sometimes used in a context where the third argument is an
157
+ input type too. — *end note*]
158
+
159
+ ``` cpp
160
+ template<class MDS1, class MDS2>
161
+ requires(is-mdspan<MDS1> && is-mdspan<MDS2>)
162
+ constexpr
163
+ bool compatible-static-extents(size_t r1, size_t r2) { // exposition only
164
+ return MDS1::static_extent(r1) == dynamic_extent ||
165
+ MDS2::static_extent(r2) == dynamic_extent ||
166
+ MDS1::static_extent(r1) == MDS2::static_extent(r2);
167
+ }
168
+
169
+ template<in-vector In1, in-vector In2, in-vector Out>
170
+ constexpr bool possibly-addable() { // exposition only
171
+ return compatible-static-extents<Out, In1>(0, 0) &&
172
+ compatible-static-extents<Out, In2>(0, 0) &&
173
+ compatible-static-extents<In1, In2>(0, 0);
174
+ }
175
+
176
+ template<in-matrix In1, in-matrix In2, in-matrix Out>
177
+ constexpr bool possibly-addable() { // exposition only
178
+ return compatible-static-extents<Out, In1>(0, 0) &&
179
+ compatible-static-extents<Out, In1>(1, 1) &&
180
+ compatible-static-extents<Out, In2>(0, 0) &&
181
+ compatible-static-extents<Out, In2>(1, 1) &&
182
+ compatible-static-extents<In1, In2>(0, 0) &&
183
+ compatible-static-extents<In1, In2>(1, 1);
184
+ }
185
+
186
+ template<in-matrix InMat, in-vector InVec, in-vector OutVec>
187
+ constexpr bool possibly-multipliable() { // exposition only
188
+ return compatible-static-extents<OutVec, InMat>(0, 0) &&
189
+ compatible-static-extents<InMat, InVec>(1, 0);
190
+ }
191
+
192
+ template<in-vector InVec, in-matrix InMat, in-vector OutVec>
193
+ constexpr bool possibly-multipliable() { // exposition only
194
+ return compatible-static-extents<OutVec, InMat>(0, 1) &&
195
+ compatible-static-extents<InMat, InVec>(0, 0);
196
+ }
197
+
198
+ template<in-matrix InMat1, in-matrix InMat2, in-matrix OutMat>
199
+ constexpr bool possibly-multipliable() { // exposition only
200
+ return compatible-static-extents<OutMat, InMat1>(0, 0) &&
201
+ compatible-static-extents<OutMat, InMat2>(1, 1) &&
202
+ compatible-static-extents<InMat1, InMat2>(1, 0);
203
+ }
204
+ ```
205
+
206
+ #### Preconditions <a id="linalg.helpers.precond">[[linalg.helpers.precond]]</a>
207
+
208
+ [*Note 1*: These exposition-only helper functions use the less
209
+ constraining input concepts even for the output arguments, because the
210
+ additional constraint for assignability of elements is not necessary,
211
+ and they are sometimes used in a context where the third argument is an
212
+ input type too. — *end note*]
213
+
214
+ ``` cpp
215
+ constexpr bool addable( // exposition only
216
+ const in-vector auto& in1, const in-vector auto& in2, const in-vector auto& out) {
217
+ return out.extent(0) == in1.extent(0) && out.extent(0) == in2.extent(0);
218
+ }
219
+
220
+ constexpr bool addable( // exposition only
221
+ const in-matrix auto& in1, const in-matrix auto& in2, const in-matrix auto& out) {
222
+ return out.extent(0) == in1.extent(0) && out.extent(1) == in1.extent(1) &&
223
+ out.extent(0) == in2.extent(0) && out.extent(1) == in2.extent(1);
224
+ }
225
+
226
+ constexpr bool multipliable( // exposition only
227
+ const in-matrix auto& in_mat, const in-vector auto& in_vec, const in-vector auto& out_vec) {
228
+ return out_vec.extent(0) == in_mat.extent(0) && in_mat.extent(1) == in_vec.extent(0);
229
+ }
230
+
231
+ constexpr bool multipliable( // exposition only
232
+ const in-vector auto& in_vec, const in-matrix auto& in_mat, const in-vector auto& out_vec) {
233
+ return out_vec.extent(0) == in_mat.extent(1) && in_mat.extent(0) == in_vec.extent(0);
234
+ }
235
+
236
+ constexpr bool multipliable( // exposition only
237
+ const in-matrix auto& in_mat1, const in-matrix auto& in_mat2, const in-matrix auto& out_mat) {
238
+ return out_mat.extent(0) == in_mat1.extent(0) && out_mat.extent(1) == in_mat2.extent(1) &&
239
+ in_mat1.extent(1) == in_mat2.extent(0);
240
+ }
241
+ ```
242
+