<T>LAPACK 0.1.1
C++ Template Linear Algebra PACKage
Loading...
Searching...
No Matches
lasy2.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_LASY2_HH
13#define TLAPACK_LASY2_HH
14
16#include "tlapack/blas/swap.hpp"
17
18namespace tlapack {
19
35template <
36 TLAPACK_MATRIX matrixX_t,
37 TLAPACK_MATRIX matrixT_t,
38 TLAPACK_MATRIX matrixB_t,
39 enable_if_t<is_real<type_t<matrixX_t>> && is_real<type_t<matrixT_t>> &&
40 is_real<type_t<matrixB_t>>,
41 bool> = true>
43 Op trans_r,
44 int isign,
45 const matrixT_t& TL,
46 const matrixT_t& TR,
47 const matrixB_t& B,
49 matrixX_t& X,
51{
52 using idx_t = size_type<matrixX_t>;
53 using T = type_t<matrixX_t>;
54
55 // Functor for creating new matrices of type matrix_t
57
58 const idx_t n1 = ncols(TL);
59 const idx_t n2 = ncols(TR);
60 const T eps = ulp<T>();
61 const T small_num = safe_min<T>() / eps;
62
63 const T zero(0);
64 const T one(1);
65 const T eight(8);
66
67 tlapack_check(isign == -1 or isign == 1);
68
69 // Quick return
70 scale = one;
71 xnorm = zero;
72 if (n1 == 0 or n2 == 0) return 0;
73
74 T sgn(isign);
75 int info = 0;
76
77 if (n1 == 1 and n2 == 1) {
78 T tau1 = TL(0, 0) + sgn * TR(0, 0);
79 T bet = abs(tau1);
80 if (bet < small_num) {
82 bet = small_num;
83 info = 1;
84 }
85 scale = one;
86 const T gam = abs(B(0, 0));
87 if (small_num * gam > bet) scale = one / gam;
88 X(0, 0) = (B(0, 0) * scale) / tau1;
89 xnorm = abs(X(0, 0));
90
91 return info;
92 }
93 if ((n1 == 2 and n2 == 1) or (n1 == 1 and n2 == 2)) {
95 "lasy2: not implemented for n1=2 and n2=1 or n1=1 and "
96 "n2=2");
97 return -1;
98 }
99 if (n1 == 2 and n2 == 2) {
100 // 2x2 blocks, build a 4x4 matrix
101 T btmp[4];
102 T tmp[4];
103 T T16_[4 * 4];
104 auto T16 = new_4by4_matrix(T16_);
105 idx_t jpiv[4];
106
107 T smin = max(max(abs(TR(0, 0)), abs(TR(0, 1))),
108 max(abs(TR(1, 0)), abs(TR(1, 1))));
109 smin = max(smin, max(max(abs(TL(0, 0)), abs(TL(0, 1))),
110 max(abs(TL(1, 0)), abs(TL(1, 1)))));
111 smin = max(eps * smin, small_num);
112
113 for (idx_t i = 0; i < 4; ++i)
114 for (idx_t j = 0; j < 4; ++j)
115 T16(i, j) = zero;
116
117 T16(0, 0) = TL(0, 0) + sgn * TR(0, 0);
118 T16(1, 1) = TL(1, 1) + sgn * TR(0, 0);
119 T16(2, 2) = TL(0, 0) + sgn * TR(1, 1);
120 T16(3, 3) = TL(1, 1) + sgn * TR(1, 1);
121
122 if (trans_l == Op::Trans) {
123 T16(0, 1) = TL(1, 0);
124 T16(1, 0) = TL(0, 1);
125 T16(2, 3) = TL(1, 0);
126 T16(3, 2) = TL(0, 1);
127 }
128 else {
129 T16(0, 1) = TL(0, 1);
130 T16(1, 0) = TL(1, 0);
131 T16(2, 3) = TL(0, 1);
132 T16(3, 2) = TL(1, 0);
133 }
134 if (trans_r == Op::Trans) {
135 T16(0, 2) = sgn * TR(0, 1);
136 T16(1, 3) = sgn * TR(0, 1);
137 T16(2, 0) = sgn * TR(1, 0);
138 T16(3, 1) = sgn * TR(1, 0);
139 }
140 else {
141 T16(0, 2) = sgn * TR(1, 0);
142 T16(1, 3) = sgn * TR(1, 0);
143 T16(2, 0) = sgn * TR(0, 1);
144 T16(3, 1) = sgn * TR(0, 1);
145 }
146 btmp[0] = B(0, 0);
147 btmp[1] = B(1, 0);
148 btmp[2] = B(0, 1);
149 btmp[3] = B(1, 1);
150
151 // Perform elimination with pivoting to solve 4x4 system
152 idx_t ipsv, jpsv;
153 for (idx_t i = 0; i < 3; ++i) {
154 ipsv = i;
155 jpsv = i;
156 // Do pivoting to get largest pivot element
157 T xmax = zero;
158 for (idx_t ip = i; ip < 4; ++ip) {
159 for (idx_t jp = i; jp < 4; ++jp) {
160 if (abs(T16(ip, jp)) >= xmax) {
161 xmax = abs(T16(ip, jp));
162 ipsv = ip;
163 jpsv = jp;
164 }
165 }
166 }
167 if (ipsv != i) {
168 auto row1 = row(T16, ipsv);
169 auto row2 = row(T16, i);
171 const T temp = btmp[i];
172 btmp[i] = btmp[ipsv];
173 btmp[ipsv] = temp;
174 }
175 if (jpsv != i) {
176 auto col1 = col(T16, jpsv);
177 auto col2 = col(T16, i);
179 }
180 jpiv[i] = jpsv;
181 if (abs(T16(i, i)) < smin) {
182 info = 1;
183 T16(i, i) = smin;
184 }
185 for (idx_t j = i + 1; j < 4; ++j) {
186 T16(j, i) = T16(j, i) / T16(i, i);
187 btmp[j] = btmp[j] - T16(j, i) * btmp[i];
188 for (idx_t k = i + 1; k < 4; ++k) {
189 T16(j, k) = T16(j, k) - T16(j, i) * T16(i, k);
190 }
191 }
192 }
193
194 if (abs(T16(3, 3)) < smin) {
195 info = 1;
196 T16(3, 3) = smin;
197 }
198 scale = one;
199 if ((eight * small_num) * abs(btmp[0]) > abs(T16(0, 0)) or
200 (eight * small_num) * abs(btmp[1]) > abs(T16(1, 1)) or
201 (eight * small_num) * abs(btmp[2]) > abs(T16(2, 2)) or
202 (eight * small_num) * abs(btmp[3]) > abs(T16(3, 3))) {
203 scale = (one / eight) / max(max(abs(btmp[0]), abs(btmp[1])),
204 max(abs(btmp[2]), abs(btmp[3])));
205 btmp[0] = btmp[0] * scale;
206 btmp[1] = btmp[1] * scale;
207 btmp[2] = btmp[2] * scale;
208 btmp[3] = btmp[3] * scale;
209 }
210 for (idx_t i = 0; i < 4; ++i) {
211 idx_t k = 3 - i;
212 T temp = one / T16(k, k);
213 tmp[k] = btmp[k] * temp;
214 for (idx_t j = k + 1; j < 4; ++j) {
215 tmp[k] = tmp[k] - (temp * T16(k, j)) * tmp[j];
216 }
217 }
218 for (idx_t i = 0; i < 3; ++i) {
219 if (jpiv[2 - i] != 2 - i) {
220 const T temp = tmp[2 - i];
221 tmp[2 - i] = tmp[jpiv[2 - i]];
222 tmp[jpiv[2 - i]] = temp;
223 }
224 }
225 X(0, 0) = tmp[0];
226 X(1, 0) = tmp[1];
227 X(0, 1) = tmp[2];
228 X(1, 1) = tmp[3];
229 xnorm = max(abs(tmp[0]) + abs(tmp[2]), abs(tmp[1]) + abs(tmp[3]));
230
231 return info;
232 }
233
234 return 0;
235}
236
237} // namespace tlapack
238
239#endif // TLAPACK_LASY2_HH
Op
Definition types.hpp:222
constexpr int sgn(const T &val)
Type-safe sgn function.
Definition utils.hpp:109
#define TLAPACK_MATRIX
Macro for tlapack::concepts::Matrix compatible with C++17.
Definition concepts.hpp:896
int lasy2(Op trans_l, Op trans_r, int isign, const matrixT_t &TL, const matrixT_t &TR, const matrixB_t &B, type_t< matrixX_t > &scale, matrixX_t &X, type_t< matrixX_t > &xnorm)
lasy2 solves the Sylvester matrix equation where the matrices are of order 1 or 2.
Definition lasy2.hpp:42
void swap(vectorX_t &x, vectorY_t &y)
Swap vectors, .
Definition swap.hpp:31
#define tlapack_check(cond)
Throw an error if cond is false.
Definition exceptionHandling.hpp:98
#define tlapack_error(info, detailedInfo)
Error handler.
Definition exceptionHandling.hpp:142
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