<T>LAPACK 0.1.1
C++ Template Linear Algebra PACKage
Loading...
Searching...
No Matches
rscl.hpp
Go to the documentation of this file.
1
3//
4// Copyright (c) 2021-2023, University of Colorado Denver. All rights reserved.
5//
6// This file is part of <T>LAPACK.
7// <T>LAPACK is free software: you can redistribute it and/or modify it under
8// the terms of the BSD 3-Clause license. See the accompanying LICENSE file.
9
10#ifndef TLAPACK_RSCL_HH
11#define TLAPACK_RSCL_HH
12
14#include "tlapack/blas/scal.hpp"
16
17namespace tlapack {
18
19template <TLAPACK_VECTOR vector_t,
20 TLAPACK_REAL alpha_t,
21 enable_if_t<is_real<alpha_t>, int> = 0>
22void rscl(const alpha_t& alpha, vector_t& x)
23{
25
26 // constants
29 const real_t r = abs(alpha);
30
31 if (r > safeMax) {
32 scal(safeMin, x);
33 scal(safeMax / alpha, x);
34 }
35 else if (r < safeMin) {
36 scal(safeMin / alpha, x);
37 scal(safeMax, x);
38 }
39 else
40 scal(real_t(1) / alpha, x);
41}
42
72template <TLAPACK_VECTOR vector_t,
73 TLAPACK_COMPLEX alpha_t,
74 enable_if_t<is_complex<alpha_t>, int> = 0>
75void rscl(const alpha_t& alpha, vector_t& x)
76{
77 using real_t = real_type<alpha_t>;
78
79 const real_t safeMax = safe_max<real_t>();
80 const real_t safeMin = safe_min<real_t>();
81 const real_t zero(0);
82 const real_t one(1);
83
84 const real_t alphaR = real(alpha);
85 const real_t alphaI = imag(alpha);
86 const real_t absR = abs(alphaR);
87 const real_t absI = abs(alphaI);
88
89 if (alphaI == zero) {
90 // If alpha is real, then we can use another routine.
91 // std::cout << "absI == zero" << std::endl;
92 rscl(alphaR, x);
93 }
94
95 else if (alphaR == zero) {
96 // If alpha has a zero real part, then we follow the same rules as if
97 // alpha were real.
98 if (absI > safeMax) {
99 scal(safeMin, x);
100 scal(alpha_t(zero, -safeMax / alphaI), x);
101 }
102 else if (absI < safeMin) {
103 scal(alpha_t(zero, -safeMin / alphaI), x);
104 scal(safeMax, x);
105 }
106 else
107 scal(alpha_t(zero, -one / alphaI), x);
108 }
109
110 else {
111 // The following numbers can be computed.
112 // They are the inverse of the real and imaginary parts of 1/alpha.
113 // Note that a and b are always different from zero.
114 // NaNs are only possible if either:
115 // 1. alphaR or alphaI is NaN.
116 // 2. alphaR and alphaI are both infinite, in which case it makes sense
117 // to propagate a NaN.
118 real_t a = alphaR + alphaI * (alphaI / alphaR);
119 real_t b = alphaI + alphaR * (alphaR / alphaI);
120
121 if (abs(a) < safeMin || abs(b) < safeMin) {
122 // This means that both alphaR and alphaI are very small.
123 scal(alpha_t(safeMin / a, -safeMin / b), x);
124 scal(safeMax, x);
125 }
126 else if (abs(a) > safeMax || abs(b) > safeMax) {
127 if (isinf(alphaR) || isinf(alphaI)) {
128 // This means that a and b are both Inf. No need for scaling.
129 // Propagates zero.
130 scal(alpha_t(one / a, -one / b), x);
131 }
132 else {
133 scal(safeMin, x);
134 if (isinf(a) || isinf(b)) {
135 // Infs were generated. We do proper scaling to avoid them.
136 if (absR >= absI) {
137 // |a| <= |b|
138 a = (safeMin * alphaR) +
139 safeMin * (alphaI * (alphaI / alphaR));
140 b = (safeMin * alphaI) +
141 alphaR * ((safeMin * alphaR) / alphaI);
142 }
143 else {
144 // |a| > |b|
145 a = (safeMin * alphaR) +
146 alphaI * ((safeMin * alphaI) / alphaR);
147 b = (safeMin * alphaI) +
148 safeMin * (alphaR * (alphaR / alphaI));
149 }
150 scal(alpha_t(one / a, -one / b), x);
151 }
152 else {
153 scal(alpha_t(safeMax / a, -safeMax / b), x);
154 }
155 }
156 }
157 else {
158 // No overflow or underflow.
159 scal(alpha_t(one / a, -one / b), x);
160 }
161 }
162}
163
164} // namespace tlapack
165
166#endif // TLAPACK_RSCL_HH
constexpr bool isinf(const T &x) noexcept
Extends std::isinf() to complex numbers.
Definition utils.hpp:117
#define TLAPACK_COMPLEX
Macro for tlapack::concepts::Complex compatible with C++17.
Definition concepts.hpp:921
#define TLAPACK_VECTOR
Macro for tlapack::concepts::Vector compatible with C++17.
Definition concepts.hpp:906
#define TLAPACK_REAL
Macro for tlapack::concepts::Real compatible with C++17.
Definition concepts.hpp:918
void rscl(const alpha_t &alpha, vector_t &x)
Scale vector by the reciprocal of a constant, .
Definition rscl.hpp:22
void scal(const alpha_t &alpha, vector_t &x)
Scale vector by constant, .
Definition scal.hpp:30
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