<T>LAPACK 0.1.1
C++ Template Linear Algebra PACKage
Loading...
Searching...
No Matches
lantr.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_LANTR_HH
13#define TLAPACK_LANTR_HH
14
16
17namespace tlapack {
18
48template <TLAPACK_NORM norm_t,
49 TLAPACK_UPLO uplo_t,
50 TLAPACK_DIAG diag_t,
51 TLAPACK_SMATRIX matrix_t>
53{
54 using T = type_t<matrix_t>;
55 using real_t = real_type<T>;
56 using idx_t = size_type<matrix_t>;
58
59 // constants
60 const idx_t m = nrows(A);
61 const idx_t n = ncols(A);
62
63 // check arguments
64 tlapack_check_false(normType != Norm::Fro && normType != Norm::Inf &&
65 normType != Norm::Max && normType != Norm::One);
66 tlapack_check_false(uplo != Uplo::Lower && uplo != Uplo::Upper);
67 tlapack_check_false(diag != Diag::NonUnit && diag != Diag::Unit);
68
69 // quick return
70 if (m == 0 || n == 0) return real_t(0);
71
72 // Norm value
73 real_t norm(0);
74
75 if (normType == Norm::Max) {
76 if (diag == Diag::NonUnit) {
77 if (uplo == Uplo::Upper) {
78 for (idx_t j = 0; j < n; ++j) {
79 for (idx_t i = 0; i <= min(j, m - 1); ++i) {
80 real_t temp = abs(A(i, j));
81
82 if (temp > norm)
83 norm = temp;
84 else {
85 if (isnan(temp)) return temp;
86 }
87 }
88 }
89 }
90 else {
91 for (idx_t j = 0; j < n; ++j) {
92 for (idx_t i = j; i < m; ++i) {
93 real_t temp = abs(A(i, j));
94
95 if (temp > norm)
96 norm = temp;
97 else {
98 if (isnan(temp)) return temp;
99 }
100 }
101 }
102 }
103 }
104 else {
105 norm = real_t(1);
106 if (uplo == Uplo::Upper) {
107 for (idx_t j = 0; j < n; ++j) {
108 for (idx_t i = 0; i < min(j, m); ++i) {
109 real_t temp = abs(A(i, j));
110
111 if (temp > norm)
112 norm = temp;
113 else {
114 if (isnan(temp)) return temp;
115 }
116 }
117 }
118 }
119 else {
120 for (idx_t j = 0; j < n; ++j) {
121 for (idx_t i = j + 1; i < m; ++i) {
122 real_t temp = abs(A(i, j));
123
124 if (temp > norm)
125 norm = temp;
126 else {
127 if (isnan(temp)) return temp;
128 }
129 }
130 }
131 }
132 }
133 }
134 else if (normType == Norm::Inf) {
135 if (uplo == Uplo::Upper) {
136 for (idx_t i = 0; i < m; ++i) {
137 real_t sum(0);
138 if (diag == Diag::NonUnit)
139 for (idx_t j = i; j < n; ++j)
140 sum += abs(A(i, j));
141 else {
142 sum = real_t(1);
143 for (idx_t j = i + 1; j < n; ++j)
144 sum += abs(A(i, j));
145 }
146
147 if (sum > norm)
148 norm = sum;
149 else {
150 if (isnan(sum)) return sum;
151 }
152 }
153 }
154 else {
155 for (idx_t i = 0; i < m; ++i) {
156 real_t sum(0);
157 if (diag == Diag::NonUnit || i >= n)
158 for (idx_t j = 0; j <= min(i, n - 1); ++j)
159 sum += abs(A(i, j));
160 else {
161 sum = real_t(1);
162 for (idx_t j = 0; j < i; ++j)
163 sum += abs(A(i, j));
164 }
165
166 if (sum > norm)
167 norm = sum;
168 else {
169 if (isnan(sum)) return sum;
170 }
171 }
172 }
173 }
174 else if (normType == Norm::One) {
175 if (uplo == Uplo::Upper) {
176 for (idx_t j = 0; j < n; ++j) {
177 real_t sum(0);
178 if (diag == Diag::NonUnit || j >= m)
179 for (idx_t i = 0; i <= min(j, m - 1); ++i)
180 sum += abs(A(i, j));
181 else {
182 sum = real_t(1);
183 for (idx_t i = 0; i < j; ++i)
184 sum += abs(A(i, j));
185 }
186
187 if (sum > norm)
188 norm = sum;
189 else {
190 if (isnan(sum)) return sum;
191 }
192 }
193 }
194 else {
195 for (idx_t j = 0; j < n; ++j) {
196 real_t sum(0);
197 if (diag == Diag::NonUnit)
198 for (idx_t i = j; i < m; ++i)
199 sum += abs(A(i, j));
200 else {
201 sum = real_t(1);
202 for (idx_t i = j + 1; i < m; ++i)
203 sum += abs(A(i, j));
204 }
205
206 if (sum > norm)
207 norm = sum;
208 else {
209 if (isnan(sum)) return sum;
210 }
211 }
212 }
213 }
214 else {
215 real_t scale(1), sum(0);
216
217 if (uplo == Uplo::Upper) {
218 if (diag == Diag::NonUnit) {
219 for (idx_t j = 0; j < n; ++j)
220 lassq(slice(A, range(0, min(j + 1, m)), j), scale, sum);
221 }
222 else {
223 sum = real_t(min(m, n));
224 for (idx_t j = 1; j < n; ++j)
225 lassq(slice(A, range(0, min(j, m)), j), scale, sum);
226 }
227 }
228 else {
229 if (diag == Diag::NonUnit) {
230 for (idx_t j = 0; j < min(m, n); ++j)
231 lassq(slice(A, range(j, m), j), scale, sum);
232 }
233 else {
234 sum = real_t(min(m, n));
235 for (idx_t j = 0; j < min(m - 1, n); ++j)
236 lassq(slice(A, range(j + 1, m), j), scale, sum);
237 }
238 }
239 norm = scale * sqrt(sum);
240 }
241
242 return norm;
243}
244
245} // namespace tlapack
246
247#endif // TLAPACK_LANTR_HH
constexpr bool isnan(const T &x) noexcept
Extends std::isnan() to complex numbers.
Definition utils.hpp:125
#define TLAPACK_NORM
Macro for tlapack::concepts::Norm compatible with C++17.
Definition concepts.hpp:939
#define TLAPACK_DIAG
Macro for tlapack::concepts::Diag compatible with C++17.
Definition concepts.hpp:945
#define TLAPACK_UPLO
Macro for tlapack::concepts::Uplo compatible with C++17.
Definition concepts.hpp:942
#define TLAPACK_SMATRIX
Macro for tlapack::concepts::SliceableMatrix compatible with C++17.
Definition concepts.hpp:899
constexpr auto diag(T &A, int diagIdx=0) noexcept
Get the Diagonal of an Eigen Matrix.
Definition eigen.hpp:576
void lassq(const vector_t &x, real_type< type_t< vector_t > > &scale, real_type< type_t< vector_t > > &sumsq, abs_f absF)
Updates a sum of squares represented in scaled form.
Definition lassq.hpp:49
auto lantr(norm_t normType, uplo_t uplo, diag_t diag, const matrix_t &A)
Calculates the norm of a symmetric matrix.
Definition lantr.hpp:52
#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