namespace ewalena  0.2.15
ewalena is not an acronym
include/ewalena/lac/solver_jacobi.h
Go to the documentation of this file.
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 */
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines