LTI-Lib latest version v1.9 - last update 10 Apr 2010

ltiFastSVD.h

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 .......: ltiFastSVD.h
00027  * authors ....: Peter Doerfler
00028  * organization: LTI, RWTH Aachen
00029  * creation ...: 12.06.02
00030  * revisions ..: $Id: ltiFastSVD.h,v 1.7 2006/09/11 17:03:34 ltilib Exp $
00031  */
00032 
00033 #ifndef _LTI_FAST_SVD_H_
00034 #define _LTI_FAST_SVD_H_
00035 
00036 #include "ltiLapackInterface.h"
00037 
00038 #ifdef HAVE_LAPACK
00039 
00040 #include "ltiSVD.h"
00041 
00042 namespace lti {
00043   /**
00044    * A fast LAPACK-based method for computation of the singular value
00045    * decomposition SVD. Two routines can be chosen via the parameter
00046    * parameters::useDC. If this is true (default) the divide and
00047    * conquer method _GESDD is used which is generally faster
00048    * especially on large data but also requires more workspace.  In
00049    * case memory allocation fails when using the faster version,
00050    * choose the simple driver _GESVD by setting parameters::useDC to
00051    * \a false.
00052    *
00053    * The size of the returned matrices depends on the value of
00054    * parameters::useMinDimensions. The input data matrix is of size
00055    * MxN. Let minMN=min(M,N). The vector containing the singular
00056    * values always has the size minMN. If the parameter is true, the
00057    * matrix with left singular vectors U is of size MxminMN and V
00058    * (right SV) is of size minMNxN. Otherwise, U is a MxM and V a NxN
00059    * matrix.
00060    *
00061    * \b Note: The functor returns U and V untransposed to be
00062    * compatible with singularValueDecomp. Both U and V can be
00063    * transposed by the algorithm -- which might even be faster -- by
00064    * setting parameters::transposeU or parameters::transposeV.
00065    *
00066    * The following are the man pages of the two LAPACK functions used:
00067    * -------------------------------------------------------------
00068    *
00069    * SGESVD computes the singular value decomposition (SVD) of a real
00070    * M-by-N matrix A, optionally computing the left and/or right
00071    * singular vectors. The SVD is written
00072    *
00073    * A = U * SIGMA * transpose(V)
00074    *
00075    * where SIGMA is an M-by-N matrix which is zero except for its
00076    * min(m,n) diago­ nal elements, U is an M-by-M orthogonal matrix,
00077    * and V is an N-by-N orthogo­ nal matrix.  The diagonal elements of
00078    * SIGMA are the singular values of A; they are real and
00079    * non-negative, and are returned in descending order.  The first
00080    * min(m,n) columns of U and V are the left and right singular
00081    * vectors of A.
00082    *
00083    * Note that the routine returns VT = V**T, not V.
00084    *
00085    * ---------------------------------------------------------------
00086    *
00087    * SGESDD computes the singular value decomposition (SVD) of a real
00088    * M-by-N matrix A, optionally computing the left and right singular
00089    * vectors.  If sin­ gular vectors are desired, it uses a
00090    * divide-and-conquer algorithm.
00091    *
00092    * The SVD is written
00093    *
00094    * A = U * SIGMA * transpose(V)
00095    *
00096    * where SIGMA is an M-by-N matrix which is zero except for its
00097    * min(m,n) diago­ nal elements, U is an M-by-M orthogonal matrix,
00098    * and V is an N-by-N orthogo­ nal matrix.  The diagonal elements of
00099    * SIGMA are the singular values of A; they are real and
00100    * non-negative, and are returned in descending order.  The first
00101    * min(m,n) columns of U and V are the left and right singular
00102    * vectors of A.
00103    *
00104    * Note that the routine returns VT = V**T, not V.
00105    *
00106    * The divide and conquer algorithm makes very mild assumptions
00107    * about floating point arithmetic. It will work on machines with a
00108    * guard digit in add/sub­ tract, or on those binary machines
00109    * without guard digits which subtract like the Cray X-MP, Cray
00110    * Y-MP, Cray C-90, or Cray-2. It could conceivably fail on
00111    * hexadecimal or decimal machines without guard digits, but we know
00112    * of none.
00113    *
00114    *
00115    * @ingroup lapack
00116    *
00117    * @see \ref lapack
00118    */
00119   template<class T>
00120   class fastSVD : public singularValueDecomp<T>, lapackInterface {
00121   public:
00122     /**
00123      * FastSVD parameter class. \b Note that the sort parameter
00124      * inherited from singularValueDecomp<T> is always true for this
00125      * functor, since sorting is done automatically during computation
00126      * of singular values and vectors.
00127      */
00128     class parameters : public singularValueDecomp<T>::parameters {
00129     public:
00130       /**
00131        * default constructor
00132        */
00133       parameters()
00134         : singularValueDecomp<T>::parameters() {
00135         this->sort = true;
00136         useDC = true;
00137         useMinDimensions = true;
00138       };
00139 
00140       /**
00141        * copy constructor
00142        */
00143       parameters(const parameters& other) {
00144         copy(other);
00145       };
00146 
00147       /**
00148        * If true the divide-and-conquer method for calculating the SVD
00149        * is used. This is generally faster, especially on large
00150        * matrices. However, it uses more temporary memory than the
00151        * simple method. Thus, if the computation fails due to memory
00152        * problems setting this parameter to false might solve the
00153        * problem. Default is true.
00154        */
00155       bool useDC;
00156 
00157       /**
00158        * Let the data matrix have M rows and N columns. Then, usually,
00159        * U will be an MxM orthogonal matrix and V an NxN orthogonal
00160        * matrix. However, there are only min(M,N) singular values. For
00161        * most applications it suffices to calculate only min(M,N) left
00162        * and right singular vectors, which is done when
00163        * useMinDimensions is true (default). All singular values are
00164        * calculated when false.
00165        */
00166       bool useMinDimensions;
00167 
00168       /**
00169        * returns the name of this type
00170        */
00171       virtual const char* getTypeName() const {
00172         return "fastSVD::parameters";
00173       };
00174 
00175       /**
00176        * copy member.
00177        */
00178       parameters& copy(const parameters& other) {
00179 #ifndef _LTI_MSC_6
00180         // MS Visual C++ 6 is not able to compile this...
00181         singularValueDecomp<T>::parameters::copy(other);
00182 #else
00183         // ...so we have to use this workaround.
00184         // Conditional on that, copy may not be virtual.
00185         singularValueDecomp<T>::parameters&
00186           (singularValueDecomp<T>::parameters::* p_copy)(const singularValueDecomp<T>::parameters&) =
00187           singularValueDecomp<T>::parameters::copy;
00188         (this->*p_copy)(other);
00189 #endif
00190 
00191         useDC = other.useDC;
00192         useMinDimensions = other.useMinDimensions;
00193 
00194         return (*this);
00195       };
00196 
00197       /**
00198        * returns a pointer to a clone of the parameters.
00199        */
00200       virtual functor::parameters* clone() const {
00201         return (new parameters(*this));
00202       };
00203 
00204 #     ifndef _LTI_MSC_6
00205       /**
00206        * read the parameters from the given ioHandler
00207        * @param handler the ioHandler to be used
00208        * @param complete if true (the default) the enclosing begin/end will
00209        *        be also read, otherwise only the data block will be read.
00210        * @return true if write was successful
00211        */
00212       virtual bool read(ioHandler &handler, const bool complete=true)
00213 #     else
00214       bool readMS(ioHandler& handler,const bool complete=true)
00215 #     endif
00216       {
00217         bool b=true;
00218 
00219         if (complete) {
00220           b=handler.readBegin();
00221         }
00222 
00223         if (b) {
00224           lti::read(handler,"useDC",useDC);
00225           lti::read(handler,"useMinDimensions",useMinDimensions);
00226         }
00227 
00228 #     ifndef _LTI_MSC_6
00229         // This is the standard C++ code, which MS Visual C++ 6 is not
00230         // able to compile...
00231         b = b && singularValueDecomp<T>::parameters::read(handler,false);
00232 #     else
00233         bool (functor::parameters::* p_readMS)(ioHandler&,const bool&) =
00234           functor::parameters::readMS;
00235         b = b && (this->*p_readMS)(handler,false);
00236 #     endif
00237 
00238         if (complete) {
00239           b=b && handler.readEnd();
00240         }
00241 
00242         return b;
00243       }
00244 
00245 #     ifdef _LTI_MSC_6
00246       /**
00247        * read the parameters from the given ioHandler
00248        * @param handler the ioHandler to be used
00249        * @param complete if true (the default) the enclosing begin/end will
00250        *        be also read, otherwise only the data block will be read.
00251        * @return true if write was successful
00252        */
00253       virtual bool read(ioHandler& handler,const bool complete=true) {
00254         // ...we need this workaround to cope with another really awful MSVC
00255         // bug.
00256         return readMS(handler,complete);
00257       }
00258 #     endif
00259 
00260 #     ifndef _LTI_MSC_6
00261       /**
00262        * write the parameters in the given ioHandler
00263        * @param handler the ioHandler to be used
00264        * @param complete if true (the default) the enclosing begin/end will
00265        *        be also written, otherwise only the data block will be
00266        *        written.
00267        * @return true if write was successful
00268        */
00269       virtual bool write(ioHandler& handler,const bool complete=true) const
00270 #     else
00271       bool writeMS(ioHandler& handler,const bool complete=true) const
00272 #     endif
00273       {
00274         bool b=true;
00275 
00276         if (complete) {
00277           b=handler.writeBegin();
00278         }
00279 
00280         if (b) {
00281           lti::write(handler,"useDC",useDC);
00282           lti::write(handler,"useMinDimensions",useMinDimensions);
00283         }
00284 
00285 #       ifndef _LTI_MSC_6
00286         // This is the standard C++ code, which MS Visual C++ 6 is not
00287         // able to compile...
00288         b = b && singularValueDecomp<T>::parameters::write(handler,false);
00289 #       else
00290         bool
00291         (functor::parameters::* p_writeMS)(ioHandler&,const bool&) const =
00292           functor::parameters::writeMS;
00293         b = b && (this->*p_writeMS)(handler,false);
00294 #       endif
00295 
00296         if (complete) {
00297           b=b && handler.writeEnd();
00298         }
00299 
00300         return b;
00301       }
00302 
00303 #     ifdef _LTI_MSC_6
00304       /**
00305        * write the parameters to the given ioHandler
00306        * @param handler the ioHandler to be used
00307        * @param complete if true (the default) the enclosing begin/end will
00308        *        be also writen, otherwise only the data block will be writen.
00309        * @return true if write was successful
00310        */
00311       virtual bool write(ioHandler& handler,const bool complete=true) {
00312         // ...we need this workaround to cope with another really awful MSVC
00313         // bug.
00314         return writeMS(handler,complete);
00315       }
00316 #     endif
00317 
00318     };
00319 
00320     /**
00321      * default constructor
00322      */
00323     fastSVD();
00324 
00325     /**
00326      * constructor, sets the parameters
00327      */
00328     fastSVD(const parameters& theParams);
00329 
00330     /**
00331      * destructor
00332      */
00333     virtual ~fastSVD();
00334 
00335     /**
00336      * returns the current parameters.
00337      */
00338     const parameters& getParameters() const;
00339 
00340     /**
00341      * clone this functor
00342      */
00343     virtual functor* clone() const;
00344 
00345     /**
00346      * Computes singular values as well as left and right singular
00347      * values. The method used for calculating the SVD is set by
00348      * parameters::useDC. The number of singular values is set by
00349      * parameters::useMinDimensions. Both the \a leftSV (U) and the \a
00350      * rightSV (V) can be transposed by setting parameters::transposeU
00351      * and parameters::transposeV, respectively.
00352      *
00353      * @param theMatrix data matrix with M rows and N columns.
00354      * @param leftSV left singular vectors in M or min(M,N) columns.
00355      * @param singularValues min(M,N) singular values
00356      * @param rightSV right singular vectors in N or min(M,N) columns.
00357      */
00358     virtual bool apply(const matrix<T>& theMatrix,
00359                        matrix<T>& leftSV,
00360                        vector<T>& singularValues,
00361                        matrix<T>& rightSV) const;
00362 
00363     /**
00364      * On place version that computes singular values as well as left
00365      * and right singular values. The method used for calculating the
00366      * SVD is set by parameters::useDC. The number of singular values
00367      * is set by parameters::useMinDimensions. The \a rightSV (V) can
00368      * be transposed by setting parameters::transposeV. The parameter
00369      * parameters::transposeU has no effect.
00370      *
00371      * The left singular vectors are returned in \a theMatrix which
00372      * has M rows and N columns. If M>N only the first N left singular
00373      * values are returned in \a theMatrix. If M<=N all M left
00374      * singular values are returned in the first M columns of \a
00375      * theMatrix.
00376      *
00377      * @param theMatrix data matrix with M rows and N columns.
00378      * @param singularValues min(M,N) singular values
00379      * @param rightSV right singular vectors in N or min(M,N) columns.
00380      */
00381     virtual bool apply(matrix<T>& theMatrix,
00382                        vector<T>& singularValues,
00383                        matrix<T>& rightSV) const;
00384 
00385 
00386 
00387     /**
00388      * returns the name of this type
00389      */
00390     virtual const char* getTypeName() const {
00391       return "fastSVD";
00392     };
00393 
00394   private:
00395     // lapack routine in template form
00396 
00397     int svd(char* jobu, char* jobvt,
00398             integer* m, integer* n, T* a, integer* lda,
00399             T* s, T* u, integer* ldu, T* vt, integer* ldvt,
00400             T* work, integer* lwork,
00401             integer* info) const;
00402 
00403     int sdd(char* jobz, integer* m, integer* n, T* a, integer* lda,
00404             T* s, T* u, integer* ldu, T* vt, integer* ldvt,
00405             T* work, integer* lwork, integer* iwork,
00406             integer* info) const;
00407   };
00408 
00409 }
00410 
00411 #endif
00412 #endif

Generated on Sat Apr 10 15:25:29 2010 for LTI-Lib by Doxygen 1.6.1