namespace ewalena  0.2.15
ewalena is not an acronym
include/ewalena/lac/solver_qr.h
Go to the documentation of this file.
00001 // -------------------------------------------------------------------
00002 // @author Toby D. Young
00003 // @version $Id: solver_qr.h 987 2012-11-26 15:16:27Z oneliefleft $
00004 //
00005 // Copyright 2012 namespace ewalena authors. All rights reserved.
00006 //
00007 // Redistribution and use in source and binary forms, with or without
00008 // modification, are permitted provided that the following conditions
00009 // are met:
00010 //
00011 // 1. Redistributions of source code must retain the above copyright
00012 //    notice, this list of conditions and the following disclaimer.
00013 //
00014 // 2. Redistributions in binary form must reproduce the above
00015 //    copyright notice, this list of conditions and the following
00016 //    disclaimer in the documentation and/or other materials provided
00017 //    with the distribution.
00018 //
00019 // THIS SOFTWARE IS PROVIDED BY THE NAMEPSACE EWALENA AUTHORS ``AS
00020 // IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00021 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00022 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00023 // NAMESPACE EWALENA AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
00024 // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00025 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00026 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00027 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
00028 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00029 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
00030 // OF THE POSSIBILITY OF SUCH DAMAGE.
00031 //
00032 // The views and conclusions contained in the software and
00033 // documentation are those of the authors and should not be
00034 // interpreted as representing official policies, either expressed or
00035 // implied, of the namespace ewalena authors.
00036 // -------------------------------------------------------------------
00037 
00038 #ifndef __ewalena_solver_qr_h
00039 #define __ewalena_solver_qr_h
00040 
00041 #ifdef EWALENA_HAVE_CONFIG_H
00042 #include <ewalena/base/config.h>
00043 #endif
00044 
00045 #include <ewalena/lac/solver_base.h>
00046 
00047 #include <algorithm>
00048 
00049 namespace ewalena 
00050 {
00051 
00057   template <typename ValueType = double>
00058     class SolverQR
00059     : 
00060     public SolverBase<ValueType>
00061     {
00062       
00063     public:
00064 
00068     SolverQR (SolverControl<ValueType> &solver_control);
00069     
00073     virtual void solve (const Matrix<ValueType> &A,
00074                         Vector<ValueType>       &lambda,
00075                         VectorBasis<ValueType>  &x);
00076     
00077     protected:
00078     
00084     void reduce_to_hessenberg_form (Matrix<ValueType> &matrix);
00085     
00086     }; /* SolverJacobi */
00087 
00088   /*-------------- Inline and Other Functions -----------------------*/
00089   
00090   template <typename ValueType>
00091     inline
00092     ValueType
00093     sign (const ValueType a,
00094           const ValueType b)
00095     {
00096       return (b>ValueType (0)) ? fabs (a) : -fabs (a);
00097     }
00098   
00099   template <typename ValueType>
00100     inline
00101     void
00102     SolverQR<ValueType>::reduce_to_hessenberg_form (Matrix<ValueType> &matrix)
00103     {
00104       assert (matrix.n_rows () == matrix.n_cols ());
00105       assert (matrix.n_cols () != 0);
00106 
00107       /* Trivial Hessenberg form already? */
00108       if (matrix.n_rows () < 3)
00109         return;  
00110 
00111       /* m = r+1 in "Numerical Recipes in C++". */
00112       for (unsigned int m=1; m<(matrix.n_rows ()-1); ++m)
00113         {
00114           unsigned int i = m;
00115           ValueType    x = ValueType (0);
00116 
00117           /* Find a pivot. */
00118           for (unsigned int j=m; j<matrix.n_rows (); ++j)
00119             if (std::fabs (matrix(j,m-1)) > std::fabs (x))
00120               {
00121                 x = matrix(j,m-1); 
00122                 i = j; 
00123               }
00124 
00125           /* Interchange rows and columns. */
00126           if (i != m)
00127             {
00128               for (unsigned int j=m-1; j<matrix.n_rows (); ++j)
00129                 std::swap (matrix(i,j), matrix(m,j));
00130               
00131               for (unsigned int j=0; j<matrix.n_rows (); ++j)
00132                 std::swap (matrix(j,i), matrix(j,m));
00133             }
00134 
00135           /* Do elimination. */
00136           if (x)
00137             {
00138               for (unsigned int i=m+1; i<matrix.n_rows (); ++i)
00139                 {
00140                   ValueType y = matrix(i,m-1);
00141                   if (y != ValueType(0))
00142                     {
00143                       y        /= x;
00144                       matrix(i,m-1)  = y;
00145                       
00146                       for (unsigned int j=m; j<matrix.n_rows (); ++j)
00147                         matrix(i,j) -= y*matrix(m,j);
00148 
00149                       for (unsigned int j=0; j<matrix.n_rows (); ++j)
00150                         matrix(j,m) += y*matrix(j,i) ;
00151                     }
00152                 }
00153             }
00154           
00155         }
00156 
00157 
00158       /* Explicitly zero out lower elements here (remove round-off
00159          errors and/or overflow). */
00160       for (unsigned int j=0; j<matrix.n_cols (); ++j)
00161         for (unsigned int i=j+2; i<matrix.n_rows (); ++i)
00162           matrix(i,j) = ValueType(0);
00163       
00164     }
00165 
00166 } /* namespace ewalena */
00167 
00168 #endif /* __ewalena_solver_qr_h */
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines