rank-local.cpp
Go to the documentation of this file.
1 /*
2  * This file is a part of TiledArray.
3  * Copyright (C) 2020 Virginia Tech
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * Eduard Valeyev
19  *
20  * lapack.cpp
21  * Created: 16 October, 2020
22  *
23  */
24 
25 #include <TiledArray/math/blas.h>
26 #include <TiledArray/math/lapack.h>
28 
29 template <class F, typename... Args>
30 inline int ta_lapack_fortran_call(F f, Args... args) {
31  lapack_int info;
32  auto ptr = [](auto&& a) {
33  using T = std::remove_reference_t<decltype(a)>;
34  if constexpr (std::is_pointer_v<T>)
35  return a;
36  else
37  return &a;
38  };
39  f(ptr(args)..., &info);
40  return info;
41 }
42 
43 #define TA_LAPACK_ERROR(F) throw std::runtime_error("lapack::" #F " failed")
44 
45 #define TA_LAPACK_FORTRAN_CALL(F, ARGS...) \
46  ((ta_lapack_fortran_call(F, ARGS) == 0) || (TA_LAPACK_ERROR(F), 0))
47 
49 
52 #define TA_LAPACK_FORTRAN(name, args...) \
53  { \
54  using numeric_type = T; \
55  if constexpr (std::is_same_v<numeric_type, double>) \
56  TA_LAPACK_FORTRAN_CALL(d##name, args); \
57  else if constexpr (std::is_same_v<numeric_type, float>) \
58  TA_LAPACK_FORTRAN_CALL(s##name, args); \
59  else \
60  std::abort(); \
61  }
62 
64 #define TA_LAPACK(name, args...) \
65  ((::lapack::name(args) == 0) || (TA_LAPACK_ERROR(name), 0))
66 
68 
70 
71 template <typename T>
72 void cholesky(Matrix<T>& A) {
73  auto uplo = lapack::Uplo::Lower;
74  integer n = A.rows();
75  auto* a = A.data();
76  integer lda = n;
77  TA_LAPACK(potrf, uplo, n, a, lda);
78 }
79 
80 template <typename T>
82  auto uplo = lapack::Uplo::Lower;
83  auto diag = lapack::Diag::NonUnit;
84  integer n = A.rows();
85  auto* l = A.data();
86  integer lda = n;
87  TA_LAPACK(trtri, uplo, diag, n, l, lda);
88 }
89 
90 template <typename T>
92  auto uplo = lapack::Uplo::Lower;
93  integer n = A.rows();
94  integer nrhs = X.cols();
95  auto* a = A.data();
96  auto* b = X.data();
97  integer lda = n;
98  integer ldb = n;
99  TA_LAPACK(posv, uplo, n, nrhs, a, lda, b, ldb);
100 }
101 
102 template <typename T>
104  auto uplo = lapack::Uplo::Lower;
105  auto diag = lapack::Diag::NonUnit;
106  integer n = A.rows();
107  integer nrhs = X.cols();
108  auto* a = A.data();
109  auto* b = X.data();
110  integer lda = n;
111  integer ldb = n;
112  TA_LAPACK(trtrs, uplo, transpose, diag, n, nrhs, a, lda, b, ldb);
113 }
114 
115 template <typename T>
116 void heig(Matrix<T>& A, std::vector<T>& W) {
117  auto jobz = lapack::Job::Vec;
118  auto uplo = lapack::Uplo::Lower;
119  integer n = A.rows();
120  T* a = A.data();
121  integer lda = A.rows();
122  W.resize(n);
123  T* w = W.data();
124  TA_LAPACK(syev, jobz, uplo, n, a, lda, w);
125 }
126 
127 template <typename T>
128 void heig(Matrix<T>& A, Matrix<T>& B, std::vector<T>& W) {
129  integer itype = 1;
130  auto jobz = lapack::Job::Vec;
131  auto uplo = lapack::Uplo::Lower;
132  integer n = A.rows();
133  T* a = A.data();
134  integer lda = A.rows();
135  T* b = B.data();
136  integer ldb = B.rows();
137  W.resize(n);
138  T* w = W.data();
139  TA_LAPACK(sygv, itype, jobz, uplo, n, a, lda, b, ldb, w);
140 }
141 
142 template <typename T>
143 void svd(Job jobu, Job jobvt, Matrix<T>& A, std::vector<T>& S, Matrix<T>* U, Matrix<T>* VT) {
144  integer m = A.rows();
145  integer n = A.cols();
146  integer k = std::min(m, n);
147  T* a = A.data();
148  integer lda = A.rows();
149 
150  S.resize(k);
151  T* s = S.data();
152 
153  T* u = nullptr;
154  T* vt = nullptr;
155  integer ldu = 1, ldvt = 1;
156  if( (jobu == Job::SomeVec or jobu == Job::AllVec) and (not U) )
157  TA_LAPACK_ERROR("Requested out-of-place right singular vectors with null U input");
158  if( (jobvt == Job::SomeVec or jobvt == Job::AllVec) and (not VT) )
159  TA_LAPACK_ERROR("Requested out-of-place left singular vectors with null VT input");
160 
161  if( jobu == Job::SomeVec ) {
162  U->resize(m, k);
163  u = U->data();
164  ldu = m;
165  }
166 
167  if( jobu == Job::AllVec ) {
168  U->resize(m, m);
169  u = U->data();
170  ldu = m;
171  }
172 
173  if( jobvt == Job::SomeVec ) {
174  VT->resize(k, n);
175  vt = VT->data();
176  ldvt = k;
177  }
178 
179  if( jobvt == Job::AllVec ) {
180  VT->resize(n, n);
181  vt = VT->data();
182  ldvt = n;
183  }
184 
185  TA_LAPACK(gesvd, jobu, jobvt, m, n, a, lda, s, u, ldu, vt, ldvt);
186 }
187 
188 template <typename T>
190  integer n = A.rows();
191  integer nrhs = B.cols();
192  T* a = A.data();
193  integer lda = A.rows();
194  T* b = B.data();
195  integer ldb = B.rows();
196  std::vector<integer> ipiv(n);
197  TA_LAPACK(gesv, n, nrhs, a, lda, ipiv.data(), b, ldb);
198 }
199 
200 template <typename T>
201 void lu_inv(Matrix<T>& A) {
202  integer n = A.rows();
203  T* a = A.data();
204  integer lda = A.rows();
205  std::vector<integer> ipiv(n);
206  TA_LAPACK(getrf, n, n, a, lda, ipiv.data());
207  TA_LAPACK(getri, n, a, lda, ipiv.data());
208 }
209 
210 #define TA_LAPACK_EXPLICIT(MATRIX, VECTOR) \
211  template void cholesky(MATRIX&); \
212  template void cholesky_linv(MATRIX&); \
213  template void cholesky_solve(MATRIX&, MATRIX&); \
214  template void cholesky_lsolve(Op, MATRIX&, MATRIX&); \
215  template void heig(MATRIX&, VECTOR&); \
216  template void heig(MATRIX&, MATRIX&, VECTOR&); \
217  template void svd(Job,Job,MATRIX&, VECTOR&, MATRIX*, MATRIX*); \
218  template void lu_solve(MATRIX&, MATRIX&); \
219  template void lu_inv(MATRIX&);
220 
221 TA_LAPACK_EXPLICIT(Matrix<double>, std::vector<double>);
222 TA_LAPACK_EXPLICIT(Matrix<float>, std::vector<float>);
223 
224 } // namespace TiledArray::math::linalg::rank_local
void cholesky_solve(Matrix< T > &A, Matrix< T > &X)
Definition: rank-local.cpp:91
void cholesky_linv(Matrix< T > &A)
Definition: rank-local.cpp:81
int64_t integer
Definition: blas.h:44
void lu_solve(Matrix< T > &A, Matrix< T > &B)
Definition: rank-local.cpp:189
KroneckerDeltaTile< _N >::numeric_type min(const KroneckerDeltaTile< _N > &arg)
void svd(Job jobu, Job jobvt, Matrix< T > &A, std::vector< T > &S, Matrix< T > *U, Matrix< T > *VT)
Definition: rank-local.cpp:143
void transpose(InputOp &&input_op, OutputOp &&output_op, const std::size_t m, const std::size_t n, const std::size_t result_stride, Result *result, const std::size_t arg_stride, const Args *const ... args)
Matrix transpose and initialization.
Definition: transpose.h:178
#define TA_LAPACK_ERROR(F)
Definition: rank-local.cpp:43
::Eigen::Matrix< T, ::Eigen::Dynamic, ::Eigen::Dynamic, Options > Matrix
Definition: rank-local.h:16
TA_LAPACK_EXPLICIT(Matrix< double >, std::vector< double >)
int ta_lapack_fortran_call(F f, Args... args)
Definition: rank-local.cpp:30
#define TA_LAPACK(name, args...)
TA_LAPACK(fn,args) invoked lapack::fn directly and checks the return value.
Definition: rank-local.cpp:64
void heig(Matrix< T > &A, std::vector< T > &W)
Definition: rank-local.cpp:116
void cholesky_lsolve(Op transpose, Matrix< T > &A, Matrix< T > &X)
Definition: rank-local.cpp:103