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

ltiQrDecomposition.h

00001 /*
00002  * Copyright (C) 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-Lib: Image Processing and Computer Vision Library
00026  * file .......: ltiQrDecomposition.h
00027  * authors ....: Arnd Hannemann
00028  * organization: LTI, RWTH Aachen
00029  * creation ...: 26.1.2004
00030  * revisions ..: $Id: ltiQrDecomposition.h,v 1.10 2006/09/11 17:05:13 ltilib Exp $
00031  */
00032 
00033 #ifndef _LTI_QR_DECOMPOSITION_H_
00034 #define _LTI_QR_DECOMPOSITION_H_
00035 
00036 
00037 #include "ltiMatrix.h"
00038 #include "ltiLinearAlgebraFunctor.h"
00039 #include "ltiPerformanceConfig.h"
00040 
00041 #ifdef HAVE_LAPACK
00042 #include "ltiLapackInterface.h"
00043 #endif
00044 
00045 namespace lti {
00046   /**
00047    * This functor computes a QRDecomposition of a given rectangular 
00048    * m x n Matrix A of the Form:
00049    *    
00050    *  A = Q * R
00051    *
00052    * Where R is an upper triangular m x m Matrix and Q is a 
00053    * m x n orthogonal matrix.
00054    * Transpose of Q muliplied with Q itself is the identity Matrix.
00055    *
00056    * If LAPACK is not used or not available, A <b>must</b> be of full rang!
00057    *
00058    * \code
00059    * matrix<float> src(3,3);
00060    * float data[] =  {1,2,3,4,5,6,7,8,9};
00061    * src.fill(data);
00062    * matrix<float> q,r;
00063    *
00064    * qrDecomposition<float> qrd;
00065    * qrd.apply(src,q,r);
00066    *
00067    * matrix<float> result;
00068    * result.multiply(q,r);
00069    *
00070    * std::cout << "Q:\n" << q << "\n";
00071    * std::cout << "R:\n" << r << "\n";
00072    * // should be identical to src
00073    * std::cout << "A = Q * R:\n"<< result << "\n";
00074    *
00075    * \endcode
00076    */
00077   template <class T>
00078 #ifdef HAVE_LAPACK
00079   class qrDecomposition : public linearAlgebraFunctor, lapackInterface {
00080 #else
00081   class qrDecomposition : public linearAlgebraFunctor {
00082 #endif
00083   public:
00084     /**
00085      * The parameters for the class qrDecomposition
00086      */
00087     class parameters : public linearAlgebraFunctor::parameters {
00088     public:
00089 
00090       /**
00091        * Default constructor
00092        */
00093       parameters() : linearAlgebraFunctor::parameters() {
00094         useLapack = true;
00095         performanceTweakThresholdForTranspose = 
00096           _LTI_PERFORMANCE_QR_DECOMPOSITION;
00097       };
00098 
00099       /**
00100        * Copy constructor
00101        * @param other the parameters object to be copied
00102        */
00103       parameters(const parameters& other) 
00104         : linearAlgebraFunctor::parameters() {
00105         copy(other);
00106       };
00107 
00108       /**
00109        * Destructor
00110        */
00111       ~parameters() {
00112       };
00113 
00114       /**
00115        * Returns name of this type
00116        */
00117       const char* getTypeName() const {
00118         return "qrDecomposition<T>::parameters";
00119       };
00120 
00121       /**
00122        * Copy the contents of a parameters object
00123        * @param other the parameters object to be copied
00124        * @return a reference to this parameters object
00125        */
00126       parameters& copy(const parameters& other) {
00127 # ifndef _LTI_MSC_6
00128         // MS Visual C++ 6 is not able to compile this...
00129         linearAlgebraFunctor::parameters::copy(other);
00130 # else
00131         // ...so we have to use this workaround.
00132         // Conditional on that, copy may not be virtual.
00133         linearAlgebraFunctor::parameters& (linearAlgebraFunctor::parameters::* p_copy)
00134           (const linearAlgebraFunctor::parameters&) =
00135           linearAlgebraFunctor::parameters::copy;
00136         (this->*p_copy)(other);
00137 # endif
00138         
00139         useLapack = other.useLapack;
00140         performanceTweakThresholdForTranspose = 
00141           other.performanceTweakThresholdForTranspose;
00142         
00143         return *this;
00144       };
00145 
00146       /**
00147        * Copy the contents of a parameters object
00148        * @param other the parameters object to be copied
00149        * @return a reference to this parameters object
00150        */
00151       parameters& operator=(const parameters& other) {
00152         return copy(other);
00153       };
00154 
00155 
00156       /**
00157        * Returns a pointer to a clone of the parameters
00158        */
00159       virtual functor::parameters* clone() const {
00160         return new parameters(*this);
00161       };
00162 
00163 #     ifndef _LTI_MSC_6
00164       /**
00165        * write the parameters in the given ioHandler
00166        * @param handler the ioHandler to be used
00167        * @param complete if true (the default) the enclosing begin/end will
00168        *        be also written, otherwise only the data block will be written.
00169        * @return true if write was successful
00170        */
00171       virtual bool write(ioHandler& handler,const bool complete=true) const
00172 #     else
00173       /**
00174        * this function is required by MSVC only, as a workaround for a
00175        * very awful bug, which exists since MSVC V.4.0, and still by
00176        * V.6.0 with all bugfixes (so called "service packs") remains
00177        * there...  This method is also public due to another bug, so please
00178        * NEVER EVER call this method directly: use write() instead
00179        */
00180       bool writeMS(ioHandler& handler,const bool complete=true) const
00181 #     endif
00182       {
00183         bool b = true;
00184         if (complete) {
00185           b = handler.writeBegin();
00186         }
00187         
00188         if (b) {
00189           
00190         }
00191 
00192 #     ifndef _LTI_MSC_6
00193         // This is the standard C++ code, which MS Visual C++ 6 is not able to
00194         // compile...
00195         b = b && linearAlgebraFunctor::parameters::write(handler,false);
00196 #     else
00197         bool (linearAlgebraFunctor::parameters::* p_writeMS)(ioHandler&,
00198                                                          const bool) const =
00199           linearAlgebraFunctor::parameters::writeMS;
00200         b = b && (this->*p_writeMS)(handler,false);
00201 #     endif
00202         b = b && lti::write(handler, "useLapack", useLapack);
00203         b = b && lti::write(handler, "performanceTweakThresholdForTranspose",
00204                             performanceTweakThresholdForTranspose);
00205 
00206         if (complete) {
00207           b = b && handler.writeEnd();
00208         }
00209 
00210         return b;
00211       }
00212 
00213 #     ifdef _LTI_MSC_6
00214       /**
00215        * write the parameters in the given ioHandler
00216        * @param handler the ioHandler to be used
00217        * @param complete if true (the default) the enclosing begin/end will
00218        *        be also written, otherwise only the data block will be written.
00219        * @return true if write was successful
00220        */
00221       bool write(ioHandler& handler,
00222                  const bool complete=true) const {
00223         // ...we need this workaround to cope with another really
00224         // awful MSVC bug.
00225         return writeMS(handler,complete);
00226       }
00227 #     endif
00228 
00229 
00230 #     ifndef _LTI_MSC_6
00231       /**
00232        * read the parameters from the given ioHandler
00233        * @param handler the ioHandler to be used
00234        * @param complete if true (the default) the enclosing begin/end will
00235        *        be also written, otherwise only the data block will be written.
00236        * @return true if write was successful
00237        */
00238       virtual bool read(ioHandler& handler,const bool complete=true)
00239 #     else
00240       /**
00241        * this function is required by MSVC only, as a workaround for a
00242        * very awful bug, which exists since MSVC V.4.0, and still by
00243        * V.6.0 with all bugfixes (so called "service packs") remains
00244        * there...  This method is also public due to another bug, so please
00245        * NEVER EVER call this method directly: use read() instead
00246        */
00247       bool readMS(ioHandler& handler,const bool complete=true)
00248 #     endif
00249       {
00250         bool b = true;
00251         if (complete) {
00252           b = handler.readBegin();
00253         }
00254         
00255         if (b) {
00256           
00257         }
00258 
00259 #       ifndef _LTI_MSC_6
00260         // This is the standard C++ code, which MS Visual C++ 6 is not
00261         // able to compile...
00262         b = b && linearAlgebraFunctor::parameters::read(handler,false);
00263 #       else
00264         bool (linearAlgebraFunctor::parameters::* p_readMS)(ioHandler&,
00265                                                         const bool) =
00266           linearAlgebraFunctor::parameters::readMS;
00267         b = b && (this->*p_readMS)(handler,false);
00268 #       endif
00269         b = b && lti::read(handler, "useLapack", useLapack);
00270         b = b && lti::read(handler, "performanceTweakThresholdForTranspose",
00271                            performanceTweakThresholdForTranspose);
00272 
00273         if (complete) {
00274           b = b && handler.readEnd();
00275         }
00276         
00277         return b;
00278       }
00279 
00280 #     ifdef _LTI_MSC_6
00281       /**
00282        * read the parameters from the given ioHandler
00283        * @param handler the ioHandler to be used
00284        * @param complete if true (the default) the enclosing begin/end will
00285        *        be also written, otherwise only the data block will be written.
00286        * @return true if write was successful
00287        */
00288       bool read(ioHandler& handler,const bool complete=true) {
00289         // ...we need this workaround to cope with another really awful MSVC
00290         // bug.
00291         return readMS(handler,complete);
00292       }
00293 #     endif
00294 
00295       // ------------------------------------------------
00296       // the parameters
00297       // ------------------------------------------------
00298 
00299       /** 
00300        * specifies if the lapack routine is used (if available) 
00301        * for qr-decomposition.
00302        * If LAPACK is not used or not available, A <b>must</b> be of full rang!
00303        *
00304        * Default: true */
00305       bool useLapack;
00306 
00307       /**
00308        * Specifies above which matrix size, the matrix is internally transposed.
00309        * This parameter takes only effect if useLapack is false or LAPACK is
00310        * not available.
00311        * Due to memory access isues, the algorithm works a lot faster 
00312        * especially for large matrices.
00313        * Both, collumns and rows are checked against this value. So a value of 50
00314        * means that the matrix must have at least 51 rows <b>and</b> at least 51 
00315        * columns to be transposed.
00316        *
00317        *
00318        * Default: _LTI_PERFORMANCE_QR_DECOMPOSITION in ltiPerformanceConfig.h
00319        */
00320       int performanceTweakThresholdForTranspose;
00321 
00322     };
00323 
00324     /**
00325      * Default constructor
00326      */
00327     qrDecomposition();
00328 
00329     /**
00330      * Construct a functor using the given parameters
00331      */
00332     qrDecomposition(const parameters& par);
00333 
00334     /**
00335      * Copy constructor
00336      * @param other the object to be copied
00337      */
00338     qrDecomposition(const qrDecomposition& other);
00339 
00340     /**
00341      * Destructor
00342      */
00343     virtual ~qrDecomposition();
00344 
00345     /**
00346      * Returns the name of this type ("qrDecomposition")
00347      */
00348     virtual const char* getTypeName() const;
00349 
00350     //TODO: comment your apply methods!
00351     
00352 
00353     /**
00354      * operates on the given %parameter.
00355      * @param srcdest matrix<T> with the source data.  The resulting Q
00356      *                 will be left here too.
00357      * @param r matrix<T> where R will be left.
00358      * @return true if apply successful or false otherwise.
00359      */
00360     bool apply(matrix<T>& srcdest, matrix<T>& r) const;
00361 
00362 
00363     /**
00364      * operates on a copy of the given %parameters.
00365      * @param src matrix<T> with the source data.
00366      * @param q matrix<T> where Q will be left.
00367      * @param r matrix<T> where R will be left.
00368      * @return true if apply successful or false otherwise.
00369      */
00370     bool apply(const matrix<T>& src, matrix<T>& q, matrix<T>& r) const;
00371 
00372     /**
00373      * Copy data of "other" functor.
00374      * @param other the functor to be copied
00375      * @return a reference to this functor object
00376      */
00377     qrDecomposition& copy(const qrDecomposition& other);
00378 
00379     /**
00380      * Alias for copy member
00381      * @param other the functor to be copied
00382      * @return a reference to this functor object
00383      */
00384     qrDecomposition& operator=(const qrDecomposition& other);
00385 
00386     /**
00387      * Returns a pointer to a clone of this functor.
00388      */
00389     virtual functor* clone() const;
00390 
00391     /**
00392      * Returns used parameters
00393      */
00394     const parameters& getParameters() const;
00395 
00396     //TODO: comment the attributes of your functor
00397     // If you add more attributes manually, do not forget to do following:
00398     // 1. indicate in the default constructor the default values
00399     // 2. make sure that the copy member also copy your new attributes, or
00400     //    to ensure there, that these attributes are properly initialized.
00401 
00402   private:
00403 
00404     /* 
00405      * transpose the given matrix perform a column based algorithm and
00406      * transpose result again.
00407      * r must be initiated before invokation
00408      */
00409     bool transApply(matrix<T>& srcdest, matrix<T>& r) const;
00410 
00411     
00412 #ifdef HAVE_LAPACK   
00413   // LAPACK routines in template form
00414 
00415     /*  SGEQRF computes a QR factorization of a real M-by-N matrix A:
00416      *  A = Q * R. */
00417     int geqrf(integer* rows, integer* cols, T* a, integer* lda, T* tau,
00418                T* work, integer* lwork, integer* info) const;
00419 
00420 
00421     /*  SORGQR generates an M-by-N real matrix Q with orthonormal columns,
00422      *  which is defined as the first N columns of a product of K elementary
00423      *  reflectors of order M
00424      *
00425      *        Q  =  H(1) H(2) . . . H(k)
00426      *
00427      *  as returned by SGEQRF. */
00428     int orgqr(integer* rows, integer* cols, integer* k,T* a, integer* lda,
00429                T* tau, T* work, integer* lwork, integer* info) const;
00430 #endif
00431 
00432 
00433   };
00434 }
00435 
00436 #endif

Generated on Sat Apr 10 15:26:01 2010 for LTI-Lib by Doxygen 1.6.1