/************************************************************************* Finding the eigenvalues and eigenvectors of a symmetric matrix The algorithm finds eigen pairs of a symmetric matrix by reducing it to tridiagonal form and using the QL/QR algorithm. Input parameters: A - symmetric matrix which is given by its upper or lower triangular part. Array whose indexes range within [0..N-1, 0..N-1]. N - size of matrix A. IsUpper - storage format. ZNeeded - flag controlling whether the eigenvectors are needed or not. If ZNeeded is equal to: * 0, the eigenvectors are not returned; * 1, the eigenvectors are returned. Output parameters: D - eigenvalues in ascending order. Array whose index ranges within [0..N-1]. Z - if ZNeeded is equal to: * 0, Z hasn’t changed; * 1, Z contains the eigenvectors. Array whose indexes range within [0..N-1, 0..N-1]. The eigenvectors are stored in the matrix columns. Result: True, if the algorithm has converged. False, if the algorithm hasn't converged (rare case). -- ALGLIB -- Copyright 2005-2008 by Bochkanov Sergey *************************************************************************/ bool smatrixevd(ap::real_2d_array a, int n, int zneeded, bool isupper, ap::real_1d_array& d, ap::real_2d_array& z) { bool result; ap::real_1d_array tau; ap::real_1d_array e; ap::ap_error::make_assertion(zneeded==0||zneeded==1, "SMatrixEVD: incorrect ZNeeded"); smatrixtd(a, n, isupper, tau, d, e); if( zneeded==1 ) { smatrixtdunpackq(a, n, isupper, tau, z); } result = smatrixtdevd(d, e, n, zneeded, z); return result; }
/************************************************************************* Subroutine for finding the eigenvalues (and eigenvectors) of a symmetric matrix in a given half open interval (A, B] by using a bisection and inverse iteration Input parameters: A - symmetric matrix which is given by its upper or lower triangular part. Array [0..N-1, 0..N-1]. N - size of matrix A. ZNeeded - flag controlling whether the eigenvectors are needed or not. If ZNeeded is equal to: * 0, the eigenvectors are not returned; * 1, the eigenvectors are returned. IsUpperA - storage format of matrix A. B1, B2 - half open interval (B1, B2] to search eigenvalues in. Output parameters: M - number of eigenvalues found in a given half-interval (M>=0). W - array of the eigenvalues found. Array whose index ranges within [0..M-1]. Z - if ZNeeded is equal to: * 0, Z hasn’t changed; * 1, Z contains eigenvectors. Array whose indexes range within [0..N-1, 0..M-1]. The eigenvectors are stored in the matrix columns. Result: True, if successful. M contains the number of eigenvalues in the given half-interval (could be equal to 0), W contains the eigenvalues, Z contains the eigenvectors (if needed). False, if the bisection method subroutine wasn't able to find the eigenvalues in the given interval or if the inverse iteration subroutine wasn't able to find all the corresponding eigenvectors. In that case, the eigenvalues and eigenvectors are not returned, M is equal to 0. -- ALGLIB -- Copyright 07.01.2006 by Bochkanov Sergey *************************************************************************/ bool smatrixevdr(ap::real_2d_array a, int n, int zneeded, bool isupper, double b1, double b2, int& m, ap::real_1d_array& w, ap::real_2d_array& z) { bool result; ap::real_1d_array tau; ap::real_1d_array e; ap::ap_error::make_assertion(zneeded==0||zneeded==1, "SMatrixTDEVDR: incorrect ZNeeded"); smatrixtd(a, n, isupper, tau, w, e); if( zneeded==1 ) { smatrixtdunpackq(a, n, isupper, tau, z); } result = smatrixtdevdr(w, e, n, zneeded, b1, b2, m, z); return result; }
static void teststdproblem(const ap::real_2d_array& a, int n, double& materr, double& orterr) { int i; int j; ap::real_2d_array ua; ap::real_2d_array la; ap::real_2d_array t; ap::real_2d_array q; ap::real_2d_array t2; ap::real_2d_array t3; ap::real_1d_array tau; ap::real_1d_array d; ap::real_1d_array e; double v; ua.setbounds(0, n-1, 0, n-1); la.setbounds(0, n-1, 0, n-1); t.setbounds(0, n-1, 0, n-1); q.setbounds(0, n-1, 0, n-1); t2.setbounds(0, n-1, 0, n-1); t3.setbounds(0, n-1, 0, n-1); // // fill // for(i = 0; i <= n-1; i++) { for(j = 0; j <= n-1; j++) { ua(i,j) = 0; } } for(i = 0; i <= n-1; i++) { for(j = i; j <= n-1; j++) { ua(i,j) = a(i,j); } } for(i = 0; i <= n-1; i++) { for(j = 0; j <= n-1; j++) { la(i,j) = 0; } } for(i = 0; i <= n-1; i++) { for(j = 0; j <= i; j++) { la(i,j) = a(i,j); } } // // Test 2tridiagonal: upper // smatrixtd(ua, n, true, tau, d, e); smatrixtdunpackq(ua, n, true, tau, q); for(i = 0; i <= n-1; i++) { for(j = 0; j <= n-1; j++) { t(i,j) = 0; } } for(i = 0; i <= n-1; i++) { t(i,i) = d(i); } for(i = 0; i <= n-2; i++) { t(i,i+1) = e(i); t(i+1,i) = e(i); } for(i = 0; i <= n-1; i++) { for(j = 0; j <= n-1; j++) { v = ap::vdotproduct(q.getcolumn(i, 0, n-1), a.getcolumn(j, 0, n-1)); t2(i,j) = v; } } for(i = 0; i <= n-1; i++) { for(j = 0; j <= n-1; j++) { v = ap::vdotproduct(t2.getrow(i, 0, n-1), q.getcolumn(j, 0, n-1)); t3(i,j) = v; } } for(i = 0; i <= n-1; i++) { for(j = 0; j <= n-1; j++) { materr = ap::maxreal(materr, ap::abscomplex(t3(i,j)-t(i,j))); } } for(i = 0; i <= n-1; i++) { for(j = 0; j <= n-1; j++) { v = ap::vdotproduct(&q(i, 0), &q(j, 0), ap::vlen(0,n-1)); if( i==j ) { orterr = ap::maxreal(orterr, ap::abscomplex(v-1)); } else { orterr = ap::maxreal(orterr, ap::abscomplex(v)); } } } // // Test 2tridiagonal: lower // smatrixtd(la, n, false, tau, d, e); smatrixtdunpackq(la, n, false, tau, q); for(i = 0; i <= n-1; i++) { for(j = 0; j <= n-1; j++) { t(i,j) = 0; } } for(i = 0; i <= n-1; i++) { t(i,i) = d(i); } for(i = 0; i <= n-2; i++) { t(i,i+1) = e(i); t(i+1,i) = e(i); } for(i = 0; i <= n-1; i++) { for(j = 0; j <= n-1; j++) { v = ap::vdotproduct(q.getcolumn(i, 0, n-1), a.getcolumn(j, 0, n-1)); t2(i,j) = v; } } for(i = 0; i <= n-1; i++) { for(j = 0; j <= n-1; j++) { v = ap::vdotproduct(t2.getrow(i, 0, n-1), q.getcolumn(j, 0, n-1)); t3(i,j) = v; } } for(i = 0; i <= n-1; i++) { for(j = 0; j <= n-1; j++) { materr = ap::maxreal(materr, ap::abscomplex(t3(i,j)-t(i,j))); } } for(i = 0; i <= n-1; i++) { for(j = 0; j <= n-1; j++) { v = ap::vdotproduct(&q(i, 0), &q(j, 0), ap::vlen(0,n-1)); if( i==j ) { orterr = ap::maxreal(orterr, ap::abscomplex(v-1)); } else { orterr = ap::maxreal(orterr, ap::abscomplex(v)); } } } }