fml  0.1-0
Fused Matrix Library
eigen.hh
1 // This file is part of fml which is released under the Boost Software
2 // License, Version 1.0. See accompanying file LICENSE or copy at
3 // https://www.boost.org/LICENSE_1_0.txt
4 
5 #ifndef FML_GPU_LINALG_EIGEN_H
6 #define FML_GPU_LINALG_EIGEN_H
7 #pragma once
8 
9 
10 #include <stdexcept>
11 
12 #include "../../_internals/linalgutils.hh"
13 
14 #include "../arch/arch.hh"
15 
16 #include "../internals/gpuscalar.hh"
17 
18 #include "../copy.hh"
19 #include "../gpumat.hh"
20 #include "../gpuvec.hh"
21 
22 #include "internals/err.hh"
23 
24 
25 namespace fml
26 {
27 namespace linalg
28 {
29  namespace
30  {
31  template <typename REAL>
32  int eig_sym_internals(const bool only_values, gpumat<REAL> &x,
33  gpuvec<REAL> &values, gpumat<REAL> &vectors)
34  {
35  if (!x.is_square())
36  throw std::runtime_error("'x' must be a square matrix");
37 
38  auto c = x.get_card();
39 
40  len_t n = x.nrows();
41  values.resize(n);
42 
43  cusolverEigMode_t jobz;
44  if (only_values)
45  jobz = CUSOLVER_EIG_MODE_NOVECTOR;
46  else
47  jobz = CUSOLVER_EIG_MODE_VECTOR;
48 
49  int lwork;
50  gpulapack_status_t check = gpulapack::syevd_buflen(c->lapack_handle(), jobz,
51  GPUBLAS_FILL_L, n, x.data_ptr(), n, values.data_ptr(), &lwork);
52  gpulapack::err::check_ret(check, "syevd_bufferSize");
53 
54  gpuvec<REAL> work(c, lwork);
55 
56  int info = 0;
57  gpuscalar<int> info_device(c, info);
58 
59  check = gpulapack::syevd(c->lapack_handle(), jobz, GPUBLAS_FILL_L,
60  n, x.data_ptr(), n, values.data_ptr(), work.data_ptr(), lwork,
61  info_device.data_ptr());
62 
63  info_device.get_val(&info);
64  gpulapack::err::check_ret(check, "syevd");
65  fml::linalgutils::check_info(info, "syevd");
66 
67  if (!only_values)
68  {
69  vectors.resize(n, n);
70  copy::gpu2gpu(x, vectors);
71  }
72 
73  return info;
74  }
75  }
76 
77 
78 
99  template <typename REAL>
101  {
102  err::check_card(x, values);
103  gpumat<REAL> ignored(x.get_card());
104 
105  int info = eig_sym_internals(true, x, values, ignored);
106  fml::linalgutils::check_info(info, "syevd");
107  }
108 
110  template <typename REAL>
111  void eigen_sym(gpumat<REAL> &x, gpuvec<REAL> &values, gpumat<REAL> &vectors)
112  {
113  err::check_card(x, values, values);
114 
115  int info = eig_sym_internals(false, x, values, vectors);
116  fml::linalgutils::check_info(info, "syevd");
117  }
118 }
119 }
120 
121 
122 #endif
fml::gpuvec
Vector class for data held on a single GPU.
Definition: gpuvec.hh:32
fml::copy::gpu2gpu
void gpu2gpu(const gpuvec< REAL_IN > &gpu_in, gpuvec< REAL_OUT > &gpu_out)
Copy data from a GPU object to another.
Definition: copy.hh:203
fml
Core namespace.
Definition: dimops.hh:10
fml::linalg::eigen_sym
void eigen_sym(cpumat< REAL > &x, cpuvec< REAL > &values)
Compute the eigenvalues and optionally the eigenvectors for a symmetric matrix.
Definition: eigen.hh:95
fml::gpumat
Matrix class for data held on a single GPU.
Definition: gpumat.hh:35