last update 20 Sep 2009 |
00001 /* 00002 * Copyright (C) 1998-2005 00003 * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany 00004 * 00005 * 00006 * This file is part of the Computer Vision and Robotics Library (CVR-Lib) 00007 * 00008 * The CVR-Lib is free software; you can redistribute it and/or 00009 * modify it under the terms of the BSD License. 00010 * 00011 * All rights reserved. 00012 * 00013 * Redistribution and use in source and binary forms, with or without 00014 * modification, are permitted provided that the following conditions are met: 00015 * 00016 * 1. Redistributions of source code must retain the above copyright notice, 00017 * this list of conditions and the following disclaimer. 00018 * 00019 * 2. Redistributions in binary form must reproduce the above copyright notice, 00020 * this list of conditions and the following disclaimer in the documentation 00021 * and/or other materials provided with the distribution. 00022 * 00023 * 3. Neither the name of the authors nor the names of its contributors may be 00024 * used to endorse or promote products derived from this software without 00025 * specific prior written permission. 00026 * 00027 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00028 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00029 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00030 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00031 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00032 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00033 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00034 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00035 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00036 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00037 * POSSIBILITY OF SUCH DAMAGE. 00038 */ 00039 00040 00041 /** 00042 * \file cvrSymmetricEigenSystem.h 00043 * Contains the template class symmetricEigenSystem<T> that 00044 * uses LAPACK if available. 00045 * \author Thomas Rusert 00046 * \author Peter Doerfler 00047 * \date 16.06.99 00048 * 00049 * $Id: cvrSymmetricEigenSystem.h,v 1.4 2006/09/07 13:38:37 doerfler Exp $ 00050 */ 00051 00052 #ifndef _CVR_SYMMETRIC_EIGEN_SYSTEM_H_ 00053 #define _CVR_SYMMETRIC_EIGEN_SYSTEM_H_ 00054 00055 #include "cvrMatrix.h" 00056 #include "cvrVector.h" 00057 #include "cvrLinearAlgebraFunctor.h" 00058 00059 #include "cvrTypeInfo.h" 00060 00061 #ifdef HAVE_LAPACK 00062 # include "cvrLapackInterface.h" 00063 #endif 00064 00065 namespace cvr { 00066 /** 00067 * Computes the Eigenvectors and Eigenvalues of a symmetric, 00068 * positive definite, real matrix. 00069 * 00070 * The most common source of such matrices is a covariance matrix 00071 * (see cvr::secondOrderStatistics). 00072 * 00073 * This class uses the LAPACK functions by default if they are 00074 * installed on your system. Otherwise a simple Jacobi algorithm is 00075 * used. This can also be chosen deliberately by setting 00076 * parameters::useLapack to false. 00077 * 00078 * The eigenvectors can be sorted according to their eigenvalues by 00079 * setting parameters::sort. A fixed number of eigenvectors can be 00080 * set via parameters::dimension. For LAPACK this also reduces 00081 * computation time. 00082 * 00083 * Please note that the eigenvector matrices will contain the 00084 * eigenvectors in the COLUMNS and not in the rows, as could be 00085 * expected. This avoids the requirement of transposing matrices in 00086 * eigenvector-based transformations like PCA! 00087 * 00088 * @ingroup gLinearAlgebra, gStatistics 00089 */ 00090 template <typename T> 00091 class symmetricEigenSystem : public linearAlgebraFunctor 00092 #ifdef HAVE_LAPACK 00093 , public lapackInterface 00094 #endif 00095 { 00096 public: 00097 00098 /** 00099 * eigenSystem parameter class 00100 */ 00101 class parameters : public linearAlgebraFunctor::parameters { 00102 public: 00103 /** 00104 * default constructor 00105 */ 00106 parameters(); 00107 00108 /** 00109 * copy constructor 00110 */ 00111 parameters(const parameters& other); 00112 00113 /** 00114 * copy member. 00115 */ 00116 parameters& copy(const parameters& other); 00117 00118 /** 00119 * Returns the name of this class. 00120 */ 00121 const std::string& name() const; 00122 00123 /** 00124 * returns a pointer to a clone of the parameters. 00125 */ 00126 virtual parameters* clone() const; 00127 00128 /** 00129 * returns a pointer to a clone of the parameters. 00130 */ 00131 virtual parameters* newInstance() const; 00132 00133 /** 00134 * write the parameters in the given ioHandler 00135 * \param handler the ioHandler to be used 00136 * \param complete if true (the default) the enclosing begin/end will 00137 * be also written, otherwise only the data block will be written. 00138 * \return true if write was successful 00139 */ 00140 virtual bool write(ioHandler& handler, const bool complete=true) const; 00141 00142 /** 00143 * read the parameters from the given ioHandler 00144 * \param handler the ioHandler to be used 00145 * \param complete if true (the default) the enclosing begin/end will 00146 * be also written, otherwise only the data block will be written. 00147 * \return true if write was successful 00148 */ 00149 virtual bool read(ioHandler& handler, const bool complete=true); 00150 00151 00152 //**************************** 00153 // the parameters 00154 //**************************** 00155 00156 /** 00157 * If true, the eigenvalues and corresponding eigenvectors will be 00158 * sorted in decreasing order of the eigenvalues. 00159 * 00160 * For complex-valued matrices a complex number will be considered 00161 * "greater than" another one if its real part is greater, or, if both 00162 * real components are identical, if its imaginary part is greater. 00163 * 00164 * Default value: false 00165 */ 00166 bool sort; 00167 00168 /** 00169 * Mumber of dimensions calculated. 00170 * 00171 * If set to zero, then all eigenvectors and eigenvalues are calculated. 00172 * 00173 * This option is only provided for compatibility with the 00174 * fastEigenSystem functor based on LAPACK, but it does not make (yet) 00175 * the computation of the eigensolution any faster. It just will cut 00176 * the already computed complete solution to the desired size! 00177 * 00178 * Default value: 0 (implying all eigenvalues will be computed) 00179 */ 00180 int dimensions; 00181 }; 00182 00183 00184 /** 00185 * Default constructor 00186 */ 00187 symmetricEigenSystem(); 00188 00189 /** 00190 * Default constructor with parameters 00191 */ 00192 symmetricEigenSystem(const parameters& params); 00193 00194 00195 /** 00196 * Calculate the Eigensystem with \a eigenvalues and \a eigenvalues 00197 * from the given data in \a theMatrix (Samples in rows). Due to the 00198 * symmetricity of the data it suffices if \a theMatrix is upper 00199 * triangular. 00200 * 00201 * @param theMatrix Real symmetric matrix to be transformed. 00202 * Only the diagonal and above diagonal elements have 00203 * to be set. 00204 * @param eigenvalues Elements will contain the eigenvalues. 00205 * @param eigenvectors Columns will contain the eigenvectors corresponding 00206 * to the eigenvalues. 00207 * returns true if successful, false otherwise. 00208 */ 00209 virtual bool apply(const matrix<T>& theMatrix, 00210 vector<T>& eigenvalues, 00211 matrix<T>& eigenvectors) const; 00212 00213 00214 /** 00215 * Convenience function that calculates the Eigensystem like 00216 * apply, but uses the given argument \a dimensions instead of 00217 * those given in parameters::dimensions. 00218 * 00219 * @param theMatrix Real symmetric matrix to be transformed. 00220 * Only the diagonal and above diagonal elements have 00221 * to be set. 00222 * @param eigenvalues Elements will contain the eigenvalues. 00223 * @param eigenvectors Columns will contain the eigenvectors corresponding 00224 * to the eigenvalues. 00225 * @param dimensions number of dimensions in eigenspace 00226 * returns true if successful, false otherwise. 00227 */ 00228 virtual bool reducedEigenSystem(const matrix<T>& theMatrix, 00229 vector<T>& eigenvalues, 00230 matrix<T>& eigenvectors, 00231 const int dimensions) const; 00232 00233 /** 00234 * Returns the name of this class. 00235 */ 00236 const std::string& name() const; 00237 00238 /** 00239 * Returns a pointer to a clone of this functor. 00240 */ 00241 virtual symmetricEigenSystem* clone() const; 00242 00243 /** 00244 * Returns a pointer to a new instance of this functor. 00245 */ 00246 virtual symmetricEigenSystem* newInstance() const; 00247 00248 /** 00249 * returns the current parameters. 00250 */ 00251 const parameters& getParameters() const; 00252 00253 protected: 00254 #ifdef HAVE_LAPACK 00255 private: 00256 /** 00257 * Contained type in T 00258 * 00259 * This is a trick of generic programming to be an alias of type T if it is 00260 * a normal type (double, float) or the contained type A if T is 00261 * complex<A>. 00262 */ 00263 typedef typename typeInfo<T>::value_type value_type; 00264 00265 inline void rotateT(T& g,T& h,matrix<T>& a, 00266 const int i,const int j,const int k,const int l, 00267 const T s,const T tau) const; 00268 00269 inline void rotate(T& g,T& h,matrix<T>& a, 00270 const int i,const int j,const int k,const int l, 00271 const T s,const T tau) const; 00272 00273 00274 /** 00275 * Apply the LAPACK function with the correct parameters 00276 * 00277 * The matrix \c theMatrix will be modified, since LAPACK uses the unused 00278 * triangular submatrix as buffer. 00279 */ 00280 bool applyLapack(matrix<T>& theMatrix, 00281 vector<T>& eigenvalues, 00282 matrix<T>& eigenvectors, 00283 const int dimensions) const; 00284 00285 /** 00286 * Calls the lapack function of eigensystem of symmetric matrix 00287 * specialized for float and double 00288 */ 00289 int evr(char* jobz, char* range, char* uplo, 00290 integer* n, T* a, integer* lda, 00291 value_type* vl, value_type* vu, 00292 integer* il, integer* iu, 00293 value_type* abstol, 00294 integer* m, value_type* w, 00295 T* z, integer* ldz, integer* isuppz, 00296 T* work, integer* lwork, 00297 value_type* rwork,integer* lrwork, 00298 integer* iwork, integer* liwork, 00299 integer* info) const; 00300 #endif 00301 00302 }; 00303 } 00304 00305 00306 #endif 00307