<T>LAPACK 0.1.1
C++ Template Linear Algebra PACKage
Loading...
Searching...
No Matches
larf.hpp
Go to the documentation of this file.
1
5//
6// Copyright (c) 2021-2023, University of Colorado Denver. All rights reserved.
7//
8// This file is part of <T>LAPACK.
9// <T>LAPACK is free software: you can redistribute it and/or modify it under
10// the terms of the BSD 3-Clause license. See the accompanying LICENSE file.
11
12#ifndef TLAPACK_LARF_HH
13#define TLAPACK_LARF_HH
14
16#include "tlapack/blas/gemv.hpp"
17#include "tlapack/blas/ger.hpp"
18#include "tlapack/blas/geru.hpp"
19
20namespace tlapack {
21
40template <TLAPACK_SIDE side_t,
41 TLAPACK_STOREV storage_t,
42 TLAPACK_VECTOR vector_t,
43 TLAPACK_WORKSPACE work_t,
44 TLAPACK_SCALAR tau_t,
45 TLAPACK_VECTOR vectorC0_t,
46 TLAPACK_MATRIX matrixC1_t,
47 enable_if_t<std::is_convertible_v<storage_t, StoreV>, int> = 0>
50 vector_t const& x,
51 const tau_t& tau,
54 work_t& work)
55{
56 // data traits
57 using idx_t = size_type<vectorC0_t>;
58 using T = type_t<work_t>;
59 using real_t = real_type<T>;
60
61 // constants
62 const real_t one(1);
63 const idx_t k = size(C0);
64 const idx_t m = nrows(C1);
65 const idx_t n = ncols(C1);
66
67 // check arguments
68 tlapack_check(side == Side::Left || side == Side::Right);
69 tlapack_check(storeMode == StoreV::Columnwise ||
70 storeMode == StoreV::Rowwise);
71 tlapack_check((idx_t)size(x) == (side == Side::Left) ? m : n);
72
73 // Quick return if possible
74 if (m == 0 || n == 0) {
75 for (idx_t i = 0; i < k; ++i)
76 C0[i] -= tau * C0[i];
77 return;
78 }
79
80 // Vector w
81 auto [w, work1] = reshape(work, k);
82
83 if (side == Side::Left) {
84 if (storeMode == StoreV::Columnwise) {
85 // w := C0^H + C1^H*x
86 for (idx_t i = 0; i < k; ++i)
87 w[i] = conj(C0[i]);
88 gemv(CONJ_TRANS, one, C1, x, one, w);
89
90 // C1 := C1 - tau*x*w^H
91 ger(-tau, x, w, C1);
92
93 // C0 := C0 - tau*w^H
94 for (idx_t i = 0; i < k; ++i)
95 C0[i] -= tau * conj(w[i]);
96 }
97 else {
98 // w := C0^t + C1^t*x
99 for (idx_t i = 0; i < k; ++i)
100 w[i] = C0[i];
101 gemv(TRANSPOSE, one, C1, x, one, w);
102
103 // C1 := C1 - tau*conj(x)*w^t
104 for (idx_t j = 0; j < n; ++j)
105 for (idx_t i = 0; i < m; ++i)
106 C1(i, j) -= tau * conj(x[i]) * w[j];
107
108 // C0 := C0 - tau*w^t
109 for (idx_t i = 0; i < k; ++i)
110 C0[i] -= tau * w[i];
111 }
112 }
113 else { // side == Side::Right
114 if (storeMode == StoreV::Columnwise) {
115 // w := C0 + C1*x
116 for (idx_t i = 0; i < k; ++i)
117 w[i] = C0[i];
118 gemv(NO_TRANS, one, C1, x, one, w);
119
120 // C1 := C1 - tau*w*x^H
121 ger(-tau, w, x, C1);
122
123 // C0 := C0 - tau*w
124 for (idx_t i = 0; i < k; ++i)
125 C0[i] -= tau * w[i];
126 }
127 else {
128 // w := C0 + C1*conj(x)
129 for (idx_t i = 0; i < k; ++i)
130 w[i] = C0[i];
131 for (idx_t j = 0; j < n; ++j)
132 for (idx_t i = 0; i < m; ++i)
133 w[i] += C1(i, j) * conj(x[j]);
134
135 // C1 := C1 - tau*w*x^t
136 geru(-tau, w, x, C1);
137
138 // C0 := C0 - tau*w
139 for (idx_t i = 0; i < k; ++i)
140 C0[i] -= tau * w[i];
141 }
142 }
143}
144
172template <class T,
173 TLAPACK_SIDE side_t,
174 TLAPACK_STOREV storage_t,
175 TLAPACK_VECTOR vector_t,
176 TLAPACK_SCALAR tau_t,
177 TLAPACK_VECTOR vectorC0_t,
178 TLAPACK_MATRIX matrixC1_t,
179 enable_if_t<std::is_convertible_v<storage_t, StoreV>, int> = 0>
182 vector_t const& x,
183 const tau_t& tau,
184 const vectorC0_t& C0,
185 const matrixC1_t& C1)
186{
188 using idx_t = size_type<vectorC0_t>;
189
190 // constants
191 const idx_t m = nrows(C1);
192 const idx_t n = ncols(C1);
193
194 if constexpr (is_same_v<T, type_t<work_t>>)
195 return (m > 0 && n > 0) ? WorkInfo((side == Side::Left) ? n : m)
196 : WorkInfo(0);
197 else
198 return WorkInfo(0);
199}
200
254template <TLAPACK_SIDE side_t,
255 TLAPACK_STOREV storage_t,
256 TLAPACK_VECTOR vector_t,
257 TLAPACK_SCALAR tau_t,
258 TLAPACK_VECTOR vectorC0_t,
259 TLAPACK_MATRIX matrixC1_t,
260 enable_if_t<std::is_convertible_v<storage_t, StoreV>, int> = 0>
263 vector_t const& x,
264 const tau_t& tau,
265 vectorC0_t& C0,
266 matrixC1_t& C1)
267{
268 // data traits
270 using idx_t = size_type<vectorC0_t>;
271 using T = type_t<work_t>;
272
273 // Functor
275
276 // constants
277 const idx_t k = size(C0);
278 const idx_t m = nrows(C1);
279 const idx_t n = ncols(C1);
280
281 // check arguments
282 tlapack_check(side == Side::Left || side == Side::Right);
283 tlapack_check(storeMode == StoreV::Columnwise ||
284 storeMode == StoreV::Rowwise);
285 tlapack_check((idx_t)size(x) == (side == Side::Left) ? m : n);
286
287 // Quick return if possible
288 if (m == 0 || n == 0) {
289 for (idx_t i = 0; i < k; ++i)
290 C0[i] -= tau * C0[i];
291 return;
292 }
293
294 // Allocates workspace
296 std::vector<T> work_;
297 auto work = new_matrix(work_, workinfo.m, workinfo.n);
298
299 return larf_work(side, storeMode, x, tau, C0, C1, work);
300}
301
320template <TLAPACK_SIDE side_t,
321 TLAPACK_DIRECTION direction_t,
322 TLAPACK_STOREV storage_t,
323 TLAPACK_SVECTOR vector_t,
324 TLAPACK_WORKSPACE work_t,
325 TLAPACK_SCALAR tau_t,
326 TLAPACK_SMATRIX matrix_t,
327 enable_if_t<std::is_convertible_v<direction_t, Direction>, int> = 0>
329 direction_t direction,
331 vector_t const& v,
332 const tau_t& tau,
333 matrix_t& C,
334 work_t& work)
335{
336 using idx_t = size_type<matrix_t>;
338
339 // constants
340 const idx_t m = nrows(C);
341 const idx_t n = ncols(C);
342
343 // check arguments
344 tlapack_check(side == Side::Left || side == Side::Right);
345 tlapack_check(direction == Direction::Backward ||
346 direction == Direction::Forward);
347 tlapack_check(storeMode == StoreV::Columnwise ||
348 storeMode == StoreV::Rowwise);
349 tlapack_check((idx_t)size(v) == ((side == Side::Left) ? m : n));
350
351 // quick return
352 if (m == 0 || n == 0) return;
353
354 // The following code was changed from:
355 //
356 // if( side == Side::Left ) {
357 // gemv(CONJ_TRANS, one, C, v, work);
358 // ger(-tau, v, work, C);
359 // }
360 // else{
361 // gemv(NO_TRANS, one, C, v, work);
362 // ger(-tau, work, v, C);
363 // }
364 //
365 // This is so that v[0] doesn't need to be changed to 1,
366 // which is better for thread safety.
367
368 if (side == Side::Left) {
369 auto C0 = (direction == Direction::Forward) ? row(C, 0) : row(C, m - 1);
370 auto C1 = (direction == Direction::Forward) ? rows(C, range{1, m})
371 : rows(C, range{0, m - 1});
372 auto x = (direction == Direction::Forward) ? slice(v, range{1, m})
373 : slice(v, range{0, m - 1});
375 }
376 else { // side == Side::Right
377 auto C0 = (direction == Direction::Forward) ? col(C, 0) : col(C, n - 1);
378 auto C1 = (direction == Direction::Forward) ? cols(C, range{1, n})
379 : cols(C, range{0, n - 1});
380 auto x = (direction == Direction::Forward) ? slice(v, range{1, n})
381 : slice(v, range{0, n - 1});
383 }
384}
385
414template <class T,
415 TLAPACK_SIDE side_t,
416 TLAPACK_DIRECTION direction_t,
417 TLAPACK_STOREV storage_t,
418 TLAPACK_SVECTOR vector_t,
419 TLAPACK_SCALAR tau_t,
420 TLAPACK_SMATRIX matrix_t,
421 enable_if_t<std::is_convertible_v<direction_t, Direction>, int> = 0>
423 direction_t direction,
425 vector_t const& v,
426 const tau_t& tau,
427 const matrix_t& C)
428{
429 using idx_t = size_type<matrix_t>;
431
432 // constants
433 const idx_t m = nrows(C);
434 const idx_t n = ncols(C);
435
436 if (side == Side::Left && m > 0) {
437 auto&& C0 = row(C, 0);
438 auto&& C1 = rows(C, range{1, m});
439 auto&& x = slice(v, range{1, m});
441 }
442 else if (side == Side::Right && n > 0) {
443 auto&& C0 = col(C, 0);
444 auto&& C1 = cols(C, range{1, n});
445 auto&& x = slice(v, range{1, n});
447 }
448 else
449 return WorkInfo(0);
450}
451
489template <TLAPACK_SIDE side_t,
490 TLAPACK_DIRECTION direction_t,
491 TLAPACK_STOREV storage_t,
492 TLAPACK_SVECTOR vector_t,
493 TLAPACK_SCALAR tau_t,
494 TLAPACK_SMATRIX matrix_t,
495 enable_if_t<std::is_convertible_v<direction_t, Direction>, int> = 0>
497 direction_t direction,
499 vector_t const& v,
500 const tau_t& tau,
501 matrix_t& C)
502{
503 // data traits
505 using idx_t = size_type<matrix_t>;
506 using T = type_t<work_t>;
507
508 // Functor
510
511 // constants
512 const idx_t m = nrows(C);
513 const idx_t n = ncols(C);
514
515 // check arguments
516 tlapack_check(side == Side::Left || side == Side::Right);
517 tlapack_check(direction == Direction::Backward ||
518 direction == Direction::Forward);
519 tlapack_check(storeMode == StoreV::Columnwise ||
520 storeMode == StoreV::Rowwise);
521 tlapack_check((idx_t)size(v) == ((side == Side::Left) ? m : n));
522
523 // quick return
524 if (m == 0 || n == 0) return;
525
526 // Allocates workspace
528 std::vector<T> work_;
529 auto work = new_matrix(work_, workinfo.m, workinfo.n);
530
531 return larf_work(side, direction, storeMode, v, tau, C, work);
532}
533
534} // namespace tlapack
535
536#endif // TLAPACK_LARF_HH
constexpr internal::RightSide RIGHT_SIDE
right side
Definition types.hpp:291
constexpr internal::Transpose TRANSPOSE
transpose
Definition types.hpp:257
constexpr internal::ConjTranspose CONJ_TRANS
conjugate transpose
Definition types.hpp:259
constexpr internal::NoTranspose NO_TRANS
no transpose
Definition types.hpp:255
constexpr internal::LeftSide LEFT_SIDE
left side
Definition types.hpp:289
constexpr T conj(const T &x) noexcept
Extends std::conj() to real datatypes.
Definition utils.hpp:100
#define TLAPACK_SVECTOR
Macro for tlapack::concepts::SliceableVector compatible with C++17.
Definition concepts.hpp:909
#define TLAPACK_SCALAR
Macro for tlapack::concepts::Scalar compatible with C++17.
Definition concepts.hpp:915
#define TLAPACK_STOREV
Macro for tlapack::concepts::StoreV compatible with C++17.
Definition concepts.hpp:936
#define TLAPACK_SIDE
Macro for tlapack::concepts::Side compatible with C++17.
Definition concepts.hpp:927
#define TLAPACK_SMATRIX
Macro for tlapack::concepts::SliceableMatrix compatible with C++17.
Definition concepts.hpp:899
#define TLAPACK_DIRECTION
Macro for tlapack::concepts::Direction compatible with C++17.
Definition concepts.hpp:930
#define TLAPACK_WORKSPACE
Macro for tlapack::concepts::Workspace compatible with C++17.
Definition concepts.hpp:912
#define TLAPACK_VECTOR
Macro for tlapack::concepts::Vector compatible with C++17.
Definition concepts.hpp:906
#define TLAPACK_MATRIX
Macro for tlapack::concepts::Matrix compatible with C++17.
Definition concepts.hpp:896
void larf(side_t side, storage_t storeMode, vector_t const &x, const tau_t &tau, vectorC0_t &C0, matrixC1_t &C1)
Applies an elementary reflector defined by tau and v to a m-by-n matrix C decomposed into C0 and C1.
Definition larf.hpp:261
void larf_work(side_t side, storage_t storeMode, vector_t const &x, const tau_t &tau, vectorC0_t &C0, matrixC1_t &C1, work_t &work)
Applies an elementary reflector defined by tau and v to a m-by-n matrix C decomposed into C0 and C1....
Definition larf.hpp:48
void gemv(Op trans, const alpha_t &alpha, const matrixA_t &A, const vectorX_t &x, const beta_t &beta, vectorY_t &y)
General matrix-vector multiply:
Definition gemv.hpp:57
void ger(const alpha_t &alpha, const vectorX_t &x, const vectorY_t &y, matrixA_t &A)
General matrix rank-1 update:
Definition ger.hpp:42
void geru(const alpha_t &alpha, const vectorX_t &x, const vectorY_t &y, matrixA_t &A)
General matrix rank-1 update:
Definition geru.hpp:43
#define tlapack_check(cond)
Throw an error if cond is false.
Definition exceptionHandling.hpp:98
constexpr WorkInfo larf_worksize(side_t side, storage_t storeMode, vector_t const &x, const tau_t &tau, const vectorC0_t &C0, const matrixC1_t &C1)
Worspace query of larf().
Definition larf.hpp:180
typename traits::real_type_traits< Types..., int >::type real_type
The common real type of the list of types.
Definition scalar_type_traits.hpp:113
Output information in the workspace query.
Definition workspace.hpp:16