<T>LAPACK 0.1.1
C++ Template Linear Algebra PACKage
Loading...
Searching...
No Matches
lahqz_shiftcolumn.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_LAHQZ_SHIFTCOLUMN_HH
13#define TLAPACK_LAHQZ_SHIFTCOLUMN_HH
14
16
17namespace tlapack {
18
44template <TLAPACK_MATRIX matrix_t, TLAPACK_VECTOR vector_t, bool>
45int lahqz_shiftcolumn(const matrix_t& A,
46 const matrix_t& B,
47 vector_t& v,
48 complex_type<type_t<matrix_t>> s1,
49 complex_type<type_t<matrix_t>> s2,
50 type_t<matrix_t> beta1,
51 type_t<matrix_t> beta2);
52
53template <TLAPACK_MATRIX matrix_t,
54 TLAPACK_VECTOR vector_t,
55 enable_if_t<is_real<type_t<matrix_t>>, bool> = true>
57 const matrix_t& B,
58 vector_t& v,
63{
64 // Using
65 using idx_t = size_type<matrix_t>;
66 using T = type_t<matrix_t>;
67 using real_t = real_type<T>;
68
69 // Constants
70 const idx_t n = ncols(A);
71 const T zero(0);
74
75 // Check arguments
76 tlapack_check_false((n != 2 and n != 3));
77 tlapack_check_false(n != nrows(A));
78 tlapack_check_false((idx_t)size(v) != n);
79
80 if (n == 2) {
81 T w1 = beta1 * A(0, 0) - real(s1) * B(0, 0);
82 T w2 = beta1 * A(1, 0) - real(s1) * B(1, 0);
83 v[0] = w1;
84 v[1] = w2;
85 }
86 else {
87 // Calculate first shifted vector
88 T w1 = beta1 * A(0, 0) - real(s1) * B(0, 0);
89 T w2 = beta1 * A(1, 0) - real(s1) * B(1, 0);
90 real_t scale1 = sqrt(abs(w1)) * sqrt(abs(w2));
91 if (scale1 >= safmin and scale1 <= safmax) {
92 w1 = w1 / scale1;
93 w2 = w2 / scale1;
94 }
95 // Solve linear system
96 w2 = w2 / B(1, 1);
97 w1 = (w1 - B(0, 1) * w2) / B(0, 0);
98 real_t scale2 = sqrt(abs(w1)) * sqrt(abs(w2));
99 if (scale2 >= safmin and scale2 <= safmax) {
100 w1 = w1 / scale2;
101 w2 = w2 / scale2;
102 }
103 // Apply second shift
104 v[0] = beta2 * (A(0, 0) * w1 + A(0, 1) * w2) -
105 real(s2) * (B(0, 0) * w1 + B(0, 1) * w2);
106 v[1] = beta2 * (A(1, 0) * w1 + A(1, 1) * w2) -
107 real(s2) * (B(1, 0) * w1 + B(1, 1) * w2);
108 v[2] = beta2 * (A(2, 0) * w1 + A(2, 1) * w2) -
109 real(s2) * (B(2, 0) * w1 + B(2, 1) * w2);
110 // Account for imaginary part
111 v[0] = v[0] + imag(s1) * imag(s1) * B(0, 0) / scale1 / scale2;
112 // Check for overflow
113 if (abs(v[0]) > safmax or abs(v[1]) > safmax or abs(v[2]) > safmax) {
114 v[0] = zero;
115 v[1] = zero;
116 v[2] = zero;
117 }
118 }
119 return 0;
120}
121
122template <TLAPACK_MATRIX matrix_t,
123 TLAPACK_VECTOR vector_t,
124 enable_if_t<is_complex<type_t<matrix_t>>, bool> = true>
125int lahqz_shiftcolumn(const matrix_t& A,
126 const matrix_t& B,
127 vector_t& v,
128 complex_type<type_t<matrix_t>> s1,
129 complex_type<type_t<matrix_t>> s2,
130 type_t<matrix_t> beta1,
131 type_t<matrix_t> beta2)
132{
133 // Using
134 using idx_t = size_type<matrix_t>;
135 using T = type_t<matrix_t>;
136 using real_t = real_type<T>;
137
138 // Constants
139 const idx_t n = ncols(A);
140 const T zero(0);
141 const real_t safmin = safe_min<real_t>();
142 const real_t safmax = safe_max<real_t>();
143
144 // Check arguments
145 tlapack_check_false((n != 2 and n != 3));
146 tlapack_check_false(n != nrows(A));
147 tlapack_check_false((idx_t)size(v) != n);
148
149 if (n == 2) {
150 T w1 = beta1 * A(0, 0) - s1 * B(0, 0);
151 T w2 = beta1 * A(1, 0) - s1 * B(1, 0);
152 v[0] = w1;
153 v[1] = w2;
154 }
155 else {
156 // Calculate first shifted vector
157 T w1 = beta1 * A(0, 0) - s1 * B(0, 0);
158 T w2 = beta1 * A(1, 0) - s1 * B(1, 0);
159 real_t scale1 = sqrt(abs1(w1)) * sqrt(abs1(w2));
160 if (scale1 >= safmin and scale1 <= safmax) {
161 w1 = w1 / scale1;
162 w2 = w2 / scale1;
163 }
164 // Solve linear system
165 w2 = w2 / B(1, 1);
166 w1 = (w1 - B(0, 1) * w2) / B(0, 0);
167 real_t scale2 = sqrt(abs1(w1)) * sqrt(abs1(w2));
168 if (scale2 >= safmin and scale2 <= safmax) {
169 w1 = w1 / scale2;
170 w2 = w2 / scale2;
171 }
172 // Apply second shift
173 v[0] = beta2 * (A(0, 0) * w1 + A(0, 1) * w2) -
174 s2 * (B(0, 0) * w1 + B(0, 1) * w2);
175 v[1] = beta2 * (A(1, 0) * w1 + A(1, 1) * w2) -
176 s2 * (B(1, 0) * w1 + B(1, 1) * w2);
177 v[2] = beta2 * (A(2, 0) * w1 + A(2, 1) * w2) -
178 s2 * (B(2, 0) * w1 + B(2, 1) * w2);
179 // Check for overflow
180 if (abs1(v[0]) > safmax or abs1(v[1]) > safmax or abs1(v[2]) > safmax) {
181 v[0] = zero;
182 v[1] = zero;
183 v[2] = zero;
184 }
185 }
186 return 0;
187}
188
189} // namespace tlapack
190
191#endif // TLAPACK_LAHQZ_SHIFTCOLUMN_HH
constexpr real_type< T > real(const T &x) noexcept
Extends std::real() to real datatypes.
Definition utils.hpp:71
constexpr real_type< T > abs1(const T &x)
1-norm absolute value, |Re(x)| + |Im(x)|
Definition utils.hpp:133
constexpr real_type< T > imag(const T &x) noexcept
Extends std::imag() to real datatypes.
Definition utils.hpp:86
#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
int lahqz_shiftcolumn(const matrix_t &A, const matrix_t &B, vector_t &v, complex_type< type_t< matrix_t > > s1, complex_type< type_t< matrix_t > > s2, type_t< matrix_t > beta1, type_t< matrix_t > beta2)
Given a 2-by-2 or 3-by-3 matrix pencil (A,B), lahqz_shiftcolumn calculates a multiple of the product:...
Definition lahqz_shiftcolumn.hpp:56
#define tlapack_check_false(cond)
Throw an error if cond is true.
Definition exceptionHandling.hpp:113
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
typename traits::complex_type_traits< Types..., int >::type complex_type
The common complex type of the list of types.
Definition scalar_type_traits.hpp:188