ViennaCL - The Vienna Computing Library  1.6.1
Free open-source GPU-accelerated linear algebra and solver library.
qr_method_func.cpp
Go to the documentation of this file.
1 /* =========================================================================
2  Copyright (c) 2010-2014, Institute for Microelectronics,
3  Institute for Analysis and Scientific Computing,
4  TU Wien.
5  Portions of this software are copyright by UChicago Argonne, LLC.
6 
7  -----------------
8  ViennaCL - The Vienna Computing Library
9  -----------------
10 
11  Project Head: Karl Rupp rupp@iue.tuwien.ac.at
12 
13  (A list of authors and contributors can be found in the PDF manual)
14 
15  License: MIT (X11), see file LICENSE in the base directory
16 ============================================================================= */
17 
18 
23 /*
24 *
25 * Test file for qr-method
26 *
27 */
28 
29 // include necessary system headers
30 #include <iostream>
31 
32 #ifndef NDEBUG
33  #define NDEBUG
34 #endif
35 
36 #define VIENNACL_WITH_UBLAS
37 
38 #include "viennacl/scalar.hpp"
39 #include "viennacl/vector.hpp"
40 #include "viennacl/linalg/prod.hpp"
41 
42 #include <fstream>
43 #include <iomanip>
47 #include "Random.hpp"
48 
49 #define EPS 10.0e-3
50 
51 
52 namespace ublas = boost::numeric::ublas;
53 typedef float ScalarType;
54 
55 void read_matrix_size(std::fstream& f, std::size_t& sz);
56 
57 void read_matrix_size(std::fstream& f, std::size_t& sz)
58 {
59  if(!f.is_open())
60  {
61  throw std::invalid_argument("File is not opened");
62  }
63 
64  f >> sz;
65 }
66 template <typename MatrixLayout>
68 {
69  if(!f.is_open())
70  {
71  throw std::invalid_argument("File is not opened");
72  }
73 
74  boost::numeric::ublas::matrix<ScalarType> h_A(A.size1(), A.size2());
75 
76  for(std::size_t i = 0; i < h_A.size1(); i++) {
77  for(std::size_t j = 0; j < h_A.size2(); j++) {
78  ScalarType val = 0.0;
79  f >> val;
80  h_A(i, j) = val;
81  }
82  }
83 
84  viennacl::copy(h_A, A);
85 }
86 
88 
90 {
91  ublas::matrix<ScalarType> A(A_orig.size1(), A_orig.size2());
92  viennacl::copy(A_orig, A);
93  for (unsigned int i = 0; i < A.size1(); i++) {
94  for (unsigned int j = 0; j < A.size2(); j++)
95  std::cout << std::setprecision(6) << std::fixed << A(i, j) << "\t";
96  std::cout << std::endl;
97  }
98  std::cout << std::endl;
99 }
100 
101 void matrix_print(ublas::matrix<ScalarType>& A);
102 
103 void matrix_print(ublas::matrix<ScalarType>& A)
104 {
105  for (unsigned int i = 0; i < A.size1(); i++) {
106  for (unsigned int j = 0; j < A.size2(); j++)
107  std::cout << std::setprecision(6) << std::fixed << A(i, j) << "\t";
108  std::cout << std::endl;
109  }
110  std::cout << std::endl;
111 }
112 
113 void vector_print(std::vector<ScalarType>& v );
114 
115 void vector_print(std::vector<ScalarType>& v )
116 {
117  for (unsigned int i = 0; i < v.size(); i++)
118  std::cout << std::setprecision(6) << std::fixed << v[i] << ",\t";
119  std::cout << "\n";
120 }
121 
122 
123 template <typename MatrixType, typename VCLMatrixType>
124 bool check_for_equality(MatrixType const & ublas_A, VCLMatrixType const & vcl_A)
125 {
126  typedef typename MatrixType::value_type value_type;
127 
128  ublas::matrix<value_type> vcl_A_cpu(vcl_A.size1(), vcl_A.size2());
129  viennacl::backend::finish(); //workaround for a bug in APP SDK 2.7 on Trinity APUs (with Catalyst 12.8)
130  viennacl::copy(vcl_A, vcl_A_cpu);
131 
132  for (std::size_t i=0; i<ublas_A.size1(); ++i)
133  {
134  for (std::size_t j=0; j<ublas_A.size2(); ++j)
135  {
136  if (std::abs(ublas_A(i,j) - vcl_A_cpu(i,j)) > EPS * std::max(std::abs(ublas_A(i, j)), std::abs(vcl_A_cpu(i, j))))
137  {
138  std::cout << "Error at index (" << i << ", " << j << "): " << ublas_A(i,j) << " vs. " << vcl_A_cpu(i,j) << std::endl;
139  std::cout << std::endl << "TEST failed!" << std::endl;
140  return false;
141  }
142  }
143  }
144  std::cout << "PASSED!" << std::endl;
145  return true;
146 }
147 
148 template <typename VectorType>
149 bool check_for_equality(VectorType const & vec_A, VectorType const & vec_B)
150 {
151 
152  for (std::size_t i=0; i<vec_A.size(); ++i)
153  {
154  if (std::abs(vec_A[i] - vec_B[i]) > EPS)
155  {
156  std::cout << "Error at index (" << i << "): " << vec_A[i] << " vs " <<vec_B[i] << std::endl;
157  std::cout << std::endl << "TEST failed!" << std::endl;
158  return false;
159  }
160  }
161  std::cout << "PASSED!" << std::endl;
162  return true;
163 }
164 
165 void fill_vector(std::vector<ScalarType>& v);
166 
167 void fill_vector(std::vector<ScalarType>& v)
168 {
169  for (unsigned int i = 0; i < v.size(); ++i)
170  v[i] = random<ScalarType>();
171  //v[i] = i % 10 + 1;
172 }
173 
174 /*
175  *
176  * ------------Functions to be tested---------------
177  *
178  */
179 
180 
181 template <typename NumericT>
182 void house_update_A_left(ublas::matrix<NumericT> & A,
183  std::vector<NumericT> D,
184  unsigned int start)
185 {
186  NumericT ss = 0;
187 
188  std::size_t row_start = start + 1;
189  for(std::size_t i = 0; i < A.size2(); i++)
190  {
191  ss = 0;
192  for(std::size_t j = row_start; j < A.size1(); j++)
193  ss = ss +(D[j] * A(j, i));
194 
195  for(std::size_t j = row_start; j < A.size1(); j++)
196  A(j, i) = A(j, i) - (2 * D[j] * ss);
197  }
198 }
199 
200 template <typename NumericT>
201 void house_update_A_right(ublas::matrix<NumericT> & A,
202  std::vector<NumericT> D)
203 {
204  NumericT ss = 0;
205 
206  for(std::size_t i = 0; i < A.size1(); i++)
207  {
208  ss = 0;
209  for(std::size_t j = 0; j < A.size2(); j++)
210  ss = ss + (D[j] * A(i, j));
211 
212  NumericT sum_Av = ss;
213 
214  for(std::size_t j = 0; j < A.size2(); j++)
215  A(i, j) = A(i, j) - (2 * D[j] * sum_Av);
216  }
217 }
218 
219 
220 template <typename NumericT>
221 void house_update_QL(ublas::matrix<NumericT> & Q,
222  std::vector<NumericT> D,
223  std::size_t A_size1)
224 
225 {
226  NumericT beta = 2;
227  ublas::matrix<NumericT> ubl_P(A_size1, A_size1);
228  ublas::matrix<ScalarType> I = ublas::identity_matrix<ScalarType>(Q.size1());
229  ublas::matrix<NumericT> Q_temp(Q.size1(), Q.size2());
230 
231  for(std::size_t i = 0; i < Q.size1(); i++)
232  {
233  for(std::size_t j = 0; j < Q.size2(); j++)
234  {
235  Q_temp(i, j) = Q(i, j);
236  }
237  }
238 
239  ubl_P = ublas::identity_matrix<NumericT>(A_size1);
240 
241  //scaled_rank_1 update
242  for(std::size_t i = 0; i < A_size1; i++)
243  {
244  for(std::size_t j = 0; j < A_size1; j++)
245  {
246  ubl_P(i, j) = I(i, j) - beta * (D[i] * D[j]);
247  }
248  }
249  Q = ublas::prod(Q_temp, ubl_P);
250 }
251 
252 template <typename NumericT>
253 void givens_next(ublas::matrix<NumericT> & Q,
254  std::vector<NumericT> & tmp1,
255  std::vector<NumericT> & tmp2,
256  int l,
257  int m)
258 {
259  for(int i2 = m - 1; i2 >= l; i2--)
260  {
261  std::size_t i = static_cast<std::size_t>(i2);
262  for(std::size_t k = 0; k < Q.size1(); k++)
263  {
264  NumericT h = Q(k, i+1);
265  Q(k, i+1) = tmp2[i] * Q(k, i) + tmp1[i]*h;
266  Q(k, i) = tmp1[i] * Q(k, i) - tmp2[i]*h;
267  }
268  }
269 }
270 
271 
272 template <typename NumericT>
273 void copy_vec(ublas::matrix<NumericT>& A,
274  std::vector<NumericT> & V,
275  std::size_t row_start,
276  std::size_t col_start,
277  bool copy_col)
278 {
279  if(copy_col)
280  {
281  for(std::size_t i = row_start; i < A.size1(); i++)
282  {
283  V[i - row_start] = A(i, col_start);
284  }
285  }
286  else
287  {
288  for(std::size_t i = col_start; i < A.size1(); i++)
289  {
290  V[i - col_start] = A(row_start, i);
291  }
292  }
293 }
294 
295 template <typename NumericT>
296 void bidiag_pack(ublas::matrix<NumericT> & A,
297  std::vector<NumericT> & D,
298  std::vector<NumericT> & S)
299 
300 {
301  std::size_t size = std::min(D.size(), S.size());
302  std::size_t i = 0;
303  for(i = 0; i < size - 1; i++)
304  {
305  D[i] = A(i, i);
306  S[i + 1] = A(i, i + 1);
307  }
308  D[size - 1] = A(size - 1, size - 1);
309 }
310 
311 
312 template <typename MatrixLayout>
313 void test_qr_method_sym(const std::string& fn)
314 {
315  std::cout << "Reading..." << std::endl;
316  std::size_t sz;
317 
318  // read file
319  std::fstream f(fn.c_str(), std::fstream::in);
320  //read size of input matrix
321  read_matrix_size(f, sz);
322 
323  viennacl::matrix<ScalarType, MatrixLayout> vcl_A(sz, sz), vcl_Q(sz, sz);
324  viennacl::vector<ScalarType> vcl_D(sz), vcl_E(sz), vcl_F(sz), vcl_G(sz), vcl_H(sz);
325  std::vector<ScalarType> std_D(sz), std_E(sz), std_F(sz), std_G(sz), std_H(sz);
326  ublas::matrix<ScalarType> ubl_A(sz, sz), ubl_Q(sz, sz);
327 
328 
329  std::cout << "Testing matrix of size " << sz << "-by-" << sz << std::endl << std::endl;
330 
331  read_matrix_body(f, vcl_A);
332  f.close();
333  viennacl::copy(vcl_A, ubl_A);
334 
335  fill_vector(std_D);
336  copy(std_D, vcl_D);
337 //--------------------------------------------------------
338  std::cout << std::endl << "Testing house_update_left..." << std::endl;
339  viennacl::linalg::house_update_A_left(vcl_A, vcl_D, 0);
340  house_update_A_left(ubl_A, std_D, 0);
341 
342  if(!check_for_equality(ubl_A, vcl_A))
343  exit(EXIT_FAILURE);
344 //--------------------------------------------------------
345  std::cout << std::endl << "Testing house_update_right..." << std::endl;
346  copy(ubl_A, vcl_A);
347  copy(std_D, vcl_D);
349  house_update_A_right(ubl_A, std_D);
350 
351  if(!check_for_equality(ubl_A, vcl_A))
352  exit(EXIT_FAILURE);
353 //--------------------------------------------------------
354 
355  std::cout << std::endl << "Testing house_update_QL..." << std::endl;
356  ubl_Q = ublas::identity_matrix<ScalarType>(ubl_Q.size1());
357  copy(ubl_Q, vcl_Q);
358  copy(ubl_A, vcl_A);
359  copy(std_D, vcl_D);
360  viennacl::linalg::house_update_QL(vcl_Q, vcl_D, vcl_A.size1());
361  house_update_QL(ubl_Q, std_D, ubl_A.size1());
362  if(!check_for_equality(ubl_Q, vcl_Q))
363  exit(EXIT_FAILURE);
364 //--------------------------------------------------------
365 
366  std::cout << std::endl << "Testing givens next..." << std::endl;
367  fill_vector(std_E);
368  fill_vector(std_F);
369  copy(std_E, vcl_E);
370  copy(std_F, vcl_F);
371  copy(ubl_Q, vcl_Q);
372  copy(ubl_A, vcl_A);
373  viennacl::linalg::givens_next(vcl_Q, vcl_E, vcl_F, 2, 5);
374  givens_next(ubl_Q, std_E, std_F, 2, 5);
375  if(!check_for_equality(ubl_Q, vcl_Q))
376  exit(EXIT_FAILURE);
377 //--------------------------------------------------------
378  std::cout << std::endl << "Testing copy vec..." << std::endl;
379  viennacl::linalg::copy_vec(vcl_A, vcl_D, 0, 2, 1);
380  copy_vec(ubl_A, std_D, 0, 2, 1);
381  copy(vcl_D, std_E); //check for equality only for same vector types
382  if(!check_for_equality(std_D, std_E))
383  exit(EXIT_FAILURE);
384 
385 //--------------------------------------------------------
386  std::cout << std::endl << "Testing bidiag pack..." << std::endl;
387  viennacl::linalg::bidiag_pack(vcl_A, vcl_D, vcl_F);
388  vcl_F[0] = 0; // first element in superdiagonal is irrelevant.
389  bidiag_pack(ubl_A, std_G, std_H);
390  std_H[0] = 0;
391  copy(std_G, vcl_G);
392  copy(std_H, vcl_H);
393 
394  if(!check_for_equality(vcl_D, vcl_G))
395  exit(EXIT_FAILURE);
396  if(!check_for_equality(vcl_F, vcl_H))
397  exit(EXIT_FAILURE);
398 //--------------------------------------------------------
399 }
400 
401 int main()
402 {
403 
404  std::cout << std::endl << "Test qr_method_sym for row_major matrix" << std::endl;
405  test_qr_method_sym<viennacl::row_major>("../examples/testdata/eigen/symm5.example");
406 
407  std::cout << std::endl << "Test qr_method_sym for column_major matrix" << std::endl;
408  test_qr_method_sym<viennacl::column_major>("../examples/testdata/eigen/symm5.example");
409 
410 
411  std::cout << std::endl <<"--------TEST SUCCESSFULLY COMPLETED----------" << std::endl;
412 }
bool check_for_equality(MatrixType const &ublas_A, VCLMatrixType const &vcl_A)
void copy_vec(ublas::matrix< NumericT > &A, std::vector< NumericT > &V, std::size_t row_start, std::size_t col_start, bool copy_col)
Implementations of dense matrix related operations including matrix-vector products.
void copy_vec(matrix_base< SCALARTYPE > &A, vector_base< SCALARTYPE > &V, vcl_size_t row_start, vcl_size_t col_start, bool copy_col)
This function copies a row or a column from a matrix to a vector.
Generic interface for matrix-vector and matrix-matrix products. See viennacl/linalg/vector_operations...
void house_update_A_right(matrix_base< NumericT > &A, vector_base< NumericT > &D)
This function applies a householder transformation to a matrix: A <- A * P with a householder reflect...
void test_qr_method_sym(const std::string &fn)
void house_update_QL(matrix_base< NumericT > &Q, vector_base< NumericT > &D, vcl_size_t A_size1)
This function updates the matrix Q, which is needed for the computation of the eigenvectors.
void house_update_QL(ublas::matrix< NumericT > &Q, std::vector< NumericT > D, std::size_t A_size1)
void finish()
Synchronizes the execution. finish() will only return after all compute kernels (CUDA, OpenCL) have completed.
Definition: memory.hpp:54
A dense matrix class.
Definition: forwards.h:374
int main()
T max(const T &lhs, const T &rhs)
Maximum.
Definition: util.hpp:59
float ScalarType
void read_matrix_size(std::fstream &f, std::size_t &sz)
#define EPS
void house_update_A_right(ublas::matrix< NumericT > &A, std::vector< NumericT > D)
Common routines used for the QR method and SVD. Experimental.
vcl_size_t size(VectorType const &vec)
Generic routine for obtaining the size of a vector (ViennaCL, uBLAS, etc.)
Definition: size.hpp:144
void house_update_A_left(ublas::matrix< NumericT > &A, std::vector< NumericT > D, unsigned int start)
void fill_vector(std::vector< ScalarType > &v)
void givens_next(ublas::matrix< NumericT > &Q, std::vector< NumericT > &tmp1, std::vector< NumericT > &tmp2, int l, int m)
void bidiag_pack(matrix_base< NumericT > &A, VectorType &dh, VectorType &sh)
This function stores the diagonal and the superdiagonal of a matrix in two vectors.
result_of::size_type< T >::type start(T const &obj)
Definition: start.hpp:44
void house_update_A_left(matrix_base< NumericT > &A, vector_base< NumericT > &D, vcl_size_t start)
This function applies a householder transformation to a matrix. A <- P * A with a householder reflect...
size_type size2() const
Returns the number of columns.
Definition: matrix_def.hpp:217
void prod(const MatrixT1 &A, bool transposed_A, const MatrixT2 &B, bool transposed_B, MatrixT3 &C, ScalarT alpha, ScalarT beta)
size_type size1() const
Returns the number of rows.
Definition: matrix_def.hpp:215
void bidiag_pack(ublas::matrix< NumericT > &A, std::vector< NumericT > &D, std::vector< NumericT > &S)
Implementation of the QR method for eigenvalue computations. Experimental.
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 read_matrix_body(std::fstream &f, viennacl::matrix< ScalarType, MatrixLayout > &A)
float ScalarType
Definition: fft_1d.cpp:42
T min(const T &lhs, const T &rhs)
Minimum.
Definition: util.hpp:45
void matrix_print(viennacl::matrix< ScalarType > &A_orig)
Implementation of the ViennaCL scalar class.
void vector_print(std::vector< ScalarType > &v)
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.