7 #ifndef UPPER_HESSENBERG_EIGEN_H
8 #define UPPER_HESSENBERG_EIGEN_H
14 #include "LapackWrapperExtra.h"
26 template <
typename Scalar =
double>
30 typedef arma::Mat<Scalar> Matrix;
31 typedef arma::Col<Scalar> Vector;
32 typedef arma::Row<Scalar> RowVector;
34 typedef std::complex<Scalar> Complex;
35 typedef arma::Mat<Complex> ComplexMatrix;
36 typedef arma::Col<Complex> ComplexVector;
46 static bool is_real(Complex v, Scalar eps)
48 return std::abs(v.imag()) <= eps;
70 n(mat.n_rows), computed(false)
86 throw std::invalid_argument(
"UpperHessenbergEigen: matrix must be square");
96 int want_T = 1, want_Z = 1;
97 int ilo = 1, ihi = n, iloz = 1, ihiz = n;
98 Scalar *wr =
new Scalar[n];
99 Scalar *wi =
new Scalar[n];
101 arma::lapack::lahqr(&want_T, &want_Z, &n, &ilo, &ihi,
102 mat_T.memptr(), &n, wr, wi, &iloz, &ihiz,
103 mat_Z.memptr(), &n, &info);
105 for(
int i = 0; i < n; i++)
107 evals[i] = Complex(wr[i], wi[i]);
113 throw std::logic_error(
"Lapack lahqr: failed to compute all the eigenvalues");
115 char side =
'R', howmny =
'B';
116 Scalar *work =
new Scalar[3 * n];
119 arma::lapack::trevc(&side, &howmny, (
int*) NULL, &n, mat_T.memptr(), &n,
120 (Scalar*) NULL, &n, mat_Z.memptr(), &n, &n, &m, work, &info);
124 throw std::invalid_argument(
"Lapack trevc: illegal value");
138 throw std::logic_error(
"UpperHessenbergEigen: need to call compute() first");
152 throw std::logic_error(
"UpperHessenbergEigen: need to call compute() first");
154 Scalar prec = std::pow(std::numeric_limits<Scalar>::epsilon(), Scalar(2.0) / 3);
155 ComplexMatrix evecs(n, n);
156 Complex *col_ptr = evecs.memptr();
157 for(
int i = 0; i < n; i++)
159 if(is_real(evals[i], prec))
162 Scalar z_norm = arma::norm(mat_Z.col(i));
163 for(
int j = 0; j < n; j++)
165 col_ptr[j] = Complex(mat_Z(j, i) / z_norm, 0);
171 Scalar r2 = arma::dot(mat_Z.col(i), mat_Z.col(i));
172 Scalar i2 = arma::dot(mat_Z.col(i + 1), mat_Z.col(i + 1));
173 Scalar z_norm = std::sqrt(r2 + i2);
174 Scalar *z_ptr = mat_Z.colptr(i);
175 for(
int j = 0; j < n; j++)
177 col_ptr[j] = Complex(z_ptr[j] / z_norm, z_ptr[j + n] / z_norm);
178 col_ptr[j + n] = std::conj(col_ptr[j]);
192 #endif // UPPER_HESSENBERG_EIGEN_H
UpperHessenbergEigen(const Matrix &mat)
void compute(const Matrix &mat)
ComplexVector eigenvalues()
ComplexMatrix eigenvectors()