namespace ewalena  0.2.15
ewalena is not an acronym
include/ewalena/lac/matrix.h
Go to the documentation of this file.
00001 // -------------------------------------------------------------------
00002 // @author Toby D. Young
00003 // @version $Id: matrix.h 1002 2012-12-04 15:01:40Z 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 #include <cassert>
00039 #include <cstring>
00040 #include <stdlib.h>
00041 #include <iostream>
00042 
00043 #ifndef __ewalena_matrix_h
00044 #define __ewalena_matrix_h
00045 
00046 #ifdef EWALENA_HAVE_CONFIG_H
00047 #include <ewalena/base/config.h>
00048 #endif
00049 
00050 #include <ewalena/base/tensor.h>
00051 #include <ewalena/lac/vector_basis.h>
00052 
00053 namespace ewalena
00054 {
00055   
00056   template <int, int, typename> class Tensor;
00057   template <typename> class VectorBasis;
00058 
00069   template <typename ValueType = double>
00070     class Matrix
00071     {
00072       
00073       
00074     public:
00075     
00079     Matrix ();
00080     
00084     ~Matrix ();
00085     
00092     explicit Matrix (const unsigned int m, 
00093                      const unsigned int n,
00094                      const bool         zero = true);
00095     
00100     Matrix (std::pair<const unsigned int, const unsigned int> mn_pair,
00101             const bool                                        zero = true);
00102     
00110     template <int dim>
00111     Matrix (const class Tensor<dim, 2, ValueType> &T);  
00112     
00117     Matrix (const class VectorBasis<ValueType> &V);  
00118     
00123     Matrix (const Matrix& M);
00124     
00128     unsigned int n_rows () const;
00129     
00133     unsigned int n_cols () const;
00134     
00138     unsigned int size () const;
00139     
00144     void reinit (const unsigned int m,
00145                  const unsigned int n,
00146                  const bool         zero = true);
00147     
00151     void reinit ();
00152     
00157     ValueType& operator () (const unsigned int i, 
00158                             const unsigned int j);
00159     
00164     const ValueType& operator () (const unsigned int i, 
00165                                   const unsigned int j) const;
00166     
00170     void invert (const Matrix<ValueType> &M);
00171     
00176     void mult (const Matrix<ValueType> &M_a, 
00177                const Matrix<ValueType> &M_b);
00178     
00183     void Tmult (const Matrix<ValueType> &M_a, 
00184                 const Matrix<ValueType> &M_b);
00185     
00190     void multT (const Matrix<ValueType> &M_a, 
00191                 const Matrix<ValueType> &M_b);
00192     
00197     void identity ();
00198     
00202     ValueType norm ();
00203     
00208     void operator += (const Matrix<ValueType> &M);
00209     
00214     void operator -= (const Matrix<ValueType> &M);
00215     
00220     void operator *= (const ValueType &scalar);
00221     
00226     void operator /= (const ValueType &scalar);
00227     
00231     void operator = (const Matrix<ValueType> &M);
00232     
00237     bool operator == (const Matrix<ValueType> &M) const;
00238     
00243     bool is_symmetric () const;
00244     
00248     friend std::ostream& operator << (std::ostream            &output, 
00249                                       const Matrix<ValueType> &M)
00250     {
00251       for (unsigned int i=0; i<M.n_rows ()*M.n_cols (); ++i) 
00252 
00253         /* Try to pretty print */
00254         (M.data[i]<(ValueType) 0.)
00255           ?
00256           output << M.data[i] << " "
00257           :
00258           output << " " 
00259                  << M.data[i] << " ";
00260       
00261       return output; 
00262     }
00263     
00264     protected:
00265     
00270     inline
00271     const 
00272     ValueType* operator* () const
00273     {
00274       return (*this).data;
00275     }
00276     
00281     inline
00282     ValueType* operator* () 
00283     {
00284       return (*this).data;
00285     }
00286     
00287     private:
00288     
00294     unsigned int __n_rows;
00295     
00301     unsigned int __n_cols;
00302     
00307     ValueType* data;
00308     
00309     }; /* Matrix */
00310   
00311   /*-------------- Inline and Other Functions -----------------------*/
00312   
00313   template <typename ValueType>
00314     inline 
00315     const ValueType& 
00316     Matrix<ValueType>::operator () (const unsigned int i, 
00317                                     const unsigned int j) const
00318     {
00319       assert (i<__n_rows);
00320       assert (j<__n_cols);
00321       
00322       /* return data[  index[0].begin () + i*index[0].increment () */
00323       /*                    + */
00324       /*                    n_rows*(index[1].begin () + j*index[1].increment ()) ]; */
00325       
00326       return data[__n_cols*i+j];
00327     }
00328   
00329   template <typename ValueType>
00330     inline 
00331     ValueType& 
00332     Matrix<ValueType>::operator () (const unsigned int i, 
00333                                     const unsigned int j) 
00334     {
00335       assert (i<__n_rows);
00336       assert (j<__n_cols);
00337       
00338       return data[__n_cols*i+j];
00339     }
00340 
00341   template <typename ValueType>
00342     inline
00343     unsigned int
00344     Matrix<ValueType>::n_rows () const
00345     {
00346       return this->__n_rows;
00347     }
00348   
00349   template <typename ValueType>
00350     inline
00351     unsigned int
00352     Matrix<ValueType>::n_cols () const
00353     {
00354       return this->__n_cols;
00355     }
00356 
00357   template <typename ValueType>
00358     inline
00359     unsigned int
00360     Matrix<ValueType>::size () const
00361     {
00362       return (this->__n_rows)*(this->__n_cols);
00363     }
00364 
00365   template <typename ValueType>
00366     inline 
00367     void
00368     Matrix<ValueType>::operator += (const Matrix<ValueType> &M) 
00369     {
00370       assert (M.__n_rows == this->__n_rows);
00371       assert (M.__n_cols == this->__n_cols);
00372       
00373       for (unsigned int i=0; i<__n_rows*__n_cols; ++i)
00374         data[i] += M.data[i];
00375     }
00376 
00377   template <typename ValueType>
00378     inline 
00379     void
00380     Matrix<ValueType>::operator -= (const Matrix<ValueType> &M) 
00381     {
00382       assert (M.__n_rows == this->__n_rows);
00383       assert (M.__n_cols == this->__n_cols);
00384 
00385       for (unsigned int i=0; i<__n_rows*__n_cols; ++i)
00386         data[i]  -= M.data[i];
00387     }
00388 
00389   template <typename ValueType>
00390     inline 
00391     void
00392     Matrix<ValueType>::operator *= (const ValueType &scalar) 
00393     {
00394       for (unsigned int i=0; i<__n_rows*__n_cols; ++i)
00395         data[i] *= scalar;
00396     }
00397 
00398   template <typename ValueType>
00399     inline 
00400     void
00401     Matrix<ValueType>::operator /= (const ValueType &scalar) 
00402     {
00403       for (unsigned int i=0; i<__n_rows*__n_cols; ++i)
00404         data[i] /= scalar;
00405     }
00406 
00407   template <typename ValueType>
00408     void
00409     Matrix<ValueType>::operator = (const Matrix<ValueType> &M) 
00410     {
00411       assert (M.data);
00412 
00413       assert (M.__n_rows == this->__n_rows);
00414       assert (M.__n_cols == this->__n_cols);
00415 
00416       for (unsigned int i=0; i<__n_rows; ++i) 
00417         for (unsigned int j=0; j<__n_cols; ++j) 
00418           (*this)(i,j) = M(i,j);
00419     }
00420 
00421   template <typename ValueType>
00422     inline 
00423     bool
00424     Matrix<ValueType>::operator == (const Matrix<ValueType> &M) const
00425     {
00426       assert (M.__n_rows == this->__n_rows);
00427       assert (M.__n_cols == this->__n_cols);
00428 
00429       return static_cast<bool> (!std::memcmp (this->data, M.data, sizeof(ValueType)*(__n_rows*__n_cols)));
00430     }
00431 
00432   template <typename ValueType>
00433     inline 
00434     bool
00435     Matrix<ValueType>::is_symmetric () const
00436     {
00437       assert (this->data);
00438       assert (__n_rows == __n_cols);
00439       
00440       /* The matrix is trivially symmetric if it has zero size. */
00441       if (data)
00442         for (unsigned int i=0; i<__n_rows; ++i) 
00443           for (unsigned int j=i+1; j<__n_cols; ++j) 
00444             if ((*this)(i,j) != (*this)(j,i)) 
00445               return false; 
00446       
00447       return true;
00448     }
00449   
00450   template <typename ValueType>
00451     inline 
00452     void
00453     Matrix<ValueType>::identity ()
00454     {
00455       /* An identity matrix is always a square matrix. */
00456       assert (this->__n_rows == this->__n_cols);
00457       this->reinit ();
00458       
00459       /* If the matrix is zero size - there is nothing to do. */
00460       if (__n_rows==0) 
00461         return;
00462       
00463       /* This is a cyclic counter that runs one past the length of a
00464          column; ie. where 1 appears cyclicly in an identity
00465          matrix. */
00466       unsigned int j = __n_rows+1;
00467       
00468       for (unsigned int i=0; i<(__n_rows*__n_cols); ++i, ++j)
00469         {
00470           if (j==__n_rows+1) 
00471             {
00472               this->data[i] = ValueType(1);
00473               j=0;
00474             }
00475         }
00476     }
00477   
00478   template <typename ValueType>
00479     inline 
00480     ValueType
00481     Matrix<ValueType>::norm ()
00482     {
00483       assert (this->data);
00484       
00485       ValueType scalar = ValueType(0);
00486       
00487       for (unsigned int i=0; i<(this->__n_rows)*(this->__n_cols); ++i)
00488         scalar += std::fabs (this->data[i]);
00489       
00490       return scalar;
00491     }
00492   
00493   template <typename ValueType> 
00494     inline  
00495     void
00496     Matrix<ValueType>::mult (const Matrix<ValueType> &M_a, 
00497                              const Matrix<ValueType> &M_b)  
00498     { 
00499       assert (M_a.data);
00500       assert (M_b.data);
00501 
00502       assert (M_a.__n_rows == M_b.__n_cols);  
00503       assert (M_a.__n_cols == M_b.__n_rows);  
00504       
00505       for (unsigned int i=0; i<M_a.__n_rows; ++i)
00506         for (unsigned int j=0; j<M_b.__n_cols; ++j)
00507           for (unsigned int k=0; k<M_b.__n_rows; ++k)
00508             (*this)(i,j) += M_a(i,k)*M_b(k,j);
00509     }
00510 
00511   template <typename ValueType> 
00512     inline  
00513     void
00514     Matrix<ValueType>::Tmult (const Matrix<ValueType> &M_a, 
00515                               const Matrix<ValueType> &M_b)  
00516     { 
00517       assert (M_a.data);
00518       assert (M_b.data);
00519 
00520       assert (M_a.__n_rows == M_b.__n_rows);  
00521       assert (M_a.__n_cols == M_b.__n_cols);  
00522       
00523       for (unsigned int i=0; i<M_a.__n_rows; ++i)
00524         for (unsigned int j=0; j<M_b.__n_cols; ++j)
00525           for (unsigned int k=0; k<M_b.__n_rows; ++k)
00526             (*this)(i,j) += M_a(k,i)*M_b(k,j);
00527     }
00528 
00529   template <typename ValueType> 
00530     inline  
00531     void
00532     Matrix<ValueType>::multT (const Matrix<ValueType> &M_a, 
00533                               const Matrix<ValueType> &M_b)  
00534     { 
00535       assert (M_a.data);
00536       assert (M_b.data);
00537 
00538       assert (M_a.__n_rows == M_b.__n_rows);  
00539       assert (M_a.__n_cols == M_b.__n_cols);  
00540       
00541       for (unsigned int i=0; i<M_a.__n_rows; ++i)
00542         for (unsigned int j=0; j<M_b.__n_cols; ++j)
00543           for (unsigned int k=0; k<M_b.__n_rows; ++k)
00544             (*this)(i,j) += M_a(i,k)*M_b(j,k);
00545     }
00546 
00547   /*-------------- Template and Other Functions ---------------------*/
00548 
00549   template <typename ValueType>
00550     template <int dim>
00551     Matrix<ValueType>::Matrix (const Tensor<dim, 2, ValueType> &T)
00552     {
00553 
00554       /* @todo: Generalise this for rank \neq 2. */
00555       __n_rows = dim;
00556       __n_cols = dim;
00557       data     = new ValueType[__n_rows*__n_cols];
00558       
00559       if ((__n_rows != 0) && (__n_cols !=0))
00560         std::memcpy (this->data, *T, sizeof(ValueType)*(__n_rows*__n_cols));
00561     }
00562 
00563   template <typename ValueType>
00564     Matrix<ValueType>::Matrix (const VectorBasis<ValueType> &V)
00565     {
00566       __n_rows = V.n_rows ();
00567       __n_cols = V.size ();
00568       data     = new ValueType[__n_rows*__n_cols];
00569 
00570       if ((__n_rows != 0) && (__n_cols !=0))
00571         std::memcpy (this->data, *V, sizeof(ValueType)*(__n_rows*__n_cols));
00572     }
00573 
00574   template <typename ValueType>
00575     inline 
00576     void
00577     Matrix<ValueType>::invert (const Matrix<ValueType> &M)
00578     {
00579       assert (M.data);
00580       assert (M.__n_rows==M.__n_cols);
00581 
00582       this->reinit (M.__n_rows,M.__n_cols);
00583 
00584       switch (M.__n_cols)
00585         {
00586         case 0:
00587           {
00588             /* Undefined operation.  */
00589             assert (false);
00590           }
00591 
00592         case 1:
00593           {
00594             assert (M(0,0)!=ValueType (0));
00595             (*this)(0,0) = ValueType (1) / M(0,0);
00596             break;
00597           }
00598           
00599         case 2:
00600           {
00601             const ValueType determinant = M(0,0)*M(1,1) - M(0,1)*M(1,0);
00602             assert (determinant!=ValueType (0));
00603             
00604             (*this)(0,0) =  M(1,1) / determinant;
00605             (*this)(0,1) = -M(0,1) / determinant;
00606             (*this)(1,0) = -M(1,0) / determinant;
00607             (*this)(1,1) =  M(0,0) / determinant;
00608             
00609             break;
00610           }
00611 
00612         case 3: 
00613           {
00614             const ValueType determinant 
00615               = M(0,0)*(M(2,2)*M(1,1) - M(2,1)*M(1,2))
00616               - M(1,0)*(M(2,2)*M(0,1) - M(2,1)*M(0,2))
00617               + M(2,0)*(M(1,2)*M(0,1) - M(1,1)*M(0,2));
00618             assert (determinant!=ValueType (0));
00619 
00620             (*this)(0,0) =    (M(2,2)*M(1,1) - M(2,1)*M(1,2)) / determinant;
00621             (*this)(0,1) =  - (M(2,2)*M(0,1) - M(2,1)*M(0,2)) / determinant;
00622             (*this)(0,2) =    (M(1,2)*M(0,1) - M(1,1)*M(0,2)) / determinant;
00623 
00624             (*this)(1,0) =  - (M(2,2)*M(1,0) - M(2,0)*M(1,2)) / determinant;
00625             (*this)(1,1) =    (M(2,2)*M(0,0) - M(2,0)*M(0,2)) / determinant;
00626             (*this)(1,2) =  - (M(1,2)*M(0,0) - M(1,0)*M(0,2)) / determinant;
00627 
00628             (*this)(2,0) =    (M(2,1)*M(1,0) - M(2,0)*M(1,1)) / determinant;
00629             (*this)(2,1) =  - (M(2,1)*M(0,0) - M(2,0)*M(0,1)) / determinant;
00630             (*this)(2,2) =    (M(1,1)*M(0,0) - M(1,0)*M(0,1)) / determinant;
00631 
00632             break; 
00633 
00634           }
00635 
00636           /* This is not likely to work well for big or even medium
00637              sized matrices - so don't do it.  */
00638         default:
00639           assert (false);
00640         }
00641       
00642     }
00643   
00644 } /* namespace ewalena */
00645 
00646 #endif /* __ewalena_matrix_h */
00647   
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines