latest version v1.9 - last update 10 Apr 2010 |
00001 /* 00002 * Copyright (C) 2002, 2003, 2004, 2005, 2006 00003 * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany 00004 * 00005 * This file is part of the LTI-Computer Vision Library (LTI-Lib) 00006 * 00007 * The LTI-Lib is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public License (LGPL) 00009 * as published by the Free Software Foundation; either version 2.1 of 00010 * the License, or (at your option) any later version. 00011 * 00012 * The LTI-Lib is distributed in the hope that it will be 00013 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty 00014 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with the LTI-Lib; see the file LICENSE. If 00019 * not, write to the Free Software Foundation, Inc., 59 Temple Place - 00020 * Suite 330, Boston, MA 02111-1307, USA. 00021 */ 00022 00023 00024 /*---------------------------------------------------------------- 00025 * project ....: LTI Digital Image/Signal Processing Library 00026 * file .......: ltiFastEigenSystem.h 00027 * authors ....: Peter Doerfler 00028 * organization: LTI, RWTH Aachen 00029 * creation ...: 12.04.02 00030 * revisions ..: $Id: ltiFastEigenSystem.h,v 1.7 2006/09/11 17:02:29 ltilib Exp $ 00031 */ 00032 00033 #ifndef _LTI_FAST_EIGEN_SYSTEM_H_ 00034 #define _LTI_FAST_EIGEN_SYSTEM_H_ 00035 00036 #include "ltiLapackInterface.h" 00037 00038 #ifdef HAVE_LAPACK 00039 00040 #include "ltiEigenSystem.h" 00041 00042 namespace lti { 00043 /** 00044 * A fast LAPACK-based method for computation of (some) eigenvector 00045 * and eigenvalues. Depending on the parameters useRRR (relatively 00046 * robust representation), either xSYEVR (true) or xSYEVX (false) 00047 * are used. The latter is default since RRR goes into infinite 00048 * loops for some data. \b Note however that switching useRRR to 00049 * true is usually much faster (a simple test yielded 25% speed-up). 00050 * 00051 * Part of the man page of xSYEVR: 00052 * 00053 * DSYEVR (SSYEVR) computes selected eigenvalues and, optionally, 00054 * eigenvectors of a real symmetric tridiagonal matrix T. 00055 * Eigenvalues and eigenvectors can be selected by specifying either 00056 * a range of values or a range of indices for the desired 00057 * eigenvalues. 00058 * 00059 * Whenever possible, DSYEVR calls DSTEGR to compute the 00060 * eigenspectrum using Relatively Robust Representations. DSTEGR 00061 * computes eigenvalues by the dqds algorithm, while orthogonal 00062 * eigenvectors are com puted from various "good" L D L^T 00063 * representations (also known as Relatively Robust 00064 * Representations). Gram-Schmidt orthogonalization is avoided as 00065 * far as possible. More specifically, the various steps of the 00066 * algorithm are as fol lows. For the i-th unreduced block of T, 00067 * 00068 * (a) Compute T - sigma_i = L_i D_i L_i^T, such that L_i D_i L_i^T 00069 * is a relatively robust representation, 00070 * 00071 * (b) Compute the eigenvalues, lambda_j, of L_i D_i L_i^T to 00072 * high relative accuracy by the dqds algorithm, 00073 * 00074 * (c) If there is a cluster of close eigenvalues, 00075 * "choose" sigma_i close to the cluster, and go to step (a), 00076 * 00077 * (d) Given the approximate eigenvalue lambda_j of 00078 * L_i D_i L_i^T, compute the corresponding eigenvector by 00079 * forming a rank-revealing twisted factorization. 00080 * 00081 * The desired accuracy of the output can be specified by the input 00082 * parameter ABSTOL. 00083 * 00084 * For more details, see "A new O(n^2) algorithm for the symmetric 00085 * tridiagonal eigenvalue/eigenvector problem", by Inderjit Dhillon, 00086 * Computer Science Division Technical Report No. UCB//CSD-97-971, 00087 * UC Berkeley, May 1997. 00088 * 00089 * 00090 * Part of the man page of xSYEVX: 00091 * 00092 * SSYEVX computes selected eigenvalues and, optionally, eigenvectors 00093 * of a real symmetric matrix A. Eigenvalues and eigenvectors can be 00094 * selected by specifying either a range of values or a range of indices 00095 * for the desired eigenvalues. 00096 * 00097 * @ingroup lapack 00098 * 00099 * @see \ref lapack 00100 */ 00101 template<class T> 00102 class fastEigenSystem : public eigenSystem<T>, lapackInterface { 00103 public: 00104 /** 00105 * eigenSystem parameter class 00106 */ 00107 class parameters : public eigenSystem<T>::parameters { 00108 public: 00109 /** 00110 * default constructor 00111 */ 00112 parameters() 00113 : eigenSystem<T>::parameters(),dimensions(0), useRRR(false) { 00114 }; 00115 00116 /** 00117 * copy constructor 00118 */ 00119 parameters(const parameters& other) { 00120 copy(other); 00121 }; 00122 00123 /** 00124 * number of dimensions calculated. The default is zero. In this 00125 * case, all eigenvectors and eigenvalues are calculated. 00126 */ 00127 int dimensions; 00128 00129 /** 00130 * use relatively robust representation (RRR i.e. xSYEVR) or not 00131 * (i.e. xSYEVX) 00132 * 00133 * Default: false 00134 */ 00135 bool useRRR; 00136 00137 /** 00138 * returns the name of this type 00139 */ 00140 virtual const char* getTypeName() const { 00141 return "fastEigenSystem::parameters"; 00142 }; 00143 00144 /** 00145 * copy member. 00146 */ 00147 parameters& copy(const parameters& other) { 00148 #ifndef _LTI_MSC_6 00149 // MS Visual C++ 6 is not able to compile this... 00150 eigenSystem<T>::parameters::copy(other); 00151 #else 00152 // ...so we have to use this workaround. 00153 // Conditional on that, copy may not be virtual. 00154 eigenSystem<T>::parameters& 00155 (eigenSystem<T>::parameters::* p_copy)(const eigenSystem<T>::parameters&) = 00156 eigenSystem<T>::parameters::copy; 00157 (this->*p_copy)(other); 00158 #endif 00159 dimensions = other.dimensions; 00160 useRRR = other.useRRR; 00161 00162 return (*this); 00163 }; 00164 00165 /** 00166 * returns a pointer to a clone of the parameters. 00167 */ 00168 virtual functor::parameters* clone() const { 00169 return (new parameters(*this)); 00170 }; 00171 }; 00172 00173 /** 00174 * default constructor 00175 */ 00176 fastEigenSystem(); 00177 00178 /** 00179 * constructor, sets the parameters 00180 */ 00181 fastEigenSystem(const parameters& theParams); 00182 00183 /** 00184 * constructor, sets the parameters 00185 */ 00186 fastEigenSystem(const int dimensions); 00187 00188 /** 00189 * destructor 00190 */ 00191 virtual ~fastEigenSystem(); 00192 00193 /** 00194 * returns the current parameters. 00195 */ 00196 const parameters& getParameters() const; 00197 00198 /** 00199 * clone this functor 00200 */ 00201 virtual functor* clone() const; 00202 00203 /** 00204 * Computes eigenvalues and eigenvectors of the given matrix. The 00205 * functor can efficiently calculate only a few dimensions of the 00206 * eigenspace, taking those with the largest eigenvalues. The 00207 * number of dimensions is set with parameters::dimensions. 00208 * 00209 * @param theMatrix matrix whose eigenvectors are to be computed 00210 * @param eigenvalues elements will contain the eigenvalues 00211 * @param eigenvectors columns will contain the eigenvectors 00212 * corresponding to the eigenvalues 00213 */ 00214 virtual bool apply(const matrix<T>& theMatrix, 00215 vector<T>& eigenvalues, 00216 matrix<T>& eigenvectors) const; 00217 00218 00219 /** 00220 * returns the name of this type 00221 */ 00222 virtual const char* getTypeName() const { 00223 return "fastEigenSystem"; 00224 }; 00225 00226 private: 00227 // lapack routine in template form 00228 00229 int evr(char* jobz, char* range, char* uplo, 00230 integer* n, T* a, integer* lda, 00231 T* vl, T* vu, 00232 integer* il, integer* iu, 00233 T* abstol, 00234 integer* m, T* w, 00235 T* z, integer* ldz, integer* isuppz, 00236 T* work, integer* lwork, 00237 integer* iwork, integer* liwork, 00238 integer* info) const; 00239 00240 int evx(char* jobz, char* range, char* uplo, 00241 integer* n, T* a, integer* lda, 00242 T* vl, T* vu, 00243 integer* il, integer* iu, 00244 T* abstol, 00245 integer* m, T* w, 00246 T* z, integer* ldz, 00247 T* work, integer* lwork, 00248 integer* iwork, integer* ifail, 00249 integer* info) const; 00250 00251 }; 00252 00253 } 00254 00255 #endif 00256 #endif