<T>LAPACK 0.1.2
C++ Template Linear Algebra PACKage
Loading...
Searching...
No Matches
larf.hpp
Go to the documentation of this file.
1
5//
6// Copyright (c) 2025, 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,
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
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) {
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
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,
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,
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
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,
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
345 tlapack_check(direction == Direction::Backward ||
346 direction == Direction::Forward);
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,
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,
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
517 tlapack_check(direction == Direction::Backward ||
518 direction == Direction::Forward);
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
#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
Sort the numbers in D in increasing order (if ID = 'I') or in decreasing order (if ID = 'D' ).
Definition arrayTraits.hpp:15
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
constexpr T conj(const T &x) noexcept
Extends std::conj() to real datatypes.
Definition utils.hpp:100
@ Right
right side
@ Left
left side
constexpr internal::RightSide RIGHT_SIDE
right side
Definition types.hpp:296
constexpr internal::Transpose TRANSPOSE
transpose
Definition types.hpp:262
@ Forward
Forward direction.
@ Backward
Backward direction.
constexpr internal::ConjTranspose CONJ_TRANS
conjugate transpose
Definition types.hpp:264
@ Rowwise
Rowwise storage.
@ Columnwise
Columnwise storage.
constexpr internal::NoTranspose NO_TRANS
no transpose
Definition types.hpp:260
constexpr internal::LeftSide LEFT_SIDE
left side
Definition types.hpp:294
Output information in the workspace query.
Definition workspace.hpp:16