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

matrix.h

Go to the documentation of this file.
00001 #ifndef fl_matrix_h
00002 #define fl_matrix_h
00003 
00004 
00005 #include "fl/pointer.h"
00006 
00007 #include <math.h>
00008 #include <iostream>
00009 #include <sstream>
00010 #include <vector>
00011 #include <map>
00012 #include <complex>
00013 
00014 
00015 // The linear algebra package has the following goals:
00016 // * Be simple and straightforward for a programmer to use.  It should be
00017 //   easy to express most common linear algebra calculations using
00018 //   overloaded operators.
00019 // * Work seamlessly with LAPACK.  To this end, storage is always column
00020 //   major.
00021 // * Be lightweight to compile.  We avoid putting much implementation in
00022 //   the headers, even though we are using templates.
00023 // * Be lightweight at run-time.  Eg: shallow copy semantics, and only a
00024 //   couple of variables that need to be copied.  Should limit total copying
00025 //   to 16 bytes or less.
00026 
00027 // Other notes:
00028 // * In general, the implementation does not protect you from shooting yourself
00029 //   in the foot.  Specifically, there is no range checking or verification
00030 //   that memory addresses are valid.  All these do is make a bug easier to
00031 //   find (rather than eliminate it), and they cost at runtime.  In cases
00032 //   where there is some legitimate interpretation of bizarre parameter values,
00033 //   we assume the programmer meant that interpretation and plow on.
00034 
00035 
00036 namespace fl
00037 {
00038   // Forward declarations
00039   template<class T> class Matrix;
00040   template<class T> class MatrixTranspose;
00041   template<class T> class MatrixRegion;
00042 
00043 
00044   // Matrix general interface -------------------------------------------------
00045 
00051   template<class T>
00052   class MatrixAbstract
00053   {
00054   public:
00055         virtual ~MatrixAbstract ();
00056 
00057         // Assignment should be shallow copy when possible, but may be deep copy
00058         // if convenient to the class.  Tip: never rely on shallow copy semantics.
00059         // Ie: never expect a change in one matrix to be reflected in another.
00060         // Also never rely on deep copy semantics unless it is guaranteed by a
00061         // function.
00062         // No assignment operator is defined at this level because it would have
00063         // bad interactions with automatically generated assignment operators
00064         // in derived classes.
00065 
00066         // Structural functions
00067         // These are the core functions in terms of which most other functions can
00068         // be implemented.  To some degree, they abstract away the actual storage
00069         // structure of the matrix.
00070         virtual T & operator () (const int row, const int column) const = 0;  
00071     virtual T & operator [] (const int row) const;  
00072         virtual int rows () const;
00073         virtual int columns () const;
00074         virtual MatrixAbstract * duplicate () const = 0; 
00075         virtual void clear (const T scalar = (T) 0);  
00076         virtual void resize (const int rows, const int columns = 1) = 0;  
00077 
00078         // Higher level functions
00079         virtual T frob (T n) const;  
00080         virtual T sumSquares () const;  
00081         virtual void normalize (const T scalar = 1.0);  
00082         virtual T dot (const MatrixAbstract & B) const;  
00083         virtual Matrix<T> cross (const MatrixAbstract & B) const;  
00084         virtual void identity (const T scalar = 1.0);  
00085         virtual MatrixRegion<T> row (const int r) const;  
00086         virtual MatrixRegion<T> column (const int c) const;  
00087         virtual MatrixRegion<T> region (const int firstRow = 0, const int firstColumn = 0, int lastRow = -1, int lastColumn = -1) const;  
00088 
00089         // Basic operations
00090 
00091         // The reason to have operators at this abstract level is to allow some
00092         // manipulation of matrices even if we know nothing of their storage
00093         // method.  The other possible motivation (laziness thru inheritance)
00094         // doesn't really pan out, since C++ tries to resolve an overloaded
00095         // function name in the current class rather than looking up the hierarchy.
00096         // However, polymorphism is still a valid motivation.
00097 
00098         // Ideally, if a subclass reimplements one of these operations, the return
00099         // type should be as specific as possible.  Unfortunately, some C++
00100         // compilers (namely MS VC++) won't allow a subclass to be declared as
00101         // the return type of an overidden function.  Therefore, once we declare
00102         // these operations, the return type becomes "nailed down" for all
00103         // subclasses.  If a given return type is not universally useful, the
00104         // function can't be declared (or used) at this abstract level.
00105         // * Some operations that involve MatrixAbstract must return a dense
00106         // matrix.  For these, we know the return type must be Matrix.
00107         // * The notation "M<T>" in commented out interfaces means that it is
00108         // better to return the actual type of the subclass.
00109         // * We can be less picky about return type for *= /= += -= because they
00110         // usually won't be in the middle of an expression.
00111 
00112         // For basic arithmetic each class may have up to 24 operators:
00113         // 3 overloads for each of 8 operators: * / + - *= /= += -=
00114         // The overloads are for: 1) MatrixAbstract, 2) the current class,
00115         // and 3) a scalar.  A class may have more overloads if it wishes to
00116         // directly interract with other matrix classes.
00117 
00118         virtual bool operator == (const MatrixAbstract & B) const;  
00119         bool operator != (const MatrixAbstract & B) const
00120         {
00121           return ! ((*this) == B);
00122         }
00123 
00124         //virtual M<T> operator ! () const;  ///< Invert matrix (or create pseudo-inverse)
00125         //virtual M<T> operator ~ () const;  ///< Transpose matrix
00126 
00127         virtual Matrix<T> operator * (const MatrixAbstract & B) const;  
00128         //virtual M<T> operator * (const T scalar) const;  ///< Multiply each element by scalar
00129         virtual Matrix<T> elementMultiply (const MatrixAbstract & B) const;  
00130         //virtual Matrix<T> operator / (const MatrixAbstract & B) const;  ///< Elementwise division.  Could mean this * !B, but such expressions are done other ways in linear algebra.
00131         //virtual M<T> operator / (const T scalar) const;  ///< Divide each element by scalar
00132         virtual Matrix<T> operator + (const MatrixAbstract & B) const;  
00133         //virtual M<T> operator + (const T scalar) const;  ///< Add scalar to each element
00134         virtual Matrix<T> operator - (const MatrixAbstract & B) const;  
00135         //virtual M<T> operator - (const T scalar) const;  ///< Subtract scalar from each element
00136 
00137         virtual MatrixAbstract & operator *= (const MatrixAbstract & B);  
00138         virtual MatrixAbstract & operator *= (const T scalar);  
00139         //virtual MatrixAbstract & operator /= (const MatrixAbstract & B);  ///< Elementwise divide and store back to this
00140         virtual MatrixAbstract & operator /= (const T scalar);  
00141         virtual MatrixAbstract & operator += (const MatrixAbstract & B);  
00142         //virtual MatrixAbstract & operator += (const T scalar);  ///< Increase each element by scalar
00143         virtual MatrixAbstract & operator -= (const MatrixAbstract & B);  
00144         virtual MatrixAbstract & operator -= (const T scalar);  
00145 
00146         // Serialization
00147         virtual void read (std::istream & stream);
00148         virtual void write (std::ostream & stream, bool withName = false) const;
00149 
00150         // Global Data
00151         static int displayWidth;  
00152         static int displayPrecision;  
00153   };
00154 
00155 
00156   // Concrete matrices  -------------------------------------------------------
00157 
00158   template<class T>
00159   class Matrix : public MatrixAbstract<T>
00160   {
00161   public:
00162         Matrix ();
00163         Matrix (const int rows, const int columns = 1);
00164         Matrix (const MatrixAbstract<T> & that);
00165         template<class T2>
00166         Matrix (const MatrixAbstract<T2> & that)
00167         {
00168           int h = that.rows ();
00169           int w = that.columns ();
00170           resize (h, w);
00171           T * i = (T *) data;
00172           for (int c = 0; c < w; c++)
00173           {
00174                 for (int r = 0; r < h; r++)
00175                 {
00176                   *i++ = (T) that (r, c);
00177                 }
00178           }
00179         }
00180         Matrix (std::istream & stream);
00181         Matrix (T * that, const int rows, const int columns = 1);  
00182         Matrix (Pointer & that, const int rows = -1, const int columns = 1);  
00183         virtual ~Matrix ();
00184         void detach ();  
00185 
00186         virtual T & operator () (const int row, const int column) const
00187         {
00188           return ((T *) data)[column * rows_ + row];
00189         }
00190     virtual T & operator [] (const int row) const
00191         {
00192           return ((T *) data)[row];
00193         }
00194         virtual int rows () const;
00195         virtual int columns () const;
00196         virtual MatrixAbstract<T> * duplicate () const;
00197         virtual void clear (const T scalar = (T) 0);
00198         virtual void resize (const int rows, const int columns = 1);
00199         virtual void copyFrom (const Matrix<T> & that);
00200 
00201         virtual Matrix reshape (const int rows, const int columns = 1) const;
00202 
00203         virtual T frob (T n) const;
00204         virtual T sumSquares () const;
00205         virtual T dot (const Matrix & B) const;
00206         virtual Matrix transposeSquare () const;  
00207 
00208         virtual MatrixTranspose<T> operator ~ () const;
00209         virtual Matrix operator * (const MatrixAbstract<T> & B) const;
00210         virtual Matrix operator * (const Matrix & B) const;
00211         virtual Matrix operator * (const T scalar) const;
00212         virtual Matrix operator / (const T scalar) const;
00213         virtual Matrix operator + (const Matrix & B) const;
00214         virtual Matrix operator - (const Matrix & B) const;
00215 
00216         virtual Matrix & operator *= (const Matrix & B);
00217         virtual MatrixAbstract<T> & operator *= (const T scalar);
00218         virtual MatrixAbstract<T> & operator /= (const T scalar);
00219         virtual Matrix & operator += (const Matrix & B);
00220         virtual Matrix & operator -= (const Matrix & B);
00221         virtual MatrixAbstract<T> & operator -= (const T scalar);
00222 
00223         virtual void read (std::istream & stream);
00224         virtual void write (std::ostream & stream, bool withName = false) const;
00225 
00226         // Data
00227         Pointer data;
00228         int rows_;
00229         int columns_;
00230   };
00231 
00238   template<class T>
00239   class Vector : public Matrix<T>
00240   {
00241   public:
00242         Vector ();
00243         Vector (const int rows);
00244         Vector (const MatrixAbstract<T> & that);
00245         template<class T2>
00246         Vector (const MatrixAbstract<T2> & that)
00247         {
00248           int h = that.rows ();
00249           int w = that.columns ();
00250           resize (h, w);
00251           T * i = (T *) data;
00252           for (int c = 0; c < w; c++)
00253           {
00254                 for (int r = 0; r < h; r++)
00255                 {
00256                   *i++ = (T) that (r, c);
00257                 }
00258           }
00259         }
00260         Vector (const Matrix<T> & that);
00261         Vector (std::istream & stream);
00262         Vector (T * that, const int rows);  
00263         Vector (Pointer & that, const int rows = -1);  
00264 
00265         Vector & operator = (const MatrixAbstract<T> & that);
00266         Vector & operator = (const Matrix<T> & that);
00267 
00268         virtual MatrixAbstract<T> * duplicate () const;
00269         virtual void resize (const int rows, const int columns = 1);
00270   };
00271 
00281   template<class T>
00282   class MatrixPacked : public MatrixAbstract<T>
00283   {
00284   public:
00285         MatrixPacked ();
00286         MatrixPacked (const int rows);  
00287         MatrixPacked (const MatrixAbstract<T> & that);
00288         MatrixPacked (std::istream & stream);
00289 
00290         virtual T & operator () (const int row, const int column) const;
00291     virtual T & operator [] (const int row) const;
00292         virtual int rows () const;
00293         virtual int columns () const;
00294         virtual MatrixAbstract<T> * duplicate () const;
00295         virtual void clear (const T scalar = (T) 0);
00296         virtual void resize (const int rows, const int columns = -1);
00297         virtual void copyFrom (const MatrixAbstract<T> & that);
00298         virtual void copyFrom (const MatrixPacked & that);
00299 
00300         virtual MatrixPacked operator ~ () const;
00301 
00302         virtual void read (std::istream & stream);
00303         virtual void write (std::ostream & stream, bool withName = false) const;
00304 
00305         // Data
00306         Pointer data;
00307         int rows_;  
00308   };
00309 
00317   template<class T>
00318   class MatrixSparse : public MatrixAbstract<T>
00319   {
00320   public:
00321         MatrixSparse ();
00322         MatrixSparse (const int rows, const int columns);
00323         MatrixSparse (const MatrixAbstract<T> & that);
00324         MatrixSparse (std::istream & stream);
00325         ~MatrixSparse ();
00326 
00327         void set (const int row, const int column, const T value);  
00328         virtual T & operator () (const int row, const int column) const;
00329         virtual int rows () const;
00330         virtual int columns () const;
00331         virtual MatrixAbstract<T> * duplicate () const;
00332         virtual void clear (const T scalar = (T) 0);  
00333         virtual void resize (const int rows, const int columns = 1);  
00334         virtual void copyFrom (const MatrixSparse & that);
00335 
00336         virtual T frob (T n) const;
00337 
00338         virtual MatrixSparse operator - (const MatrixSparse & B) const;
00339 
00340         virtual void read (std::istream & stream);
00341         virtual void write (std::ostream & stream, bool withName = false) const;
00342 
00343         int rows_;
00344         fl::SmartPointer< std::vector< std::map<int, T> > > data;
00345   };
00346 
00351   template<class T>
00352   class MatrixIdentity : public MatrixAbstract<T>
00353   {
00354   public:
00355         MatrixIdentity ();
00356         MatrixIdentity (int size, T value = 1);
00357 
00358         virtual T & operator () (const int row, const int column) const;
00359         virtual int rows () const;
00360         virtual int columns () const;
00361         virtual MatrixAbstract<T> * duplicate () const;
00362         virtual void clear (const T scalar = (T) 0);
00363         virtual void resize (const int rows, const int columns = -1);
00364 
00365         int size;
00366         T value;
00367   };
00368 
00373   template<class T>
00374   class MatrixDiagonal : public MatrixAbstract<T>
00375   {
00376   public:
00377         MatrixDiagonal ();
00378         MatrixDiagonal (const int rows, const int columns = -1);
00379         MatrixDiagonal (const Vector<T> & that, const int rows = -1, const int columns = -1);
00380 
00381         virtual T & operator () (const int row, const int column) const;
00382     virtual T & operator [] (const int row) const;
00383         virtual int rows () const;
00384         virtual int columns () const;
00385         virtual MatrixAbstract<T> * duplicate () const;
00386         virtual void clear (const T scalar = (T) 0);
00387         virtual void resize (const int rows, const int columns = -1);
00388 
00389         int rows_;
00390         int columns_;
00391         Pointer data;
00392   };
00393 
00394 
00395   // Views --------------------------------------------------------------------
00396 
00397   // These matrices wrap other matrices and provide a different interpretation
00398   // of the row and column coordinates.  Views are always "dense" in the sense
00399   // that every element maps to an element in the wrapped Matrix.  However,
00400   // they have no storage of their own.
00401 
00402   // Views do two jobs:
00403   // 1) Make it convenient to access a Matrix in manners other than dense.
00404   //    E.g.: You could do strided access without having to write out the
00405   //    index offsets and multipliers.
00406   // 2) Act as a proxy for some rearrangement of the Matrix in the next
00407   //    stage of calculation in order to avoid copying elements.
00408   //    E.g.: A Transpose view allows one to multiply a transposed Matrix
00409   //    without first moving all the elements to their tranposed positions.
00410 
00412   template<class T>
00413   class MatrixTranspose : public MatrixAbstract<T>
00414   {
00415   public:
00416         MatrixTranspose (const MatrixAbstract<T> & that);
00417         virtual ~MatrixTranspose ();
00418 
00419         virtual T & operator () (const int row, const int column) const
00420         {
00421           return (*wrapped) (column, row);
00422         }
00423     virtual T & operator [] (const int row) const
00424         {
00425           return (*wrapped)[row];
00426         }
00427         virtual int rows () const;
00428         virtual int columns () const;
00429         virtual MatrixAbstract<T> * duplicate () const;
00430         virtual void clear (const T scalar = (T) 0);
00431         virtual void resize (const int rows, const int columns);
00432 
00433         // It is the job of the matrix being transposed to make another instance
00434         // of itself.  It is our responsibility to delete this object when we
00435         // are destroyed.
00436         MatrixAbstract<T> * wrapped;
00437   };
00438 
00439   template<class T>
00440   class MatrixRegion : public MatrixAbstract<T>
00441   {
00442   public:
00443         MatrixRegion (const MatrixRegion & that);
00444         MatrixRegion (const MatrixAbstract<T> & that, const int firstRow = 0, const int firstColumn = 0, int lastRow = -1, int lastColumn = -1);
00445         virtual ~MatrixRegion ();
00446 
00447         template<class T2>
00448         MatrixRegion & operator = (const MatrixAbstract<T2> & that)
00449         {
00450           int h = that.rows ();
00451           int w = that.columns ();
00452           resize (h, w);
00453           for (int c = 0; c < w; c++)
00454           {
00455                 for (int r = 0; r < h; r++)
00456                 {
00457                   (*this)(r,c) = (T) that(r,c);
00458                 }
00459           }
00460           return *this;
00461         }
00462         MatrixRegion & operator = (const MatrixRegion & that);
00463 
00464         virtual T & operator () (const int row, const int column) const
00465         {
00466           return (*wrapped)(row + firstRow, column + firstColumn);
00467         }
00468     virtual T & operator [] (const int row) const
00469         {
00470           return (*wrapped)(row % rows_ + firstRow, row / rows_ + firstColumn);
00471         }
00472         virtual int rows () const;
00473         virtual int columns () const;
00474         virtual MatrixAbstract<T> * duplicate () const;
00475         virtual void clear (const T scalar = (T) 0);
00476         virtual void resize (const int rows, const int columns = 1);
00477 
00478         virtual MatrixTranspose<T> operator ~ () const;
00479         virtual Matrix<T> operator * (const MatrixAbstract<T> & B) const;
00480         virtual Matrix<T> operator * (const T scalar) const;
00481 
00482         MatrixAbstract<T> * wrapped;
00483         int firstRow;
00484         int firstColumn;
00485         int rows_;
00486         int columns_;
00487   };
00488 
00489 
00490   // Small Matrix classes -----------------------------------------------------
00491 
00492   // There are two reasons for making small Matrix classes.
00493   // 1) Avoid overhead of managing memory.
00494   // 2) Certain numerical operations (such as computing eigenvalues) have
00495   //    direct implementations in small matrix sizes (particularly 2x2).
00496 
00497   template<class T>
00498   class Matrix2x2 : public MatrixAbstract<T>
00499   {
00500   public:
00501         Matrix2x2 ();
00502         template<class T2>
00503         Matrix2x2 (const MatrixAbstract<T2> & that)
00504         {
00505           // We assume that we wouldn't assign to an explicit Matrix2x2 unless
00506           // we knew that the source is in fact at least 2 by 2.
00507           data[0][0] = (T) that(0,0);
00508           data[0][1] = (T) that(1,0);
00509           data[1][0] = (T) that(0,1);
00510           data[1][1] = (T) that(1,1);
00511         }
00512         Matrix2x2 (std::istream & stream);
00513 
00514         virtual T & operator () (const int row, const int column) const
00515         {
00516           return (T &) data[column][row];
00517         }
00518     virtual T & operator [] (const int row) const
00519         {
00520           return ((T *) data)[row];
00521         }
00522         virtual int rows () const;
00523         virtual int columns () const;
00524         virtual MatrixAbstract<T> * duplicate () const;
00525         virtual void resize (const int rows = 2, const int columns = 2);
00526         // We don't need copyFrom () because all assignments and constructors do
00527         // deep copy.
00528 
00529         virtual Matrix2x2<T> operator ! () const;
00530         virtual Matrix2x2<T> operator ~ () const;
00531         virtual Matrix<T> operator * (const MatrixAbstract<T> & B) const;
00532         virtual Matrix2x2<T> operator * (const Matrix2x2<T> & B) const;
00533         virtual Matrix2x2<T> operator * (const T scalar) const;
00534         virtual Matrix2x2<T> operator / (const T scalar) const;
00535         virtual Matrix2x2<T> & operator *= (const Matrix2x2<T> & B);
00536         virtual MatrixAbstract<T> & operator *= (const T scalar);
00537 
00538         virtual void read (std::istream & stream);
00539         virtual void write (std::ostream & stream, bool withName = false) const;
00540 
00541         // Data
00542         T data[2][2];
00543   };
00544 
00545   template<class T>
00546   class Matrix3x3 : public MatrixAbstract<T>
00547   {
00548   public:
00549         Matrix3x3 ();
00550         template<class T2>
00551         Matrix3x3 (const MatrixAbstract<T2> & that)
00552         {
00553           data[0][0] = (T) that(0,0);
00554           data[0][1] = (T) that(1,0);
00555           data[0][2] = (T) that(2,0);
00556           data[1][0] = (T) that(0,1);
00557           data[1][1] = (T) that(1,1);
00558           data[1][2] = (T) that(2,1);
00559           data[2][0] = (T) that(0,2);
00560           data[2][1] = (T) that(1,2);
00561           data[2][2] = (T) that(2,2);
00562         }
00563         Matrix3x3 (std::istream & stream);
00564 
00565         virtual T & operator () (const int row, const int column) const
00566         {
00567           return (T &) data[column][row];
00568         }
00569     virtual T & operator [] (const int row) const
00570         {
00571           return ((T *) data)[row];
00572         }
00573         virtual int rows () const;
00574         virtual int columns () const;
00575         virtual MatrixAbstract<T> * duplicate () const;
00576         virtual void resize (const int rows = 3, const int columns = 3);
00577 
00578         virtual Matrix<T> operator * (const MatrixAbstract<T> & B) const;
00579 
00580         virtual void read (std::istream & stream);
00581         virtual void write (std::ostream & stream, bool withName = false) const;
00582 
00583         // Data
00584         T data[3][3];
00585   };
00586 
00587 
00588   // Matrix operations --------------------------------------------------------
00589 
00591   template<class T>
00592   inline std::ostream &
00593   operator << (std::ostream & stream, const MatrixAbstract<T> & A)
00594   {
00595         for (int r = 0; r < A.rows (); r++)
00596         {
00597           if (r > 0)
00598           {
00599                 if (A.columns () > 1)
00600                 {
00601                   stream << std::endl;
00602                 }
00603                 else  // This is really a vector, so don't break lines.
00604                 {
00605                   stream << " ";
00606                 }
00607           }
00608           std::string line;
00609           for (int c = 0; c < A.columns (); c++)
00610           {
00611                 // Let ostream absorb the variability in the type T of the matrix.
00612                 // This may not work as expected for type char, because ostreams treat
00613                 // chars as characters, not numbers.
00614                 std::ostringstream formatted;
00615                 formatted.precision (A.displayPrecision);
00616                 formatted << A (r, c);
00617                 if (c > 0)
00618                 {
00619                   line += ' ';
00620                 }
00621                 while (line.size () < c * A.displayWidth)
00622                 {
00623                   line += ' ';
00624                 }
00625                 line += formatted.str ();
00626           }
00627           stream << line;
00628         }
00629         return stream;
00630   }
00631 
00632 
00639   template<class T>
00640   inline std::istream &
00641   operator >> (std::istream & stream, MatrixAbstract<T> & A)
00642   {
00643         int rows;
00644         int columns;
00645         stream >> rows >> columns;
00646         A.resize (rows, columns);
00647 
00648         for (int r = 0; r < rows; r++)
00649         {
00650           for (int c = 0; c < columns; c++)
00651           {
00652                 stream >> A(r, c);
00653           }
00654         }
00655         return stream;
00656   }
00657 
00662   template<class T>
00663   inline MatrixAbstract<T> &
00664   operator << (MatrixAbstract<T> & A, const std::string & source)
00665   {
00666         std::istringstream stream (source);
00667         int rows = A.rows ();
00668         int columns = A.columns ();
00669         for (int r = 0; r < rows; r++)
00670         {
00671           for (int c = 0; c < columns; c++)
00672           {
00673                 stream >> A(r,c);
00674           }
00675         }
00676         return A;
00677   }
00678 
00679   template<class T>
00680   inline void
00681   geev (const Matrix2x2<T> & A, Matrix<T> & eigenvalues)
00682   {
00683         // a = 1  :)
00684         T b = A.data[0][0] + A.data[1][1];  // trace
00685         T c = A.data[0][0] * A.data[1][1] - A.data[0][1] * A.data[1][0];  // determinant
00686         T b4c = b * b - 4 * c;
00687         if (b4c < 0)
00688         {
00689           throw "eigen: no real eigenvalues!";
00690         }
00691         if (b4c > 0)
00692         {
00693           b4c = sqrt (b4c);
00694         }
00695         eigenvalues.resize (2, 1);
00696         eigenvalues (0, 0) = (b - b4c) / 2.0;
00697         eigenvalues (1, 0) = (b + b4c) / 2.0;
00698   }
00699 
00700   inline void
00701   geev (const Matrix2x2<double> & A, Matrix<std::complex<double> > & eigenvalues)
00702   {
00703         eigenvalues.resize (2, 1);
00704 
00705         // a = 1  :)
00706         double b = -(A.data[0][0] + A.data[1][1]);  // trace
00707         double c = A.data[0][0] * A.data[1][1] - A.data[0][1] * A.data[1][0];  // determinant
00708         double b4c = b * b - 4 * c;
00709         bool imaginary = b4c < 0;
00710         if (b4c != 0)
00711         {
00712           b4c = sqrt (fabs (b4c));
00713         }
00714         if (imaginary)
00715         {
00716           b /= -2.0;
00717           b4c /= 2.0;
00718           eigenvalues(0,0) = std::complex<double> (b, b4c);
00719           eigenvalues(1,0) = std::complex<double> (b, -b4c);
00720         }
00721         else
00722         {
00723           eigenvalues(0,0) = (-b - b4c) / 2.0;
00724           eigenvalues(1,0) = (-b + b4c) / 2.0;
00725         }
00726   }
00727 }
00728 
00729 
00730 #endif

Generated on Thu Dec 9 17:13:24 2004 for fl by doxygen1.2.18