<T>LAPACK 0.1.1
C++ Template Linear Algebra PACKage
Loading...
Searching...
No Matches
rotg.hpp
Go to the documentation of this file.
1
3//
4// Copyright (c) 2017-2021, University of Tennessee. All rights reserved.
5// Copyright (c) 2021-2023, University of Colorado Denver. All rights reserved.
6//
7// This file is part of <T>LAPACK.
8// <T>LAPACK is free software: you can redistribute it and/or modify it under
9// the terms of the BSD 3-Clause license. See the accompanying LICENSE file.
10
11#ifndef TLAPACK_BLAS_ROTG_HH
12#define TLAPACK_BLAS_ROTG_HH
13
16
17namespace tlapack {
18
36template <TLAPACK_REAL T,
37 enable_if_t<is_real<T>, int> = 0,
38 disable_if_allow_optblas_t<T> = 0>
39void rotg(T& a, T& b, T& c, T& s)
40{
41 // Constants
42 const T one(1);
43 const T zero(0);
44
45 // Scaling constants
46 const T safmin = safe_min<T>();
47 const T safmax = safe_max<T>();
48
49 // Norms
50 const T anorm = abs(a);
51 const T bnorm = abs(b);
52
53 // quick return
54 if (bnorm == zero) {
55 c = one;
56 s = zero;
57 b = zero;
58 }
59 else if (anorm == zero) {
60 c = zero;
61 s = one;
62 a = b;
63 b = one;
64 }
65 else {
66 T scl = min(safmax, max(safmin, max(anorm, bnorm)));
67 T sigma((anorm > bnorm) ? sgn(a) : sgn(b));
68 T r = sigma * scl * sqrt((a / scl) * (a / scl) + (b / scl) * (b / scl));
69 c = a / r;
70 s = b / r;
71 a = r;
72 if (anorm > bnorm)
73 b = s;
74 else if (c != zero)
75 b = one / c;
76 else
77 b = one;
78 }
79}
80
103template <TLAPACK_COMPLEX T,
104 enable_if_t<is_complex<T>, int> = 0,
105 disable_if_allow_optblas_t<T> = 0>
106void rotg(T& a, const T& b, real_type<T>& c, T& s)
107{
108 using real_t = real_type<T>;
109
110 // Constants
111 const real_t one(1);
112 const real_t zero(0);
113
114 // Scaling constants
117 const real_t rtmin = sqrt(safmin / ulp<real_t>());
118 const real_t rtmax = sqrt(safmax * ulp<real_t>());
119
120 // quick return
121 if (b == zero) {
122 c = one;
123 s = zero;
124 return;
125 }
126
127 if (a == zero) {
128 c = zero;
129 real_t g1 = max(abs(real(b)), abs(imag(b)));
130 if (g1 > rtmin && g1 < rtmax) {
131 // Use unscaled algorithm
132 real_t g2 = real(b) * real(b) + imag(b) * imag(b);
133 real_t d = sqrt(g2);
134 s = conj(b) / d;
135 a = d;
136 }
137 else {
138 // Use scaled algorithm
139 real_t u = min(safmax, max(safmin, g1));
140 real_t uu = one / u;
141 T gs = b * uu;
142 real_t g2 = real(gs) * real(gs) + imag(gs) * imag(gs);
143 real_t d = sqrt(g2);
144 s = conj(gs) / d;
145 a = d * u;
146 }
147 }
148 else {
149 real_t f1 = max(abs(real(a)), abs(imag(a)));
150 real_t g1 = max(abs(real(b)), abs(imag(b)));
151 if (f1 > rtmin && f1 < rtmax && g1 > rtmin && g1 < rtmax) {
152 // Use unscaled algorithm
153 real_t f2 = real(a) * real(a) + imag(a) * imag(a);
154 real_t g2 = real(b) * real(b) + imag(b) * imag(b);
155 real_t h2 = f2 + g2;
156 real_t d = (f2 > rtmin && h2 < rtmax) ? sqrt(f2 * h2)
157 : sqrt(f2) * sqrt(h2);
158 real_t p = one / d;
159 c = f2 * p;
160 s = conj(b) * (a * p);
161 a *= h2 * p;
162 }
163 else {
164 // Use scaled algorithm
165 real_t u = min(safmax, max(safmin, max(f1, g1)));
166 real_t uu = one / u;
167 T gs = b * uu;
168 real_t g2 = real(gs) * real(gs) + imag(gs) * imag(gs);
169 real_t f2, h2, w;
170 T fs;
171 if (f1 * uu < rtmin) {
172 // a is not well-scaled when scaled by g1.
173 real_t v = min(safmax, max(safmin, f1));
174 real_t vv = one / v;
175 w = v * uu;
176 fs = a * vv;
177 f2 = real(fs) * real(fs) + imag(fs) * imag(fs);
178 h2 = f2 * w * w + g2;
179 }
180 else {
181 // Otherwise use the same scaling for a and b.
182 w = one;
183 fs = a * uu;
184 f2 = real(fs) * real(fs) + imag(fs) * imag(fs);
185 h2 = f2 + g2;
186 }
187 real_t d = (f2 > rtmin && h2 < rtmax) ? sqrt(f2 * h2)
188 : sqrt(f2) * sqrt(h2);
189 real_t p = one / d;
190 c = (f2 * p) * w;
191 s = conj(gs) * (fs * p);
192 a = (fs * (h2 * p)) * u;
193 }
194 }
195}
196
197#ifdef TLAPACK_USE_LAPACKPP
198
199template <TLAPACK_REAL T,
200 enable_if_t<is_real<T>, int> = 0,
201 enable_if_allow_optblas_t<T> = 0>
202void rotg(T& a, T& b, T& c, T& s)
203{
204 // Constants
205 const T zero = 0;
206 const T one = 1;
207 const T anorm = abs(a);
208 const T bnorm = abs(b);
209
210 T r;
211 ::lapack::lartg(a, b, &c, &s, &r);
212
213 // Return information on a and b:
214 a = r;
215 if (s == zero || c == zero || (anorm > bnorm))
216 b = s;
217 else if (c != zero)
218 b = one / c;
219 else
220 b = one;
221}
222
223template <TLAPACK_COMPLEX T,
224 enable_if_t<is_complex<T>, int> = 0,
225 enable_if_allow_optblas_t<T> = 0>
226void rotg(T& a, const T& b, real_type<T>& c, T& s)
227{
228 T r;
229 ::lapack::lartg(a, b, &c, &s, &r);
230 a = r;
231}
232
233#endif
234
235} // namespace tlapack
236
237#endif // #ifndef TLAPACK_BLAS_ROTG_HH
constexpr real_type< T > real(const T &x) noexcept
Extends std::real() to real datatypes.
Definition utils.hpp:71
constexpr T conj(const T &x) noexcept
Extends std::conj() to real datatypes.
Definition utils.hpp:100
constexpr real_type< T > imag(const T &x) noexcept
Extends std::imag() to real datatypes.
Definition utils.hpp:86
constexpr int sgn(const T &val)
Type-safe sgn function.
Definition utils.hpp:109
#define TLAPACK_COMPLEX
Macro for tlapack::concepts::Complex compatible with C++17.
Definition concepts.hpp:921
#define TLAPACK_REAL
Macro for tlapack::concepts::Real compatible with C++17.
Definition concepts.hpp:918
void rotg(T &a, T &b, T &c, T &s)
Construct plane rotation that eliminates b, such that:
Definition rotg.hpp:39
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