namespace ewalena
0.2.15
ewalena is not an acronym
|
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 */