matrix.cpp
1 /***************************************************************************
2  Copyright (C) 2002-2015 Kentaro Kitagawa
3  kitagawa@phys.s.u-tokyo.ac.jp
4 
5  This program is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  You should have received a copy of the GNU Library General
11  Public License and a list of authors along with this program;
12  see the files COPYING and AUTHORS.
13 ***************************************************************************/
14 #include "matrix.h"
15 
16 #ifdef HAVE_LAPACK
17 
18 #include <boost/numeric/ublas/io.hpp>
19 #include <boost/numeric/ublas/matrix_proxy.hpp>
20 
21 typedef int LPKint;
22 typedef double LPKdoublereal;
23 typedef struct {double r, i;} LPKdoublecomplex;
24 extern "C" int zheevr_(char *jobz, char *range, char *uplo, LPKint *n,
25  LPKdoublecomplex *a, LPKint *lda, LPKdoublereal *vl, LPKdoublereal *vu,
26  LPKint *il, LPKint *iu, LPKdoublereal *abstol, LPKint *m, LPKdoublereal *
27  w, LPKdoublecomplex *z, LPKint *ldz, LPKint *isuppz, LPKdoublecomplex *
28  work, LPKint *lwork, LPKdoublereal *rwork, LPKint *lrwork, LPKint *
29  iwork, LPKint *liwork, LPKint *info);
30 
31 template <typename T, typename A>
32 inline void
33 subst(T &y, const A &x) {
34  y = x;
35 }
36 inline void
37 subst(LPKdoublecomplex &y, const std::complex<double> &x) {
38  y.r = std::real(x);
39  y.i = std::imag(x);
40 }
41 inline void
42 subst(std::complex<double> &y, const LPKdoublecomplex &x) {
43  y = std::complex<double>(x.r, x.i);
44 }
45 
46 template <typename T, typename LPKT>
47 void cmat2lpk(const ublas::matrix<T> &a, ublas::vector<LPKT>& lpk) {
48  lpk.resize(a.size1() * a.size2());
49  LPKT *plpk = &lpk[0];
50  for(int i = 0; i < a.size2(); i++) {
51  ublas::matrix_column<const ublas::matrix<T> > acol(a, i);
52  for(int j = 0; j < acol.size(); j++)
53  subst(*plpk++, acol(j));
54  }
55 }
56 template <typename T, typename LPKT>
57 void lpk2cmat(const ublas::vector<LPKT>& lpk, ublas::matrix<T> &a) {
58  assert(a.size1() * a.size2() == lpk.size());
59  const LPKT *plpk = &lpk[0];
60  for(int i = 0; i < a.size2(); i++) {
61  ublas::matrix_column<ublas::matrix<std::complex<double> > > acol(a, i);
62  for(int j = 0; j < acol.size(); j++)
63  subst(acol(j), *plpk++);
64  }
65 }
66 template <typename T, typename LPKT>
67 void lpk2cvec(const ublas::vector<LPKT>& lpk, ublas::vector<T> &a) {
68  a.resize(lpk.size());
69  const LPKT *plpk = &lpk[0];
70  for(int i = 0; i < a.size(); i++) {
71  subst(a[i], *plpk++);
72  }
73 }
74 
75 void eigHermiteRRR(const ublas::matrix<std::complex<double> > &a_org,
76  ublas::vector<double> &lambda, ublas::matrix<std::complex<double> > &v,
77  double tol) {
78  LPKint n = a_org.size2();
79  LPKint lda = a_org.size1();
80  assert(lda >= n);
81  LPKint ldz = n;
82  ublas::vector<LPKdoublecomplex> a(n*lda), z(n*ldz);
83  ublas::vector<LPKdoublereal> w(n);
84  ublas::vector<LPKint> isuppz(2*n);
85 
86  cmat2lpk(a_org, a);
87 
88  LPKint lwork = -1, liwork = -1, lrwork = -1;
89  ublas::vector<LPKdoublecomplex> work(1);
90  ublas::vector<LPKdoublereal> rwork(1);
91  ublas::vector<LPKint> iwork(1);
92 
93  LPKint info = 0, numret;
94  LPKint il, iu;
95  LPKdoublereal vl, vu;
96  char cv = 'V', ca = 'A', cu = 'U';
97  int ret = zheevr_(&cv, &ca, &cu, &n, &a[0], &lda,
98  &vl, &vu, &il, &iu, &tol, &numret, &w[0], &z[0], &ldz,
99  &isuppz[0], &work[0], &lwork, &rwork[0], &lrwork, &iwork[0], &liwork, &info);
100  assert(info == 0);
101  lwork = lrint(work[0].r);
102  work.resize(lwork);
103  lrwork = lrint(rwork[0]);
104  rwork.resize(lrwork);
105  liwork = iwork[0];
106  iwork.resize(liwork);
107  ret = zheevr_(&cv, &ca, &cu, &n, &a[0], &lda,
108  &vl, &vu, &il, &iu, &tol, &numret, &w[0], &z[0], &ldz,
109  &isuppz[0], &work[0], &lwork, &rwork[0], &lrwork, &iwork[0], &liwork, &info);
110  assert(info == 0);
111 
112  lpk2cvec(w, lambda);
113  v.resize(n, ldz);
114  lpk2cmat(z, v);
115 }
116 #endif //HAVE_LAPACK
117 

Generated for KAME4 by  doxygen 1.8.3