ViennaCL - The Vienna Computing Library: viennacl/linalg/tql2.hpp Source File

ViennaCL - The Vienna Computing Library 1.7.1 Free open-source GPU-accelerated linear algebra and solver library. |

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
tql2.hpp
Go to the documentation of this file.
1 #ifndef VIENNACL_LINALG_TQL2_HPP
2 #define VIENNACL_LINALG_TQL2_HPP
3
4 /* =========================================================================
5 Copyright (c) 2010-2016, Institute for Microelectronics,
6 Institute for Analysis and Scientific Computing,
7 TU Wien.
8 Portions of this software are copyright by UChicago Argonne, LLC.
9
10 -----------------
11 ViennaCL - The Vienna Computing Library
12 -----------------
13
14 Project Head: Karl Rupp rupp@iue.tuwien.ac.at
15
16 (A list of authors and contributors can be found in the manual)
17
18 License: MIT (X11), see file LICENSE in the base directory
19 ============================================================================= */
20
26 #include "viennacl/vector.hpp"
27 #include "viennacl/matrix.hpp"
28 #include <iomanip>
29
30 #include "viennacl/linalg/qr-method-common.hpp"
31 #include "viennacl/linalg/prod.hpp"
32
33 namespace viennacl
34 {
35 namespace linalg
36 {
37 // Symmetric tridiagonal QL algorithm.
38 // This is derived from the Algol procedures tql1, by Bowdler, Martin, Reinsch, and Wilkinson,
39 // Handbook for Auto. Comp., Vol.ii-Linear Algebra, and the corresponding Fortran subroutine in EISPACK.
40 template <typename SCALARTYPE, typename VectorType>
41 void tql1(vcl_size_t n,
42 VectorType & d,
43 VectorType & e)
44 {
45 for (vcl_size_t i = 1; i < n; i++)
46 e[i - 1] = e[i];
47
48
49 e[n - 1] = 0;
50
51 SCALARTYPE f = 0.;
52 SCALARTYPE tst1 = 0.;
53 SCALARTYPE eps = static_cast<SCALARTYPE>(1e-6);
54
55
56 for (vcl_size_t l = 0; l < n; l++)
57 {
58 // Find small subdiagonal element.
59 tst1 = std::max<SCALARTYPE>(tst1, std::fabs(d[l]) + std::fabs(e[l]));
60 vcl_size_t m = l;
61 while (m < n)
62 {
63 if (std::fabs(e[m]) <= eps * tst1)
64 break;
65 m++;
66 }
67
68 // If m == l, d[l) is an eigenvalue, otherwise, iterate.
69 if (m > l)
70 {
71 vcl_size_t iter = 0;
72 do
73 {
74 iter = iter + 1; // (Could check iteration count here.)
75
76 // Compute implicit shift
77 SCALARTYPE g = d[l];
78 SCALARTYPE p = (d[l + 1] - g) / (2 * e[l]);
79 SCALARTYPE r = viennacl::linalg::detail::pythag<SCALARTYPE>(p, 1);
80 if (p < 0)
81 {
82 r = -r;
83 }
84
85 d[l] = e[l] / (p + r);
86 d[l + 1] = e[l] * (p + r);
87 SCALARTYPE h = g - d[l];
88 for (vcl_size_t i = l + 2; i < n; i++)
89 {
90 d[i] -= h;
91 }
92
93 f = f + h;
94
95 // Implicit QL transformation.
96 p = d[m];
97 SCALARTYPE c = 1;
98 SCALARTYPE s = 0;
99 for (int i = int(m - 1); i >= int(l); i--)
100 {
101 g = c * e[vcl_size_t(i)];
102 h = c * p;
103 r = viennacl::linalg::detail::pythag<SCALARTYPE>(p, e[vcl_size_t(i)]);
104 e[vcl_size_t(i) + 1] = s * r;
105 s = e[vcl_size_t(i)] / r;
106 c = p / r;
107 p = c * d[vcl_size_t(i)] - s * g;
108 d[vcl_size_t(i) + 1] = h + s * (c * g + s * d[vcl_size_t(i)]);
109 }
110 e[l] = s * p;
111 d[l] = c * p;
112 // Check for convergence.
113 }
114 while (std::fabs(e[l]) > eps * tst1);
115 }
116 d[l] = d[l] + f;
117 e[l] = 0;
118 }
119 }
120
121
122
123
124
125
126
127 // Symmetric tridiagonal QL algorithm.
128 // This is derived from the Algol procedures tql2, by Bowdler, Martin, Reinsch, and Wilkinson,
129 // Handbook for Auto. Comp., Vol.ii-Linear Algebra, and the corresponding Fortran subroutine in EISPACK.
130 template <typename SCALARTYPE, typename VectorType, typename F>
131 void tql2(matrix_base<SCALARTYPE, F> & Q,
132 VectorType & d,
133 VectorType & e)
134 {
135 vcl_size_t n = static_cast<vcl_size_t>(viennacl::traits::size1(Q));
136
137 //boost::numeric::ublas::vector<SCALARTYPE> cs(n), ss(n);
138 std::vector<SCALARTYPE> cs(n), ss(n);
139 viennacl::vector<SCALARTYPE> tmp1(n), tmp2(n);
140
141 for (vcl_size_t i = 1; i < n; i++)
142 e[i - 1] = e[i];
143
144 e[n - 1] = 0;
145
146 SCALARTYPE f = 0;
147 SCALARTYPE tst1 = 0;
148 SCALARTYPE eps = static_cast<SCALARTYPE>(viennacl::linalg::detail::EPS);
149
150 for (vcl_size_t l = 0; l < n; l++)
151 {
152 // Find small subdiagonal element.
153 tst1 = std::max<SCALARTYPE>(tst1, std::fabs(d[l]) + std::fabs(e[l]));
154 vcl_size_t m = l;
155 while (m < n)
156 {
157 if (std::fabs(e[m]) <= eps * tst1)
158 break;
159 m++;
160 }
161
162 // If m == l, d[l) is an eigenvalue, otherwise, iterate.
163 if (m > l)
164 {
165 vcl_size_t iter = 0;
166 do
167 {
168 iter = iter + 1; // (Could check iteration count here.)
169
170 // Compute implicit shift
171 SCALARTYPE g = d[l];
172 SCALARTYPE p = (d[l + 1] - g) / (2 * e[l]);
173 SCALARTYPE r = viennacl::linalg::detail::pythag<SCALARTYPE>(p, 1);
174 if (p < 0)
175 {
176 r = -r;
177 }
178
179 d[l] = e[l] / (p + r);
180 d[l + 1] = e[l] * (p + r);
181 SCALARTYPE dl1 = d[l + 1];
182 SCALARTYPE h = g - d[l];
183 for (vcl_size_t i = l + 2; i < n; i++)
184 {
185 d[i] -= h;
186 }
187
188 f = f + h;
189
190 // Implicit QL transformation.
191 p = d[m];
192 SCALARTYPE c = 1;
193 SCALARTYPE c2 = c;
194 SCALARTYPE c3 = c;
195 SCALARTYPE el1 = e[l + 1];
196 SCALARTYPE s = 0;
197 SCALARTYPE s2 = 0;
198 for (int i = int(m - 1); i >= int(l); i--)
199 {
200 c3 = c2;
201 c2 = c;
202 s2 = s;
203 g = c * e[vcl_size_t(i)];
204 h = c * p;
205 r = viennacl::linalg::detail::pythag(p, e[vcl_size_t(i)]);
206 e[vcl_size_t(i) + 1] = s * r;
207 s = e[vcl_size_t(i)] / r;
208 c = p / r;
209 p = c * d[vcl_size_t(i)] - s * g;
210 d[vcl_size_t(i) + 1] = h + s * (c * g + s * d[vcl_size_t(i)]);
211
212
213 cs[vcl_size_t(i)] = c;
214 ss[vcl_size_t(i)] = s;
215 }
216
217
218 p = -s * s2 * c3 * el1 * e[l] / dl1;
219 e[l] = s * p;
220 d[l] = c * p;
221
222 viennacl::copy(cs, tmp1);
223 viennacl::copy(ss, tmp2);
224
225 viennacl::linalg::givens_next(Q, tmp1, tmp2, int(l), int(m));
226
227 // Check for convergence.
228 }
229 while (std::fabs(e[l]) > eps * tst1);
230 }
231 d[l] = d[l] + f;
232 e[l] = 0;
233 }
234
235 // Sort eigenvalues and corresponding vectors.
236 /*
237 for (int i = 0; i < n-1; i++) {
238 int k = i;
239 SCALARTYPE p = d[i];
240 for (int j = i+1; j < n; j++) {
241 if (d[j] > p) {
242 k = j;
243 p = d[j);
244 }
245 }
246 if (k != i) {
247 d[k] = d[i];
248 d[i] = p;
249 for (int j = 0; j < n; j++) {
250 p = Q(j, i);
251 Q(j, i) = Q(j, k);
252 Q(j, k) = p;
253 }
254 }
255 }
256
257 */
258
259 }
260 } // namespace linalg
261 } // namespace viennacl
262 #endif
prod.hpp
Generic interface for matrix-vector and matrix-matrix products. See viennacl/linalg/vector_operations...
matrix.hpp
Implementation of the dense matrix class.
viennacl::traits::size1
vcl_size_t size1(MatrixType const &mat)
Generic routine for obtaining the number of rows of a matrix (ViennaCL, uBLAS, etc.)
Definition: size.hpp:163
viennacl::linalg::tql2
void tql2(matrix_base< SCALARTYPE, F > &Q, VectorType &d, VectorType &e)
Definition: tql2.hpp:131
viennacl::matrix_base
Definition: matrix_def.hpp:103
s2
viennacl::scalar< int > s2
Definition: global_variables.cpp:58
qr-method-common.hpp
Common routines used for the QR method and SVD. Experimental.
viennacl::vcl_size_t
std::size_t vcl_size_t
Definition: forwards.h:75
viennacl::vector
Definition: forwards.h:266
viennacl::linalg::detail::pythag
SCALARTYPE pythag(SCALARTYPE a, SCALARTYPE b)
Definition: qr-method-common.hpp:65
vector.hpp
The vector type with operator-overloads and proxy classes is defined here. Linear algebra operations ...
viennacl::copy
void copy(std::vector< NumericT > &cpu_vec, circulant_matrix< NumericT, AlignmentV > &gpu_mat)
Copies a circulant matrix from the std::vector to the OpenCL device (either GPU or multi-core CPU) ...
Definition: circulant_matrix.hpp:150
viennacl::linalg::tql1
void tql1(vcl_size_t n, VectorType &d, VectorType &e)
Definition: tql2.hpp:41
viennacl::linalg::givens_next
void givens_next(matrix_base< NumericT > &Q, vector_base< NumericT > &tmp1, vector_base< NumericT > &tmp2, int l, int m)
This function updates the matrix Q. It is part of the tql2 algorithm.
Definition: matrix_operations.hpp:1092