From Jason Turner

[linalg.algs.blas1]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp9eiur0hi/{from.md → to.md} +617 -0
tmp/tmp9eiur0hi/{from.md → to.md} RENAMED
@@ -0,0 +1,617 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### BLAS 1 algorithms <a id="linalg.algs.blas1">[[linalg.algs.blas1]]</a>
2
+
3
+ #### Complexity <a id="linalg.algs.blas1.complexity">[[linalg.algs.blas1.complexity]]</a>
4
+
5
+ *Complexity:* All algorithms in [[linalg.algs.blas1]] with `mdspan`
6
+ parameters perform a count of `mdspan` array accesses and arithmetic
7
+ operations that is linear in the maximum product of extents of any
8
+ `mdspan` parameter.
9
+
10
+ #### Givens rotations <a id="linalg.algs.blas1.givens">[[linalg.algs.blas1.givens]]</a>
11
+
12
+ ##### Compute Givens rotation <a id="linalg.algs.blas1.givens.lartg">[[linalg.algs.blas1.givens.lartg]]</a>
13
+
14
+ ``` cpp
15
+ template<class Real>
16
+ setup_givens_rotation_result<Real> setup_givens_rotation(Real a, Real b) noexcept;
17
+
18
+ template<class Real>
19
+ setup_givens_rotation_result<complex<Real>>
20
+ setup_givens_rotation(complex<Real> a, complex<Real> b) noexcept;
21
+ ```
22
+
23
+ These functions compute the Givens plane rotation represented by the two
24
+ values c and s such that the 2 x 2 system of equations
25
+ $$\left[ \begin{matrix}
26
+ c & s \\
27
+ -\overline{s} & c \\
28
+ \end{matrix} \right]
29
+ \cdot
30
+ \left[ \begin{matrix}
31
+ a \\
32
+ b \\
33
+ \end{matrix} \right]
34
+ =
35
+ \left[ \begin{matrix}
36
+ r \\
37
+ 0 \\
38
+ \end{matrix} \right]$$
39
+
40
+ holds, where c is always a real scalar, and c² + |s|^2 = 1. That is, c
41
+ and s represent a 2 x 2 matrix, that when multiplied by the right by the
42
+ input vector whose components are a and b, produces a result vector
43
+ whose first component r is the Euclidean norm of the input vector, and
44
+ whose second component is zero.
45
+
46
+ [*Note 1*: These functions correspond to the LAPACK function
47
+ `xLARTG`. — *end note*]
48
+
49
+ *Returns:* `c, s, r`, where `c` and `s` form the Givens plane rotation
50
+ corresponding to the input `a` and `b`, and `r` is the Euclidean norm of
51
+ the two-component vector formed by `a` and `b`.
52
+
53
+ ##### Apply a computed Givens rotation to vectors <a id="linalg.algs.blas1.givens.rot">[[linalg.algs.blas1.givens.rot]]</a>
54
+
55
+ ``` cpp
56
+ template<inout-vector InOutVec1, inout-vector InOutVec2, class Real>
57
+ void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, Real s);
58
+ template<class ExecutionPolicy, inout-vector InOutVec1, inout-vector InOutVec2, class Real>
59
+ void apply_givens_rotation(ExecutionPolicy&& exec,
60
+ InOutVec1 x, InOutVec2 y, Real c, Real s);
61
+ template<inout-vector InOutVec1, inout-vector InOutVec2, class Real>
62
+ void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, complex<Real> s);
63
+ template<class ExecutionPolicy, inout-vector InOutVec1, inout-vector InOutVec2, class Real>
64
+ void apply_givens_rotation(ExecutionPolicy&& exec,
65
+ InOutVec1 x, InOutVec2 y, Real c, complex<Real> s);
66
+ ```
67
+
68
+ [*Note 2*: These functions correspond to the BLAS function
69
+ `xROT`. — *end note*]
70
+
71
+ *Mandates:* *`compatible-static-extents`*`<InOutVec1, InOutVec2>(0, 0)`
72
+ is `true`.
73
+
74
+ *Preconditions:* `x.extent(0)` equals `y.extent(0)`.
75
+
76
+ *Effects:* Applies the plane rotation specified by `c` and `s` to the
77
+ input vectors `x` and `y`, as if the rotation were a 2 x 2 matrix and
78
+ the input vectors were successive rows of a matrix with two rows.
79
+
80
+ #### Swap matrix or vector elements <a id="linalg.algs.blas1.swap">[[linalg.algs.blas1.swap]]</a>
81
+
82
+ ``` cpp
83
+ template<inout-object InOutObj1, inout-object InOutObj2>
84
+ void swap_elements(InOutObj1 x, InOutObj2 y);
85
+ template<class ExecutionPolicy, inout-object InOutObj1, inout-object InOutObj2>
86
+ void swap_elements(ExecutionPolicy&& exec, InOutObj1 x, InOutObj2 y);
87
+ ```
88
+
89
+ [*Note 1*: These functions correspond to the BLAS function
90
+ `xSWAP`. — *end note*]
91
+
92
+ *Constraints:* `x.rank()` equals `y.rank()`.
93
+
94
+ *Mandates:* For all `r` in the range [0, `x.rank()`),
95
+
96
+ ``` cpp
97
+ compatible-static-extents<InOutObj1, InOutObj2>(r, r)
98
+ ```
99
+
100
+ is `true`.
101
+
102
+ *Preconditions:* `x.extents()` equals `y.extents()`.
103
+
104
+ *Effects:* Swaps all corresponding elements of `x` and `y`.
105
+
106
+ #### Multiply the elements of an object in place by a scalar <a id="linalg.algs.blas1.scal">[[linalg.algs.blas1.scal]]</a>
107
+
108
+ ``` cpp
109
+ template<class Scalar, inout-object InOutObj>
110
+ void scale(Scalar alpha, InOutObj x);
111
+ template<class ExecutionPolicy, class Scalar, inout-object InOutObj>
112
+ void scale(ExecutionPolicy&& exec, Scalar alpha, InOutObj x);
113
+ ```
114
+
115
+ [*Note 1*: These functions correspond to the BLAS function
116
+ `xSCAL`. — *end note*]
117
+
118
+ *Effects:* Overwrites x with the result of computing the elementwise
119
+ multiplication α x, where the scalar α is `alpha`.
120
+
121
+ #### Copy elements of one matrix or vector into another <a id="linalg.algs.blas1.copy">[[linalg.algs.blas1.copy]]</a>
122
+
123
+ ``` cpp
124
+ template<in-object InObj, out-object OutObj>
125
+ void copy(InObj x, OutObj y);
126
+ template<class ExecutionPolicy, in-object InObj, out-object OutObj>
127
+ void copy(ExecutionPolicy&& exec, InObj x, OutObj y);
128
+ ```
129
+
130
+ [*Note 1*: These functions correspond to the BLAS function
131
+ `xCOPY`. — *end note*]
132
+
133
+ *Constraints:* `x.rank()` equals `y.rank()`.
134
+
135
+ *Mandates:* For all `r` in the range [ 0, `x.rank()`),
136
+
137
+ ``` cpp
138
+ compatible-static-extents<InObj, OutObj>(r, r)
139
+ ```
140
+
141
+ is `true`.
142
+
143
+ *Preconditions:* `x.extents()` equals `y.extents()`.
144
+
145
+ *Effects:* Assigns each element of x to the corresponding element of y.
146
+
147
+ #### Add vectors or matrices elementwise <a id="linalg.algs.blas1.add">[[linalg.algs.blas1.add]]</a>
148
+
149
+ ``` cpp
150
+ template<in-object InObj1, in-object InObj2, out-object OutObj>
151
+ void add(InObj1 x, InObj2 y, OutObj z);
152
+ template<class ExecutionPolicy, in-object InObj1, in-object InObj2, out-object OutObj>
153
+ void add(ExecutionPolicy&& exec,
154
+ InObj1 x, InObj2 y, OutObj z);
155
+ ```
156
+
157
+ [*Note 1*: These functions correspond to the BLAS function
158
+ `xAXPY`. — *end note*]
159
+
160
+ *Constraints:* `x.rank()`, `y.rank()`, and `z.rank()` are all equal.
161
+
162
+ *Mandates:* *`possibly-addable`*`<InObj1, InObj2, OutObj>()` is `true`.
163
+
164
+ *Preconditions:* *`addable`*`(x,y,z)` is `true`.
165
+
166
+ *Effects:* Computes z = x + y.
167
+
168
+ *Remarks:* `z` may alias `x` or `y`.
169
+
170
+ #### Dot product of two vectors <a id="linalg.algs.blas1.dot">[[linalg.algs.blas1.dot]]</a>
171
+
172
+ [*Note 1*: The functions in this section correspond to the BLAS
173
+ functions `xDOT`, `xDOTU`, and `xDOTC`. — *end note*]
174
+
175
+ The following elements apply to all functions in
176
+ [[linalg.algs.blas1.dot]].
177
+
178
+ *Mandates:* `compatible-static-extents<InVec1, InVec2>(0, 0)` is `true`.
179
+
180
+ *Preconditions:* `v1.extent(0)` equals `v2.extent(0)`.
181
+
182
+ ``` cpp
183
+ template<in-vector InVec1, in-vector InVec2, class Scalar>
184
+ Scalar dot(InVec1 v1, InVec2 v2, Scalar init);
185
+ template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2, class Scalar>
186
+ Scalar dot(ExecutionPolicy&& exec,
187
+ InVec1 v1, InVec2 v2, Scalar init);
188
+ ```
189
+
190
+ These functions compute a non-conjugated dot product with an explicitly
191
+ specified result type.
192
+
193
+ *Returns:* Let `N` be `v1.extent(0)`.
194
+
195
+ - `init` if `N` is zero;
196
+ - otherwise, *GENERALIZED_SUM*(plus\<\>(), init, v1\[0\]\*v2\[0\], …,
197
+ v1\[N-1\]\*v2\[N-1\]).
198
+
199
+ *Remarks:* If `InVec1::value_type`, `InVec2::value_type`, and `Scalar`
200
+ are all floating-point types or specializations of `complex`, and if
201
+ `Scalar` has higher precision than `InVec1::value_type` or
202
+ `InVec2::value_type`, then intermediate terms in the sum use `Scalar`’s
203
+ precision or greater.
204
+
205
+ ``` cpp
206
+ template<in-vector InVec1, in-vector InVec2>
207
+ auto dot(InVec1 v1, InVec2 v2);
208
+ template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2>
209
+ auto dot(ExecutionPolicy&& exec,
210
+ InVec1 v1, InVec2 v2);
211
+ ```
212
+
213
+ These functions compute a non-conjugated dot product with a default
214
+ result type.
215
+
216
+ *Effects:* Let `T` be
217
+ `decltype(declval<typename InVec1::value_type>() * declval<typename InVec2::value_type>())`.
218
+ Then,
219
+
220
+ - the two-parameter overload is equivalent to:
221
+ ``` cpp
222
+ return dot(v1, v2, T{});
223
+ ```
224
+
225
+ and
226
+ - the three-parameter overload is equivalent to:
227
+ ``` cpp
228
+ return dot(std::forward<ExecutionPolicy>(exec), v1, v2, T{});
229
+ ```
230
+
231
+ ``` cpp
232
+ template<in-vector InVec1, in-vector InVec2, class Scalar>
233
+ Scalar dotc(InVec1 v1, InVec2 v2, Scalar init);
234
+ template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2, class Scalar>
235
+ Scalar dotc(ExecutionPolicy&& exec,
236
+ InVec1 v1, InVec2 v2, Scalar init);
237
+ ```
238
+
239
+ These functions compute a conjugated dot product with an explicitly
240
+ specified result type.
241
+
242
+ *Effects:*
243
+
244
+ - The three-parameter overload is equivalent to:
245
+ ``` cpp
246
+ return dot(conjugated(v1), v2, init);
247
+ ```
248
+
249
+ and
250
+ - the four-parameter overload is equivalent to:
251
+ ``` cpp
252
+ return dot(std::forward<ExecutionPolicy>(exec), conjugated(v1), v2, init);
253
+ ```
254
+
255
+ ``` cpp
256
+ template<in-vector InVec1, in-vector InVec2>
257
+ auto dotc(InVec1 v1, InVec2 v2);
258
+ template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2>
259
+ auto dotc(ExecutionPolicy&& exec,
260
+ InVec1 v1, InVec2 v2);
261
+ ```
262
+
263
+ These functions compute a conjugated dot product with a default result
264
+ type.
265
+
266
+ *Effects:* Let `T` be
267
+ `decltype(`*`conj-if-needed`*`(declval<typename InVec1::value_type>()) * declval<typename InVec2::value_type>())`.
268
+ Then,
269
+
270
+ - the two-parameter overload is equivalent to:
271
+ ``` cpp
272
+ return dotc(v1, v2, T{});
273
+ ```
274
+
275
+ and
276
+ - the three-parameter overload is equivalent to
277
+ ``` cpp
278
+ return dotc(std::forward<ExecutionPolicy>(exec), v1, v2, T{});
279
+ ```
280
+
281
+ #### Scaled sum of squares of a vector’s elements <a id="linalg.algs.blas1.ssq">[[linalg.algs.blas1.ssq]]</a>
282
+
283
+ ``` cpp
284
+ template<in-vector InVec, class Scalar>
285
+ sum_of_squares_result<Scalar> vector_sum_of_squares(InVec v, sum_of_squares_result<Scalar> init);
286
+ template<class ExecutionPolicy, in-vector InVec, class Scalar>
287
+ sum_of_squares_result<Scalar> vector_sum_of_squares(ExecutionPolicy&& exec,
288
+ InVec v, sum_of_squares_result<Scalar> init);
289
+ ```
290
+
291
+ [*Note 1*: These functions correspond to the LAPACK function
292
+ `xLASSQ`. — *end note*]
293
+
294
+ *Mandates:*
295
+ `decltype(`*`abs-if-needed`*`(declval<typename InVec::value_type>()))`
296
+ is convertible to `Scalar`.
297
+
298
+ *Effects:* Returns a value `result` such that
299
+
300
+ - `result.scaling_factor` is the maximum of `init.scaling_factor` and
301
+ *`abs-if-needed`*`(x[i])` for all `i` in the domain of `v`; and
302
+ - let `s2init` be
303
+ ``` cpp
304
+ init.scaling_factor * init.scaling_factor * init.scaled_sum_of_squares
305
+ ```
306
+
307
+ then
308
+ `result.scaling_factor * result.scaling_factor * result.scaled_sum_of_squares`
309
+ equals the sum of `s2init` and the squares of
310
+ *`abs-if-needed`*`(x[i])` for all `i` in the domain of `v`.
311
+
312
+ *Remarks:* If `InVec::value_type`, and `Scalar` are all floating-point
313
+ types or specializations of `complex`, and if `Scalar` has higher
314
+ precision than `InVec::value_type`, then intermediate terms in the sum
315
+ use `Scalar`’s precision or greater.
316
+
317
+ #### Euclidean norm of a vector <a id="linalg.algs.blas1.nrm2">[[linalg.algs.blas1.nrm2]]</a>
318
+
319
+ ``` cpp
320
+ template<in-vector InVec, class Scalar>
321
+ Scalar vector_two_norm(InVec v, Scalar init);
322
+ template<class ExecutionPolicy, in-vector InVec, class Scalar>
323
+ Scalar vector_two_norm(ExecutionPolicy&& exec, InVec v, Scalar init);
324
+ ```
325
+
326
+ [*Note 1*: These functions correspond to the BLAS function
327
+ `xNRM2`. — *end note*]
328
+
329
+ *Mandates:* Let `a` be
330
+ *`abs-if-needed`*`(declval<typename InVec::value_type>())`. Then,
331
+ `decltype(init + a * a` is convertible to `Scalar`.
332
+
333
+ *Returns:* The square root of the sum of the square of `init` and the
334
+ squares of the absolute values of the elements of `v`.
335
+
336
+ [*Note 2*: For `init` equal to zero, this is the Euclidean norm (also
337
+ called 2-norm) of the vector `v`. — *end note*]
338
+
339
+ *Remarks:* If `InVec::value_type`, and `Scalar` are all floating-point
340
+ types or specializations of `complex`, and if `Scalar` has higher
341
+ precision than `InVec::value_type`, then intermediate terms in the sum
342
+ use `Scalar`’s precision or greater.
343
+
344
+ [*Note 3*: An implementation of this function for floating-point types
345
+ `T` can use the `scaled_sum_of_squares` result from
346
+ `vector_sum_of_squares(x, {.scaling_factor=1.0, .scaled_sum_of_squares=init})`. — *end note*]
347
+
348
+ ``` cpp
349
+ template<in-vector InVec>
350
+ auto vector_two_norm(InVec v);
351
+ template<class ExecutionPolicy, in-vector InVec>
352
+ auto vector_two_norm(ExecutionPolicy&& exec, InVec v);
353
+ ```
354
+
355
+ *Effects:* Let `a` be
356
+ *`abs-if-needed`*`(declval<typename InVec::value_type>())`. Let `T` be
357
+ `decltype(a * a)`. Then,
358
+
359
+ - the one-parameter overload is equivalent to:
360
+ ``` cpp
361
+ return vector_two_norm(v, T{});
362
+ ```
363
+
364
+ and
365
+ - the two-parameter overload is equivalent to:
366
+ ``` cpp
367
+ return vector_two_norm(std::forward<ExecutionPolicy>(exec), v, T{});
368
+ ```
369
+
370
+ #### Sum of absolute values of vector elements <a id="linalg.algs.blas1.asum">[[linalg.algs.blas1.asum]]</a>
371
+
372
+ ``` cpp
373
+ template<in-vector InVec, class Scalar>
374
+ Scalar vector_abs_sum(InVec v, Scalar init);
375
+ template<class ExecutionPolicy, in-vector InVec, class Scalar>
376
+ Scalar vector_abs_sum(ExecutionPolicy&& exec, InVec v, Scalar init);
377
+ ```
378
+
379
+ [*Note 1*: These functions correspond to the BLAS functions `SASUM`,
380
+ `DASUM`, `SCASUM`, and `DZASUM`. — *end note*]
381
+
382
+ *Mandates:*
383
+
384
+ ``` cpp
385
+ decltype(init + abs-if-needed(real-if-needed(declval<typename InVec::value_type>())) +
386
+ abs-if-needed(imag-if-needed(declval<typename InVec::value_type>())))
387
+ ```
388
+
389
+ is convertible to `Scalar`.
390
+
391
+ *Returns:* Let `N` be `v.extent(0)`.
392
+
393
+ - `init` if `N` is zero;
394
+ - otherwise, if `InVec::value_type` is an arithmetic type,
395
+ ``` cpp
396
+ GENERALIZED_SUM(plus<>(), init, abs-if-needed(v[0]), …, abs-if-needed(v[N-1]))
397
+ ```
398
+ - otherwise,
399
+ ``` cpp
400
+ GENERALIZED_SUM(plus<>(), init,
401
+ abs-if-needed(real-if-needed(v[0])) + abs-if-needed(imag-if-needed(v[0])),
402
+ …,
403
+ abs-if-needed(real-if-needed(v[N-1])) + abs-if-needed(imag-if-needed(v[N-1])))
404
+ ```
405
+
406
+ *Remarks:* If `InVec::value_type` and `Scalar` are all floating-point
407
+ types or specializations of `complex`, and if `Scalar` has higher
408
+ precision than `InVec::value_type`, then intermediate terms in the sum
409
+ use `Scalar`’s precision or greater.
410
+
411
+ ``` cpp
412
+ template<in-vector InVec>
413
+ auto vector_abs_sum(InVec v);
414
+ template<class ExecutionPolicy, in-vector InVec>
415
+ auto vector_abs_sum(ExecutionPolicy&& exec, InVec v);
416
+ ```
417
+
418
+ *Effects:* Let `T` be `typename InVec::value_type`. Then,
419
+
420
+ - the one-parameter overload is equivalent to:
421
+ ``` cpp
422
+ return vector_abs_sum(v, T{});
423
+ ```
424
+
425
+ and
426
+ - the two-parameter overload is equivalent to:
427
+ ``` cpp
428
+ return vector_abs_sum(std::forward<ExecutionPolicy>(exec), v, T{});
429
+ ```
430
+
431
+ #### Index of maximum absolute value of vector elements <a id="linalg.algs.blas1.iamax">[[linalg.algs.blas1.iamax]]</a>
432
+
433
+ ``` cpp
434
+ template<in-vector InVec>
435
+ typename InVec::extents_type vector_idx_abs_max(InVec v);
436
+ template<class ExecutionPolicy, in-vector InVec>
437
+ typename InVec::extents_type vector_idx_abs_max(ExecutionPolicy&& exec, InVec v);
438
+ ```
439
+
440
+ [*Note 1*: These functions correspond to the BLAS function
441
+ `IxAMAX`. — *end note*]
442
+
443
+ Let `T` be
444
+
445
+ ``` cpp
446
+ decltype(abs-if-needed(real-if-needed(declval<typename InVec::value_type>())) +
447
+ abs-if-needed(imag-if-needed(declval<typename InVec::value_type>())))
448
+ ```
449
+
450
+ *Mandates:* `declval<T>() < declval<T>()` is a valid expression.
451
+
452
+ *Returns:*
453
+
454
+ - `numeric_limits<typename InVec::size_type>::max()` if `v` has zero
455
+ elements;
456
+ - otherwise, the index of the first element of `v` having largest
457
+ absolute value, if `InVec::value_type` is an arithmetic type;
458
+ - otherwise, the index of the first element `vₑ` of `v` for which
459
+ ``` cpp
460
+ abs-if-needed(real-if-needed($v_e$)) + abs-if-needed(imag-if-needed($v_e$))
461
+ ```
462
+
463
+ has the largest value.
464
+
465
+ #### Frobenius norm of a matrix <a id="linalg.algs.blas1.matfrobnorm">[[linalg.algs.blas1.matfrobnorm]]</a>
466
+
467
+ [*Note 1*: These functions exist in the BLAS standard but are not part
468
+ of the reference implementation. — *end note*]
469
+
470
+ ``` cpp
471
+ template<in-matrix InMat, class Scalar>
472
+ Scalar matrix_frob_norm(InMat A, Scalar init);
473
+ template<class ExecutionPolicy, in-matrix InMat, class Scalar>
474
+ Scalar matrix_frob_norm(ExecutionPolicy&& exec, InMat A, Scalar init);
475
+ ```
476
+
477
+ *Mandates:* Let `a` be
478
+ *`abs-if-needed`*`(declval<typename InMat::value_type>())`. Then,
479
+ `decltype(init + a * a)` is convertible to `Scalar`.
480
+
481
+ *Returns:* The square root of the sum of squares of `init` and the
482
+ absolute values of the elements of `A`.
483
+
484
+ [*Note 1*: For `init` equal to zero, this is the Frobenius norm of the
485
+ matrix `A`. — *end note*]
486
+
487
+ *Remarks:* If `InMat::value_type` and `Scalar` are all floating-point
488
+ types or specializations of `complex`, and if `Scalar` has higher
489
+ precision than `InMat::value_type`, then intermediate terms in the sum
490
+ use `Scalar`’s precision or greater.
491
+
492
+ ``` cpp
493
+ template<in-matrix InMat>
494
+ auto matrix_frob_norm(InMat A);
495
+ template<class ExecutionPolicy, in-matrix InMat>
496
+ auto matrix_frob_norm(ExecutionPolicy&& exec, InMat A);
497
+ ```
498
+
499
+ *Effects:* Let `a` be
500
+ *`abs-if-needed`*`(declval<typename InMat::value_type>())`. Let `T` be
501
+ `decltype(a * a)`. Then,
502
+
503
+ - the one-parameter overload is equivalent to:
504
+ ``` cpp
505
+ return matrix_frob_norm(A, T{});
506
+ ```
507
+
508
+ and
509
+ - the two-parameter overload is equivalent to:
510
+ ``` cpp
511
+ return matrix_frob_norm(std::forward<ExecutionPolicy>(exec), A, T{});
512
+ ```
513
+
514
+ #### One norm of a matrix <a id="linalg.algs.blas1.matonenorm">[[linalg.algs.blas1.matonenorm]]</a>
515
+
516
+ [*Note 1*: These functions exist in the BLAS standard but are not part
517
+ of the reference implementation. — *end note*]
518
+
519
+ ``` cpp
520
+ template<in-matrix InMat, class Scalar>
521
+ Scalar matrix_one_norm(InMat A, Scalar init);
522
+ template<class ExecutionPolicy, in-matrix InMat, class Scalar>
523
+ Scalar matrix_one_norm(ExecutionPolicy&& exec, InMat A, Scalar init);
524
+ ```
525
+
526
+ *Mandates:*
527
+ `decltype(`*`abs-if-needed`*`(declval<typename InMat::value_type>()))`
528
+ is convertible to `Scalar`.
529
+
530
+ *Returns:*
531
+
532
+ - `init` if `A.extent(1)` is zero;
533
+ - otherwise, the sum of `init` and the one norm of the matrix A.
534
+
535
+ [*Note 1*: The one norm of the matrix `A` is the maximum over all
536
+ columns of `A`, of the sum of the absolute values of the elements of the
537
+ column. — *end note*]
538
+
539
+ *Remarks:* If `InMat::value_type` and `Scalar` are all floating-point
540
+ types or specializations of `complex`, and if `Scalar` has higher
541
+ precision than `InMat::value_type`, then intermediate terms in the sum
542
+ use `Scalar`’s precision or greater.
543
+
544
+ ``` cpp
545
+ template<in-matrix InMat>
546
+ auto matrix_one_norm(InMat A);
547
+ template<class ExecutionPolicy, in-matrix InMat>
548
+ auto matrix_one_norm(ExecutionPolicy&& exec, InMat A);
549
+ ```
550
+
551
+ *Effects:* Let `T` be
552
+ `decltype(`*`abs-if-needed`*`(declval<typename InMat::value_type>())`.
553
+ Then,
554
+
555
+ - the one-parameter overload is equivalent to:
556
+ ``` cpp
557
+ return matrix_one_norm(A, T{});
558
+ ```
559
+
560
+ and
561
+ - the two-parameter overload is equivalent to:
562
+ ``` cpp
563
+ return matrix_one_norm(std::forward<ExecutionPolicy>(exec), A, T{});
564
+ ```
565
+
566
+ #### Infinity norm of a matrix <a id="linalg.algs.blas1.matinfnorm">[[linalg.algs.blas1.matinfnorm]]</a>
567
+
568
+ [*Note 1*: These functions exist in the BLAS standard but are not part
569
+ of the reference implementation. — *end note*]
570
+
571
+ ``` cpp
572
+ template<in-matrix InMat, class Scalar>
573
+ Scalar matrix_inf_norm(InMat A, Scalar init);
574
+ template<class ExecutionPolicy, in-matrix InMat, class Scalar>
575
+ Scalar matrix_inf_norm(ExecutionPolicy&& exec, InMat A, Scalar init);
576
+ ```
577
+
578
+ *Mandates:*
579
+ `decltype(`*`abs-if-needed`*`(declval<typename InMat::value_type>()))`
580
+ is convertible to `Scalar`.
581
+
582
+ *Returns:*
583
+
584
+ - `init` if `A.extent(0)` is zero;
585
+ - otherwise, the sum of `init` and the infinity norm of the matrix `A`.
586
+
587
+ [*Note 1*: The infinity norm of the matrix `A` is the maximum over all
588
+ rows of `A`, of the sum of the absolute values of the elements of the
589
+ row. — *end note*]
590
+
591
+ *Remarks:* If `InMat::value_type` and `Scalar` are all floating-point
592
+ types or specializations of `complex`, and if `Scalar` has higher
593
+ precision than `InMat::value_type`, then intermediate terms in the sum
594
+ use `Scalar`’s precision or greater.
595
+
596
+ ``` cpp
597
+ template<in-matrix InMat>
598
+ auto matrix_inf_norm(InMat A);
599
+ template<class ExecutionPolicy, in-matrix InMat>
600
+ auto matrix_inf_norm(ExecutionPolicy&& exec, InMat A);
601
+ ```
602
+
603
+ *Effects:* Let `T` be
604
+ `decltype(`*`abs-if-needed`*`(declval<typename InMat::value_type>())`.
605
+ Then,
606
+
607
+ - the one-parameter overload is equivalent to:
608
+ ``` cpp
609
+ return matrix_inf_norm(A, T{});
610
+ ```
611
+
612
+ and
613
+ - the two-parameter overload is equivalent to:
614
+ ``` cpp
615
+ return matrix_inf_norm(std::forward<ExecutionPolicy>(exec), A, T{});
616
+ ```
617
+