Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

lusolve.h

00001 /***************************************************************************
00002                           lusolve.h  -  description
00003                              -------------------
00004     begin                : Mon May 8 2000
00005     copyright            : (C) 2000 by Michael Peeters
00006     email                : Michael.Peeters@vub.ac.be
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 #ifndef LUSOLVE_H
00019 #define LUSOLVE_H
00020 
00021 #include "utility.h"
00022 #include <stdexcept>
00023 #include "numerictraits.h"
00024 #include "numerictypes.h"
00025 
00026 namespace MODEL {
00027 
00028   template <integer dims, class NT = NumericTraits<number,dims> >
00029   class LUSolve
00030   {
00031   public:
00032         typedef typename NT::number     numT;
00033         typedef typename NT::vect       vect;   
00034         typedef typename NT::matrix     matrix;
00035                 
00036         LUSolve(matrix& m, bool own=false) : M(own?m.clone():&m), owned(own) {decompose();};
00037         ~LUSolve() {if(owned) delete M;}
00038                 
00040         vect    operator()(const vect& u) {vect res(u); solve(res); return
00041                                                                                                                                   res;}
00042 
00044         void    solve(vect& u);
00046         numT    det(void);
00047                 
00048   private:
00049         // to avoid silly errors
00050         NO_COPY(LUSolve);
00051                 
00052         // perform decomposition
00053         void    decompose(void);
00054 
00055   private:
00056         matrix*                                 M;              
00057         integer                                 pivotrows[dims];
00058         numT                                    pivotsign;
00059                         
00060         bool    owned;
00061 
00062         static const numT       tiny=1.E-20;
00063   };
00064 
00065   template <integer dims, class NT >
00066   void LUSolve<dims,NT>::decompose(void)
00067   {
00068     matrix&             a(*M);
00069 
00070         pivotsign=1.0;  
00071         vect    rowscale(1.);
00072         // Test for singularity
00073         for (integer i=0;i<dims;i++)
00074           {
00075                 numT big=0.0;
00076                 numT t(0.);
00077                 for (integer j=0;j<dims;j++)
00078                   if ((t=fabs(a[i][j])) > big) big=t;
00079                 if (big == 0.0) throw std::logic_error("Singular matrix in routine ludcmp");
00080                 rowscale[i]/=big;
00081           }
00082         
00083         numT sum(0.);
00084         for (integer j=0;j<dims;j++)
00085           {
00086                 for (integer i=0;i<j;i++)
00087                   {
00088                         sum=a[i][j];
00089                         for (integer k=0;k<i;k++) sum -= a[i][k]*a[k][j];
00090                         a[i][j]=sum;
00091                   }
00092                 numT    big(0.);
00093                 integer imax(-1);
00094                 numT    dum(0.);
00095                 for (integer i=j;i<dims;i++)
00096                   {
00097                         sum=a[i][j];
00098                         for (integer k=0;k<j;k++) sum -= a[i][k]*a[k][j];
00099                         a[i][j]=sum;
00100                         if ( (dum=rowscale[i]*abs(sum) ) >= big) {
00101                           big=dum;
00102                           imax=i;
00103                         }
00104                   }
00105                 if (j != imax) {
00106                   for (integer k=0;k<dims;k++) {
00107                         dum=a[imax][k];
00108                         a[imax][k]=a[j][k];
00109                         a[j][k]=dum;
00110                   }
00111                   pivotsign *= -1;
00112                   rowscale[imax]=rowscale[j];
00113                 }
00114                 pivotrows[j]=imax;
00115                 if (a[j][j] == 0.0) a[j][j]=tiny;
00116                 if (j != (dims-1)) {
00117                   dum=1.0/(a[j][j]);
00118                   for (integer i=j+1;i<dims;i++) a[i][j] *= dum;
00119                 }
00120           }
00121   }
00122 
00123   template <integer dims, class NT>
00124   void LUSolve<dims,NT>::solve(vect& u)
00125   {
00126     matrix&             a(*M);
00127     numT                sum(0.);
00128         integer         ii(-1);
00129         bool    nonzero=false;
00130         
00131         for (integer i=0;i<dims;i++)
00132           {             
00133                 integer ip=pivotrows[i];
00134                 sum=u[ip];
00135                 u[ip]=u[i];
00136                 
00137                 if (nonzero) for (integer j=ii;j<i;j++) sum -= a[i][j]*u[j];
00138                 else if (sum!=0.0) {nonzero=true; ii=i;}
00139                 
00140                 u[i]=sum;
00141           }
00142         for (integer i(dims-1);i>=0;i--) {
00143           sum = u[i];
00144           for (integer j(i+1);j<dims;j++) sum -= a[i][j]*u[j];
00145           u[i]=sum/a[i][i];
00146         }
00147   }
00148 
00149   template <integer dims, class NT>
00150   LUSolve<dims,NT>::numT        
00151   LUSolve<dims,NT>::det(void)
00152   {
00153         numT    d(pivotsign);
00154         for(integer j=0;j<dims;j++) d *= (*M)[j][j];
00155         return d;
00156   }
00157 
00158 
00159 } // end MODEL;
00160 
00161 #endif
00162 
00163 /*********************************************************************
00164 $Id: lusolve.h,v 1.1.2.1 2001/11/15 13:33:26 mpeeters Exp $
00165 **********************************************************************
00166 
00167 $Log: lusolve.h,v $
00168 Revision 1.1.2.1  2001/11/15 13:33:26  mpeeters
00169 Last commit before moving everything to new gcc stdc++ headers (3.0).
00170 
00171 Revision 1.1  2001/05/22 10:54:55  mpeeters
00172 Moved sources and headers for libModel to model/ subdirectory, in an attempt to rationalize the source tree. This should make things "netter".
00173 
00174 Revision 1.4  2001/05/21 11:53:16  mpeeters
00175 Removed Makefile.in, which is automatically generated anyway.
00176 
00177 Revision 1.3  2000/09/22 08:54:08  mpeeters
00178 Changed dependencies. Missed this one on the last commit
00179 
00180 Revision 1.2  2000/09/15 10:26:31  mpeeters
00181 Cleaned out header and added CVS tails to files, removed superfuous
00182 @author comments, inserted dates
00183 
00184 *********************************************************************/

To get the sources or tarballs, please go to SourceForge or you can use the CVS repository.

More Info? Michael Peeters. Also, check our research website: www.alna.vub.ac.be

Last update: June 2002.


Looking for Open Source? Check out SourceForge Logo !