<T>LAPACK 0.1.1
C++ Template Linear Algebra PACKage
Loading...
Searching...
No Matches
labrd.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_LABRD_HH
13#define TLAPACK_LABRD_HH
14
16#include "tlapack/blas/gemv.hpp"
17#include "tlapack/blas/scal.hpp"
20
21namespace tlapack {
22
51template <TLAPACK_SMATRIX A_t,
52 TLAPACK_VECTOR vector_t,
54 TLAPACK_SMATRIX matrixY_t>
56{
57 using TA = type_t<A_t>;
58 using idx_t = size_type<A_t>;
60 using real_t = real_type<TA>;
61
62 // constants
63 const real_t one(1);
64 const real_t zero(0);
65 const idx_t m = nrows(A);
66 const idx_t n = ncols(A);
67 const idx_t nb = ncols(X);
68
69 // quick return if possible
70 if (m == 0 or n == 0) return 0;
71
72 if (m >= n) {
73 //
74 // Reduce to upper bidiagonal form
75 //
76 for (idx_t i = 0; i < nb; ++i) {
77 // Update A(i:m,i)
78 if (i > 0) {
79 auto y = slice(Y, i, range{0, i});
80 auto A2 = slice(A, range{i, m}, range{0, i});
81 auto a21 = slice(A, range{i, m}, i);
82 conjugate(y);
83 gemv(NO_TRANS, -one, A2, y, one, a21);
84 conjugate(y);
85
86 auto X2 = slice(X, range{i, m}, range{0, i});
87 auto a22 = slice(A, range{0, i}, i);
88 real_t e = real(A(i - 1, i));
89 A(i - 1, i) = one;
90 gemv(NO_TRANS, -one, X2, a22, one, a21);
91 A(i - 1, i) = e;
92 }
93
94 // Generate reflection Q(i) to annihilate A(i+1:m,i)
95 auto v = slice(A, range{i, m}, i);
97
98 if (i < n - 1) {
99 real_t d = real(A(i, i));
100 A(i, i) = one;
101
102 //
103 // Compute Y(i+1:n,i) = y11
104 //
105 {
106 auto y11 = slice(Y, range{i + 1, n}, i);
107
108 // y11 = A(i:m,i+1:n)^H * v
109 auto A0 = slice(A, range{i, m}, range{i + 1, n});
110 gemv(CONJ_TRANS, one, A0, v, zero, y11);
111 // t = A(i:m,0:i)^H * v
112 auto A1 = slice(A, range{i, m}, range{0, i});
113 auto t = slice(Y, range{0, i}, i);
114 gemv(CONJ_TRANS, one, A1, v, zero, t);
115 // y11 = y11 - Y(i+1:n,0:i) * t
116 auto Y2 = slice(Y, range{i + 1, n}, range{0, i});
117 gemv(NO_TRANS, -one, Y2, t, one, y11);
118 // t = X(i:m,0:i)^H * v
119 auto X2 = slice(X, range{i, m}, range{0, i});
120 gemv(CONJ_TRANS, one, X2, v, zero, t);
121 // y11 = y11 - A(0:i,i+1:n)^H * t
122 auto A2 = slice(A, range{0, i}, range{i + 1, n});
123 gemv(CONJ_TRANS, -one, A2, t, one, y11);
124 // y11 = y11 * tauq(i)
125 scal(tauq[i], y11);
126 }
127
128 //
129 // Update A(i,i+1:n) = a11
130 //
131 {
132 auto a11 = slice(A, i, range{i + 1, n});
133
134 // a11 = conj(a11) - Y(i+1:n,0:i+1)*conj(s)
135 // for (idx_t l = 0; l < n; ++l)
136 // A(i, l) = conj(A(i, l));
137
138 auto s = slice(A, i, range{0, i + 1});
139 conjugate(a11);
140 conjugate(s);
141 auto Y3 = slice(Y, range{i + 1, n}, range{0, i + 1});
142 gemv(NO_TRANS, -one, Y3, s, one, a11);
143 conjugate(s);
144 // a11 = a11 - A(0:i,i+1:n)^H * conj(X(i,0:i))
145 auto A3 = slice(A, range{0, i}, range{i + 1, n});
146 auto x = slice(X, i, range{0, i});
147 conjugate(x);
148 gemv(CONJ_TRANS, -one, A3, x, one, a11);
149 conjugate(x);
150 }
151
152 //
153 // Generate reflection P(i) to annihilate A(i,i+2:n)
154 //
155 auto w = slice(A, i, range{i + 1, n});
157 real_t e = real(A(i, i + 1));
158 A(i, i + 1) = one;
159
160 //
161 // Compute X(i+1:m,i) = x11
162 //
163 {
164 auto x11 = slice(X, range{i + 1, m}, i);
165
166 // x11 = A(i+1:m,i+1:n) * w
167 auto A4 = slice(A, range{i + 1, m}, range{i + 1, n});
168 gemv(NO_TRANS, one, A4, w, zero, x11);
169 // t = Y(i+1:n,0:i+1)^H * w
170 auto Y4 = slice(Y, range{i + 1, n}, range{0, i + 1});
171 auto t2 = slice(X, range{0, i + 1}, i);
172 gemv(CONJ_TRANS, one, Y4, w, zero, t2);
173 // x11 = x11 - A(i+1:m,0:i+1) * t
174 auto A5 = slice(A, range{i + 1, m}, range{0, i + 1});
175 gemv(NO_TRANS, -one, A5, t2, one, x11);
176 // t = A(0:i,i+1:n) * w
177 auto A6 = slice(A, range{0, i}, range{i + 1, n});
178 auto t3 = slice(X, range{0, i}, i);
179 gemv(NO_TRANS, one, A6, w, zero, t3);
180 // x11 = x11 - X(i+1:m,0:i) * t
181 auto X4 = slice(X, range{i + 1, m}, range{0, i});
182 gemv(NO_TRANS, -one, X4, t3, one, x11);
183 // x11 = x11 * taup(i)
184 scal(taup[i], x11);
185 conjugate(w);
186 }
187
188 A(i, i) = d;
189 A(i, i + 1) = e;
190 }
191 }
192 }
193 else {
194 //
195 // Reduce to lower bidiagonal form
196 //
197 for (idx_t i = 0; i < nb; ++i) {
198 auto w = slice(A, i, range{i, n});
199 conjugate(w);
200
201 // Update A(i,i:n)
202 if (i > 0) {
203 auto Y2 = slice(Y, range{i, n}, range{0, i});
204 auto s = slice(A, i, range{0, i});
205 conjugate(s);
206 real_t e = real(A(i, i - 1));
207 A(i, i - 1) = one;
208 gemv(NO_TRANS, -one, Y2, s, one, w);
209 A(i, i - 1) = e;
210 conjugate(s);
211
212 auto A2 = slice(A, range{0, i}, range{i, n});
213 auto x = slice(X, i, range{0, i});
214 conjugate(x);
215 gemv(CONJ_TRANS, -one, A2, x, one, w);
216 conjugate(x);
217 }
218
219 // Generate reflection P(i) to annihilate A(i,i+1:n)
221
222 if (i + 1 < m) {
223 real_t d = real(A(i, i));
224 A(i, i) = one;
225
226 //
227 // Compute X(i+1:m,i) = x11
228 //
229 {
230 auto x11 = slice(X, range{i + 1, m}, i);
231
232 // x11 = A(i+1:m,i+1:n) * w
233 auto A4 = slice(A, range{i + 1, m}, range{i, n});
234 gemv(NO_TRANS, one, A4, w, zero, x11);
235 if (i > 0) {
236 // t = Y(i:n,0:i)^H * w
237 auto Y4 = slice(Y, range{i, n}, range{0, i});
238 auto t2 = slice(X, range{0, i}, i);
239 gemv(CONJ_TRANS, one, Y4, w, zero, t2);
240 // x11 = x11 - A(i+1:m,0:i) * t
241 auto A5 = slice(A, range{i + 1, m}, range{0, i});
242 gemv(NO_TRANS, -one, A5, t2, one, x11);
243 // t = A(0:i,i:n) * w
244 auto A6 = slice(A, range{0, i}, range{i, n});
245 auto t3 = slice(X, range{0, i}, i);
246 gemv(NO_TRANS, one, A6, w, zero, t3);
247 // x11 = x11 - X(i+1:m,0:i) * t
248 auto X4 = slice(X, range{i + 1, m}, range{0, i});
249 gemv(NO_TRANS, -one, X4, t3, one, x11);
250 }
251 // x11 = x11 * taup(i)
252 scal(taup[i], x11);
253 conjugate(w);
254 }
255
256 // Update A(i+1:m,i)
257 {
258 auto y = slice(Y, i, range{0, i});
259 auto A2 = slice(A, range{i + 1, m}, range{0, i});
260 auto a21 = slice(A, range{i + 1, m}, i);
261 conjugate(y);
262 gemv(NO_TRANS, -one, A2, y, one, a21);
263 conjugate(y);
264
265 auto X2 = slice(X, range{i + 1, m}, range{0, i + 1});
266 auto a22 = slice(A, range{0, i + 1}, i);
267 gemv(NO_TRANS, -one, X2, a22, one, a21);
268 }
269
270 //
271 // Generate reflection Q(i) to annihilate A(i+2:m,i)
272 //
273 auto v = slice(A, range{i + 1, m}, i);
275 real_t e = real(A(i + 1, i));
276 A(i + 1, i) = one;
277
278 //
279 // Compute Y(i+1:n,i) = y11
280 //
281 {
282 auto y11 = slice(Y, range{i + 1, n}, i);
283
284 // y11 = A(i+1:m,i+1:n)^H * v
285 auto A0 = slice(A, range{i + 1, m}, range{i + 1, n});
286 gemv(CONJ_TRANS, one, A0, v, zero, y11);
287 // t = A(i+1:m,0:i)^H * v
288 auto A1 = slice(A, range{i + 1, m}, range{0, i});
289 auto t = slice(Y, range{0, i}, i);
290 gemv(CONJ_TRANS, one, A1, v, zero, t);
291 // y11 = y11 - Y(i+1:n,0:i) * t
292 auto Y2 = slice(Y, range{i + 1, n}, range{0, i});
293 gemv(NO_TRANS, -one, Y2, t, one, y11);
294 // t = X(i+1:m,0:i+1)^H * v
295 auto t2 = slice(Y, range{0, i + 1}, i);
296 auto X3 = slice(X, range{i + 1, m}, range{0, i + 1});
297 gemv(CONJ_TRANS, one, X3, v, zero, t2);
298 // y11 = y11 - A(0:i+1,i+1:n)^H * t
299 auto A3 = slice(A, range{0, i + 1}, range{i + 1, n});
300 gemv(CONJ_TRANS, -one, A3, t2, one, y11);
301 // y11 = y11 * tauq(i)
302 scal(tauq[i], y11);
303 }
304
305 A(i, i) = d;
306 A(i + 1, i) = e;
307 }
308 else {
309 conjugate(w);
310 }
311 }
312 }
313
314 return 0;
315}
316
317} // namespace tlapack
318
319#endif // TLAPACK_LABRD_HH
constexpr internal::Forward FORWARD
Forward direction.
Definition types.hpp:376
constexpr internal::ConjTranspose CONJ_TRANS
conjugate transpose
Definition types.hpp:259
constexpr internal::ColumnwiseStorage COLUMNWISE_STORAGE
Columnwise storage.
Definition types.hpp:409
constexpr internal::NoTranspose NO_TRANS
no transpose
Definition types.hpp:255
constexpr real_type< T > real(const T &x) noexcept
Extends std::real() to real datatypes.
Definition utils.hpp:71
#define TLAPACK_SMATRIX
Macro for tlapack::concepts::SliceableMatrix compatible with C++17.
Definition concepts.hpp:899
#define TLAPACK_VECTOR
Macro for tlapack::concepts::Vector compatible with C++17.
Definition concepts.hpp:906
void conjugate(vector_t &x)
Conjugates a vector.
Definition conjugate.hpp:24
int labrd(A_t &A, vector_t &tauq, vector_t &taup, X_t &X, matrixY_t &Y)
Reduces the first nb rows and columns of a general m by n matrix A to upper or lower bidiagonal form ...
Definition labrd.hpp:55
void larfg(storage_t storeMode, type_t< vector_t > &alpha, vector_t &x, type_t< vector_t > &tau)
Generates a elementary Householder reflection.
Definition larfg.hpp:73
void scal(const alpha_t &alpha, vector_t &x)
Scale vector by constant, .
Definition scal.hpp:30
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
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