namespace ewalena
0.2.15
ewalena is not an acronym
|
00001 // ------------------------------------------------------------------- 00002 // @author Toby D. Young 00003 // @version $Id: solver_jacobi.h 988 2012-11-26 19:09:39Z 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_jacobi_h 00039 #define __ewalena_solver_jacobi_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 namespace ewalena 00048 { 00049 00064 template <typename ValueType = double> 00065 class SolverJacobi 00066 : 00067 public SolverBase<ValueType> 00068 { 00069 00070 public: 00071 00075 SolverJacobi (SolverControl<ValueType> &solver_control); 00076 00080 virtual void solve (const Matrix<ValueType> &A, 00081 Vector<ValueType> &lambda, 00082 VectorBasis<ValueType> &X); 00083 00084 protected: 00085 00092 void do_jacobi_rotation (ValueType *index_i, 00093 ValueType *index_j, 00094 const ValueType &root); 00095 00100 void sort (Vector<ValueType> &lambda); 00101 00106 void sort (Vector<ValueType> &lambda, 00107 VectorBasis<ValueType> &X); 00108 00109 }; /* SolverJacobi */ 00110 00111 /*-------------- Inline and Other Functions -----------------------*/ 00112 00113 template <typename ValueType> 00114 inline 00115 void 00116 SolverJacobi<ValueType>::do_jacobi_rotation (ValueType *index_i, 00117 ValueType *index_j, 00118 const ValueType &root) 00119 { 00120 const ValueType c = ValueType(1) / sqrt(root*root+ValueType(1)); 00121 const ValueType s = root*c; 00122 const ValueType tau = s / (ValueType(1)+c); 00123 const ValueType tmp_1 = *index_i; 00124 const ValueType tmp_2 = *index_j; 00125 00126 *index_i -= s*(tmp_2 + tmp_1*tau); 00127 *index_j += s*(tmp_1 - tmp_2*tau); 00128 } 00129 00130 template <typename ValueType> 00131 inline 00132 void 00133 SolverJacobi<ValueType>::sort (Vector<ValueType> &lambda) 00134 { 00135 00136 /* Track if swapping is taking place. */ 00137 bool swapped = false; 00138 00139 /* Loop over all eigenvalues. */ 00140 for (unsigned int i=0; i<lambda.size (); ++i) 00141 { 00142 00143 /* We haven't swapped anything yet. */ 00144 swapped = false; 00145 00146 for (unsigned int j=i+1; j<lambda.size (); ++j) 00147 { 00148 if (lambda(i)>lambda(j)) 00149 { 00150 /* Swap the eigenvalues. */ 00151 const ValueType tmp_value = lambda(i); 00152 lambda(i) = lambda(j); 00153 lambda(j) = tmp_value; 00154 00155 swapped = true; 00156 } 00157 } 00158 00159 /* If no swapping is taking place then the algorithm is 00160 done. */ 00161 if (!swapped) 00162 return; 00163 00164 } 00165 00166 /* If the eigenvalues are not in order by now, something went 00167 deeply wrong... */ 00168 if (swapped) 00169 assert (false); 00170 } 00171 00172 template <typename ValueType> 00173 inline 00174 void 00175 SolverJacobi<ValueType>::sort (Vector<ValueType> &lambda, 00176 VectorBasis<ValueType> &X) 00177 { 00178 00179 /* Track if swapping is taking place. */ 00180 bool swapped = false; 00181 00182 /* Loop over all eigenvalues. */ 00183 for (unsigned int i=0; i<lambda.size (); ++i) 00184 { 00185 00186 /* We haven't swapped anything yet. */ 00187 swapped = false; 00188 00189 for (unsigned int j=i+1; j<lambda.size (); ++j) 00190 { 00191 if (lambda(i)>lambda(j)) 00192 { 00193 00194 /* Swap the eigenvalues. */ 00195 const ValueType tmp_value = lambda(i); 00196 lambda(i) = lambda(j); 00197 lambda(j) = tmp_value; 00198 00199 /* Swap the eigenvectors by column. */ 00200 Vector<ValueType> tmp_vector (X.n_rows ()); 00201 00202 for (unsigned int k=0; k<X.n_rows (); ++k) 00203 { 00204 tmp_vector(k) = X(k,i); 00205 X(k,i) = X(k,j); 00206 X(k,j) = tmp_vector(k); 00207 } 00208 00209 swapped = true; 00210 } 00211 } 00212 00213 /* If no swapping is taking place then the algorithm is 00214 done. */ 00215 if (!swapped) 00216 return; 00217 00218 } 00219 00220 /* If the eigenvalues are not in order by now, something went 00221 deeply wrong... */ 00222 if (swapped) 00223 assert (false); 00224 } 00225 00226 } /* namespace ewalena */ 00227 00228 #endif /* __ewalena_solver_jacobi_h */