ViennaCL - The Vienna Computing Library  1.6.1
Free open-source GPU-accelerated linear algebra and solver library.
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-2014, 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 PDF 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 
31 #include "viennacl/linalg/prod.hpp"
32 
33 namespace viennacl
34 {
35 namespace linalg
36 {
37 
38 // Symmetric tridiagonal QL algorithm.
39 // This is derived from the Algol procedures tql2, by Bowdler, Martin, Reinsch, and Wilkinson,
40 // Handbook for Auto. Comp., Vol.ii-Linear Algebra, and the corresponding Fortran subroutine in EISPACK.
41 template <typename SCALARTYPE, typename VectorType, typename F>
43  VectorType & d,
44  VectorType & e)
45 {
47 
48  //boost::numeric::ublas::vector<SCALARTYPE> cs(n), ss(n);
49  std::vector<SCALARTYPE> cs(n), ss(n);
50  viennacl::vector<SCALARTYPE> tmp1(n), tmp2(n);
51 
52  for (vcl_size_t i = 1; i < n; i++)
53  e[i - 1] = e[i];
54 
55  e[n - 1] = 0;
56 
57  SCALARTYPE f = 0;
58  SCALARTYPE tst1 = 0;
59  SCALARTYPE eps = static_cast<SCALARTYPE>(viennacl::linalg::detail::EPS);
60 
61  for (vcl_size_t l = 0; l < n; l++)
62  {
63  // Find small subdiagonal element.
64  tst1 = std::max<SCALARTYPE>(tst1, std::fabs(d[l]) + std::fabs(e[l]));
65  vcl_size_t m = l;
66  while (m < n)
67  {
68  if (std::fabs(e[m]) <= eps * tst1)
69  break;
70  m++;
71  }
72 
73  // If m == l, d[l) is an eigenvalue, otherwise, iterate.
74  if (m > l)
75  {
76  int iter = 0;
77  do
78  {
79  iter = iter + 1; // (Could check iteration count here.)
80 
81  // Compute implicit shift
82  SCALARTYPE g = d[l];
83  SCALARTYPE p = (d[l + 1] - g) / (2 * e[l]);
84  SCALARTYPE r = viennacl::linalg::detail::pythag<SCALARTYPE>(p, 1);
85  if (p < 0)
86  {
87  r = -r;
88  }
89 
90  d[l] = e[l] / (p + r);
91  d[l + 1] = e[l] * (p + r);
92  SCALARTYPE dl1 = d[l + 1];
93  SCALARTYPE h = g - d[l];
94  for (vcl_size_t i = l + 2; i < n; i++)
95  {
96  d[i] -= h;
97  }
98 
99  f = f + h;
100 
101  // Implicit QL transformation.
102  p = d[m];
103  SCALARTYPE c = 1;
104  SCALARTYPE c2 = c;
105  SCALARTYPE c3 = c;
106  SCALARTYPE el1 = e[l + 1];
107  SCALARTYPE s = 0;
108  SCALARTYPE s2 = 0;
109  for (int i2 = int(m) - 1; i2 >= int(l); i2--)
110  {
111  vcl_size_t i = vcl_size_t(i2);
112  c3 = c2;
113  c2 = c;
114  s2 = s;
115  g = c * e[i];
116  h = c * p;
118  e[i + 1] = s * r;
119  s = e[i] / r;
120  c = p / r;
121  p = c * d[i] - s * g;
122  d[i + 1] = h + s * (c * g + s * d[i]);
123 
124 
125  cs[i] = c;
126  ss[i] = s;
127  }
128 
129 
130  p = -s * s2 * c3 * el1 * e[l] / dl1;
131  e[l] = s * p;
132  d[l] = c * p;
133 
134  viennacl::copy(cs, tmp1);
135  viennacl::copy(ss, tmp2);
136 
137  viennacl::linalg::givens_next(Q, tmp1, tmp2, int(l), int(m));
138 
139  // Check for convergence.
140  }
141  while (std::fabs(e[l]) > eps * tst1);
142  }
143  d[l] = d[l] + f;
144  e[l] = 0;
145  }
146 
147  // Sort eigenvalues and corresponding vectors.
148 /*
149  for (int i = 0; i < n-1; i++) {
150  int k = i;
151  SCALARTYPE p = d[i];
152  for (int j = i+1; j < n; j++) {
153  if (d[j] > p) {
154  k = j;
155  p = d[j);
156  }
157  }
158  if (k != i) {
159  d[k] = d[i];
160  d[i] = p;
161  for (int j = 0; j < n; j++) {
162  p = Q(j, i);
163  Q(j, i) = Q(j, k);
164  Q(j, k) = p;
165  }
166  }
167  }
168 
169 */
170 
171 }
172 } // namespace linalg
173 } // namespace viennacl
174 #endif
Generic interface for matrix-vector and matrix-matrix products. See viennacl/linalg/vector_operations...
Implementation of the dense matrix class.
vcl_size_t size1(MatrixType const &mat)
Generic routine for obtaining the number of rows of a matrix (ViennaCL, uBLAS, etc.)
Definition: size.hpp:216
void tql2(matrix_base< SCALARTYPE, F > &Q, VectorType &d, VectorType &e)
Definition: tql2.hpp:42
viennacl::scalar< int > s2
Main namespace in ViennaCL. Holds all the basic types such as vector, matrix, etc. and defines operations upon them.
Definition: cpu_ram.hpp:29
Common routines used for the QR method and SVD. Experimental.
std::size_t vcl_size_t
Definition: forwards.h:74
SCALARTYPE pythag(SCALARTYPE a, SCALARTYPE b)
The vector type with operator-overloads and proxy classes is defined here. Linear algebra operations ...
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) ...
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.