<T>LAPACK 0.1.2
C++ Template Linear Algebra PACKage
Loading...
Searching...
No Matches
trevc.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_TREVC_HH
13#define TLAPACK_TREVC_HH
14
16#include "tlapack/blas/asum.hpp"
17#include "tlapack/blas/gemv.hpp"
20
21namespace tlapack {
22
23enum class HowMny : char {
24 All = 'A',
25 Back = 'B',
26 Select = 'S'
27};
28
107template <TLAPACK_SIDE side_t,
114int trevc(const side_t side,
115 const HowMny howmny,
117 const matrix_T_t& T,
120 rwork_t& rwork,
121 work_t& work)
122{
123 using idx_t = size_type<matrix_T_t>;
124 using TT = type_t<matrix_T_t>;
126 using real_t = real_type<TT>;
127
128 const idx_t n = nrows(T);
129 // Number of columns of Vl and Vr
130 // const idx_t mm = max(ncols(Vl), ncols(Vr));
131 idx_t mm;
132 if (side == Side::Both) {
133 mm = std::min<idx_t>(ncols(Vl), ncols(Vr));
134 }
135 else if (side == Side::Left) {
136 mm = ncols(Vl);
137 }
138 else {
139 mm = ncols(Vr);
140 }
141
142 // Quick return
143 if (n == 0) return 0;
144
145 idx_t m = 0; // Actual number of eigenvectors to compute
146 if (howmny == HowMny::Select) {
147 // Set m to the number of columns required to store the selected
148 // eigenvectors.
149 // If necessary, the array select is standardized for complex
150 // conjugate pairs so that select[j] is true and select[j+1] is false.
151 idx_t j = 0;
152 while (j < n) {
153 bool pair = false;
154 if (j < n - 1) {
155 if (T(j + 1, j) != TT(0)) {
156 pair = true;
157 }
158 }
159 if (!pair) {
160 if (select[j]) {
161 m++;
162 }
163 j++;
164 }
165 else {
166 if (select[j] || select[j + 1]) {
167 select[j] = true;
168 select[j + 1] = false;
169 m += 2;
170 }
171 j += 2;
172 }
173 }
174 }
175 else {
176 m = n;
177 }
178
179 // Make sure that the matrices Vl and Vr have enough space
180 tlapack_check(mm >= m);
181
182 auto [v1, work2] = reshape(work, n);
183 auto [v2, work3] = reshape(work2, n);
184 auto [v3, work4] = reshape(work3, n);
185 auto [colN, rwork2] = reshape(rwork, n);
186
187 if (side == Side::Right || side == Side::Both) {
188 //
189 // Compute right eigenvectors.
190 //
192 idx_t iVr = m - 1; // current column of Vr to store the eigenvector
193 for (idx_t ii = 0; ii < n; ii++) {
194 idx_t i = n - 1 - ii;
195 if (HowMny::Select == howmny) {
196 if (select[i] == false) {
197 continue;
198 }
199 }
200 if (i > 0) {
201 if (T(i, i - 1) != TT(0)) {
202 continue;
203 }
204 }
205
206 bool pair = false;
207 if (i < n - 1) {
208 if (T(i + 1, i) != TT(0)) {
209 pair = true;
210 }
211 }
212
213 if (!pair) {
214 //
215 // Real eigenvalue
216 //
217
218 // Calculate eigenvector of the upper quasi-triangular matrix T
220
221 // Backtransform eigenvector if required
222 if (howmny == HowMny::Back) {
223 auto Q_slice = slice(Vr, range(0, n), range(0, i + 1));
224 auto v1_slice = slice(v1, range(0, i + 1));
226 for (idx_t k = 0; k < n; ++k) {
227 Vr(k, i) = v2[k];
228 }
229 }
230 else {
231 // Copy the eigenvector to Vr
232 for (idx_t k = 0; k < n; ++k) {
233 Vr(k, iVr) = v1[k];
234 }
235 }
236 iVr--;
237 }
238 else {
239 if constexpr (is_real<TT>) {
240 // Complex conjugate pair
241 // Calculate eigenvector of the upper quasi-triangular
242 // matrix T
244
245 // Backtransform eigenvector pair if required
246 if (howmny == HowMny::Back) {
247 auto Q_slice1 = slice(Vr, range(0, n), range(0, i + 2));
248 auto v2_slice = slice(v2, range(0, i + 2));
250 // copy v3 to Vr(:, i+1)
251 for (idx_t k = 0; k < n; ++k) {
252 Vr(k, i + 1) = v3[k];
253 }
254 // Note: we assume that these eigenvectors are
255 // constructed so that v1[i+1] = 0, otherwise, we would
256 // need an extra workspace vector here.
257 auto Q_slice2 = slice(Vr, range(0, n), range(0, i + 1));
258 auto v1_slice = slice(v1, range(0, i + 1));
260 // copy v3 to Vr(:, i)
261 for (idx_t k = 0; k < n; ++k) {
262 Vr(k, i) = v3[k];
263 }
264 }
265 else {
266 // Copy the eigenvector pair to Vr
267 for (idx_t k = 0; k < n; ++k) {
268 Vr(k, iVr - 1) = v1[k];
269 Vr(k, iVr) = v2[k];
270 }
271 }
272 iVr -= 2;
273 }
274 }
275 }
276 }
277
278 if (side == Side::Left || side == Side::Both) {
279 //
280 // Compute left eigenvectors.
281 //
283 idx_t iVl = 0; // current column of Vl to store the eigenvector
284 for (idx_t i = 0; i < n; i++) {
285 if (HowMny::Select == howmny) {
286 if (select[i] == false) {
287 continue;
288 }
289 }
290 if (i > 0) {
291 if (T(i, i - 1) != TT(0)) {
292 continue;
293 }
294 }
295
296 bool pair = false;
297 if (i < n - 1) {
298 if (T(i + 1, i) != TT(0)) {
299 pair = true;
300 }
301 }
302
303 if (!pair) {
304 //
305 // Real eigenvalue
306 //
307
308 // Calculate eigenvector of the upper quasi-triangular matrix T
310
311 // Backtransform eigenvector if required
312 if (howmny == HowMny::Back) {
313 auto Q_slice = slice(Vl, range(0, n), range(i, n));
314 auto v1_slice = slice(v1, range(i, n));
316 for (idx_t k = 0; k < n; ++k) {
317 Vl(k, i) = v2[k];
318 }
319 }
320 else {
321 // Copy the eigenvector to Vl
322 for (idx_t k = 0; k < n; ++k) {
323 Vl(k, iVl) = v1[k];
324 }
325 }
326 iVl++;
327 }
328 else {
329 if constexpr (is_real<TT>) {
330 // Complex conjugate pair
331 // Calculate eigenvector of the upper quasi-triangular
332 // matrix T
334
335 // Backtransform eigenvector pair if required
336 if (howmny == HowMny::Back) {
337 auto Q_slice1 = slice(Vl, range(0, n), range(i, n));
338 auto v1_slice = slice(v1, range(i, n));
340 // copy v3 to Vl(:, i)
341 for (idx_t k = 0; k < n; ++k) {
342 Vl(k, i) = v3[k];
343 }
344 // Note: we assume that these eigenvectors are
345 // constructed so that v2[i] = 0, otherwise, we would
346 // need an extra workspace vector here.
347 auto Q_slice2 = slice(Vl, range(0, n), range(i + 1, n));
348 auto v2_slice = slice(v2, range(i + 1, n));
350 // copy v3 to Vl(:, i+1)
351 for (idx_t k = 0; k < n; ++k) {
352 Vl(k, i + 1) = v3[k];
353 }
354 }
355 else {
356 // Copy the eigenvector pair to Vl
357 for (idx_t k = 0; k < n; ++k) {
358 Vl(k, iVl) = v1[k];
359 Vl(k, iVl + 1) = v2[k];
360 }
361 }
362 iVl += 2;
363 }
364 }
365 }
366 }
367
368 return 0;
369}
370
371} // namespace tlapack
372
373#endif // TLAPACK_TREVC_HH
#define TLAPACK_SIDE
Macro for tlapack::concepts::Side compatible with C++17.
Definition concepts.hpp:927
#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 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
#define tlapack_check(cond)
Throw an error if cond is false.
Definition exceptionHandling.hpp:98
Sort the numbers in D in increasing order (if ID = 'I') or in decreasing order (if ID = 'D' ).
Definition arrayTraits.hpp:15
void trevc_backsolve_double(const matrix_T_t &T, vector_v_t &v_r, vector_v_t &v_i, const size_type< matrix_T_t > k, const vector_colN_t &colN)
Calculate the k-th right eigenvector pair of T using backsubstitution.
Definition trevc_backsolve.hpp:415
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
void trevc_forwardsolve_double(const matrix_T_t &T, vector_v_t &v_r, vector_v_t &v_i, const size_type< matrix_T_t > k, const vector_colN_t &colN)
Calculate the k-th left eigenvector pair of T using forward substitution.
Definition trevc_forwardsolve.hpp:371
@ Both
both sides
@ Right
right side
@ Left
left side
void trevc_forwardsolve_single(const matrix_T_t &T, vector_v_t &v, const size_type< matrix_T_t > k, const vector_colN_t &colN)
Calculate the k-th left eigenvector of T using forward substitution.
Definition trevc_forwardsolve.hpp:73
HowMny
Definition trevc.hpp:23
@ Back
all eigenvectors, backtransformed by input matrix
@ All
all eigenvectors
@ Select
selected eigenvectors
@ NoTrans
no transpose
@ Inf
infinity norm of matrices
@ One
one norm
void trevc_backsolve_single(const matrix_T_t &T, vector_v_t &v, const size_type< matrix_T_t > k, const vector_colN_t &colN)
Calculate the k-th right eigenvector of T using backsubstitution.
Definition trevc_backsolve.hpp:79
void trevc_colnorms(Norm norm, const matrix_T_t &T, vector_colN_t &colN)
Calculate the 1- or infinity-norms of the columns of the strictly upper triangular part of T.
Definition trevc_protect.hpp:506
int trevc(const side_t side, const HowMny howmny, select_t &select, const matrix_T_t &T, matrix_Vl_t &Vl, matrix_Vr_t &Vr, rwork_t &rwork, work_t &work)
TREVC computes some or all of the right and/or left eigenvectors of an upper quasi-triangular matrix ...
Definition trevc.hpp:114