Biomechanical Joint Model
 Author: Anderson Maciel

mat.h

Go to the documentation of this file.
00001 #ifndef AMAURY_MAT_H
00002 #define AMAURY_MAT_H
00003 
00004 #include "vec.h"
00005 #include <iostream> //iostream.h
00006 #include <sstream>
00007 
00008 namespace LinAlg{
00009 
00010 //  using namespace std;
00011  
00012 class Matrix_ 
00013 {
00014 public:
00015    typedef         double   value_type;
00016    typedef         double*  pointer;
00017    typedef         double*  iterator;
00018    typedef         double&  reference;
00019    typedef const   double*  const_iterator;
00020    typedef const   double&  const_reference;
00021 
00022    // constructors
00023    Matrix_();
00024    Matrix_(const Matrix_ &A);
00025    Matrix_(unsigned M, unsigned N, const double& value = double(0));
00026    Matrix_(unsigned M, unsigned N, const double* v);
00027    Matrix_(const Vector &V);
00028    Matrix_(unsigned M, unsigned N, const char *s);
00029 
00030    // destructor
00031    ~Matrix_();
00032 
00033    // methods
00034    Matrix_& newsize(unsigned M, unsigned N);
00035    void addToDiagonal(const Vector &V);
00036    void addToDiagonal(const double& value);
00037    void setBlock(const int m, const unsigned nrow, 
00038                  const int n, const unsigned ncol, 
00039                  const double& value = double(0));
00040    void dim(unsigned &M, unsigned &N) const { M=m_;N=n_;};
00041    unsigned row() const { return m_; };
00042    unsigned col() const { return n_; };
00043 
00044    void safeOutOfBounds(const bool on=true) { safe=on; };
00045    void setNeutral(const double& value) { neutral=value; };
00046    
00047    double det();
00048 
00049    // assignments
00050    Matrix_& operator=(const Matrix_ &A);
00051    Matrix_& operator=(const double& scalar);
00052    Matrix_& operator+=(const Matrix_ &A);
00053    Matrix_& operator-=(const Matrix_ &A);
00054    Matrix_& operator*=(const double& scalar);
00055 
00056     
00057    // access
00058    iterator begin() { return t_;}
00059    iterator end()   { return t_ + m_*n_; }
00060    const_iterator begin() const { return t_;}
00061    const_iterator end() const { return t_ + m_*n_; }
00062    // normal 2-index access
00063    reference operator()(int i, int j);
00064    const_reference operator()(int i, int j) const;
00065    // array-type index access
00066    reference operator[](int k);
00067    const_reference operator[](int k) const;
00068 
00069    virtual Vector operator*(const Vector &V) const;
00070 
00071    // basic I/O
00072    friend std::ostream& operator<<(std::ostream &s, const Matrix_ &A);
00073 
00074    // binary operators
00075    friend Matrix_ operator+ (const Matrix_ &A, const Matrix_ &B);
00076    friend Matrix_ operator- (const Matrix_ &A, const Matrix_ &B);
00077    friend Matrix_ operator- (const Matrix_ &A);
00078 
00079    friend Matrix_ operator* (const Matrix_ &A, const Matrix_ &B);
00080    friend Matrix_ operator* (const Matrix_ &A, double s);
00081    friend Matrix_ operator* (double s, const Matrix_ &A);
00082    friend bool operator == (const Matrix_ &A, const Matrix_ &B);
00083    friend bool operator != (const Matrix_ &A, const Matrix_ &B);
00084 
00085    // friend functions
00086    friend Matrix_ transpose(const Matrix_ &A);    
00087    friend Matrix_ inverse(const Matrix_ &A);    
00088 
00089 protected:
00090    double **v_;
00091    double *t_;
00092    unsigned m_, n_;  // m rows, n cols
00093    bool safe;
00094    double neutral;        // neutral element
00095    void initialize(unsigned M, unsigned N);
00096 #ifdef BOUNDS_CHECK
00097    void check_bounds(unsigned i, unsigned j) { assert (i>=0 && j>=0 && i<m_ && j<n_); };
00098 #endif
00099    void copy(const double** v);
00100    void copy(const double*  t);
00101    void set(const double& val);
00102    void destroy();     
00103 };
00104 
00105  // typedefs
00106   typedef Matrix_ MAT;
00107 
00108   // binary operators
00109   Matrix_ operator+ (const Matrix_ &A, const Matrix_ &B);
00110   Matrix_ operator- (const Matrix_ &A, const Matrix_ &B);
00111   Matrix_ operator- (const Matrix_ &A);
00112   
00113   Matrix_ operator* (const Matrix_ &A, const Matrix_ &B);
00114   Matrix_ operator* (const Matrix_ &A, double s);
00115   Matrix_ operator* (double s, const Matrix_ &A);
00116   bool operator == (const Matrix_ &A, const Matrix_ &B);
00117   bool operator != (const Matrix_ &A, const Matrix_ &B);
00118   
00119   // friend functions
00120   Matrix_ transpose(const Matrix_ &A);    
00121   Matrix_ inverse(const Matrix_ &A);  
00122   std::ostream& operator<<(std::ostream &s, const Matrix_ &A);  
00123 
00124 inline  void Matrix_::copy(const double**  v)
00125 {
00126    for (int i=0; i<m_; i++)
00127       for (int j=0; j<n_; j++)
00128          v_[i][j] = v[i][j];
00129 }
00130 
00131 
00132 inline void Matrix_::copy(const double*  t)
00133 {
00134    memcpy(t_, t, m_*n_*sizeof(double));
00135 }
00136 
00137 
00138 inline void Matrix_::set(const double& val)
00139 {
00140    for (int i=0; i<m_; i++)
00141       for (int j=0; j<n_; j++)
00142          v_[i][j] = val;
00143 }
00144 
00145 
00146 inline void Matrix_::destroy()
00147 {     
00148    delete [] t_;
00149    delete [] v_;
00150    v_ = NULL;
00151    t_ = NULL;
00152    n_ = m_ = 0;
00153 }
00154 
00155 inline  void Matrix_::initialize(unsigned M, unsigned N)
00156 {
00157    t_ = new double[M*N];
00158    v_ = new double*[M];
00159    for (int i=0;i<M;i++) v_[i] = &t_[i*N];
00160    m_ = M;
00161    n_ = N;
00162 }
00163 
00164 
00165 // restricted for the moment to 3x3 matrices
00166 
00167 /**************[ implementation of class Matrix_ ]********************/
00168 
00169 // constructors
00170 inline  Matrix_::Matrix_() : t_(0), v_(0), n_(0), m_(0), safe(false), neutral(double(0))
00171 {}
00172 
00173 
00174 inline  Matrix_::Matrix_(const Matrix_ &A) : t_(0), v_(0), n_(0), m_(0), 
00175                                                    safe(A.safe), neutral(A.neutral)
00176 {
00177    initialize(A.m_, A.n_);
00178    copy(A.t_);
00179 }
00180 
00181 
00182 inline  Matrix_::Matrix_(unsigned M, unsigned N, const double& value) :  t_(0), v_(0), n_(0), m_(0), 
00183                                                                        safe(false), neutral(double(0))
00184 {
00185    initialize(M, N);
00186    set(value);
00187 }
00188 
00189 
00190 inline  Matrix_::Matrix_(unsigned M, unsigned N, const double* v) : t_(0), v_(0), n_(0), m_(0), 
00191                                                                   safe(false), neutral(double(0))
00192 {
00193    initialize(M, N);
00194    copy(v);
00195 }
00196 
00197 
00198 
00199 inline Matrix_::Matrix_(const Vector &V) : t_(0), v_(0), n_(0), m_(0), 
00200                                                  safe(false), neutral(double(0))
00201 {
00202    initialize(V.dim(), V.dim());
00203    for (int i=0; i<V.dim(); i++) 
00204       v_[i][i] = V[i];
00205 }
00206 
00207 
00208 inline Matrix_::Matrix_(unsigned M, unsigned N, const char *s)
00209 {
00210    initialize(M, N);
00211    std::istringstream ins(s);
00212 
00213    for (int i=0; i<M; i++) 
00214       for (int j=0; j<N; j++) 
00215          ins >> v_[i][j];
00216 
00217 }
00218 
00219 
00220 inline  Matrix_::~Matrix_()
00221 { destroy(); }
00222 
00223 // methods
00224 
00225 
00226 inline Matrix_::reference Matrix_::operator()(int i, int j)
00227 {   
00228    if ( safe && (i<0 || j<0 || i>=m_ || j>=n_) )
00229    {
00230      printf("Accesing matrix ellement out of matrix dimensions");
00231      exit (-1);
00232    }
00233 #ifdef BOUNDS_CHECK
00234    check_bounds(i,j);
00235 #endif
00236    return v_[i][j]; 
00237 }
00238 
00239 
00240 inline Matrix_::const_reference Matrix_::operator()(int i, int j) const
00241 {
00242 #ifdef BOUNDS_CHECK
00243    check_bounds(i,j);
00244 #endif
00245    return v_[i][j]; 
00246 }
00247 
00248 
00249 
00250 inline  Matrix_& Matrix_::newsize(unsigned M, unsigned N)
00251 {
00252    if (m_ == M && n_ == N) return *this;
00253 
00254    destroy();
00255    initialize(M,N);
00256 
00257    return *this;
00258 }
00259 
00260 
00261 inline void Matrix_::addToDiagonal(const Vector &V)
00262 {
00263    assert (m_==n_ && n_==V.dim());
00264 
00265    for (int i=0; i<m_; i++)
00266       v_[i][i] += V[i];
00267 }
00268 
00269 
00270 inline void Matrix_::addToDiagonal(const double& value)
00271 {
00272    for (int i=0; i<m_; i++)
00273       v_[i][i] += value;
00274 }
00275 
00276 
00277 inline void Matrix_::setBlock(const int m, const unsigned nrow, 
00278                                 const int n, const unsigned ncol, const double& value)
00279 {
00280    for (int i=0; i<nrow; i++)
00281       for (int j=0; j<ncol; j++)
00282          this->operator()(m+i, n+j) = value;
00283 }
00284 
00285 
00286 // assignments
00287 //
00288 
00289 inline  Matrix_& Matrix_::operator=(const Matrix_ &A)
00290 {
00291    if (v_ == A.v_)
00292       return *this;
00293 
00294    if (m_ == A.m_ && n_ == A.n_)         // no need to re-alloc
00295       copy(A.t_);
00296    else
00297    {
00298       destroy();
00299       initialize(A.m_, A.n_);
00300       copy(A.t_);
00301    }
00302 
00303    return *this;
00304 }
00305         
00306 
00307 inline  Matrix_& Matrix_::operator=(const double& scalar)
00308 { 
00309    set(scalar);  
00310    return *this;
00311 }
00312 
00313 
00314 inline  Matrix_& Matrix_::operator+=(const Matrix_ &A)
00315 {
00316    assert(n_==A.n_ && m_==A.m_);
00317 
00318    for (int i=0; i<m_; i++)
00319       for (int j=0; j<n_; j++)
00320          v_[i][j] += A.v_[i][j];
00321    return *this;
00322 }
00323 
00324 
00325 inline  Matrix_& Matrix_::operator-=(const Matrix_ &A)
00326 {
00327    assert(n_==A.n_ && m_==A.m_);
00328 
00329    for (int i=0; i<m_; i++)
00330       for (int j=0; j<n_; j++)
00331          v_[i][j] -= A.v_[i][j];
00332    return *this;
00333 }
00334 
00335 
00336 inline  Matrix_& Matrix_::operator*=(const double& scalar)
00337 {
00338    for (int i=0; i<m_; i++)
00339       for (int j=0; j<n_; j++)
00340          v_[i][j] *= scalar; 
00341    return *this;
00342 }
00343 
00344 inline Matrix_::reference Matrix_::operator[](int k)
00345 {   
00346    if ( safe && (k<0 || k>=m_*n_))
00347    {
00348      printf("Accesing matrix ellement out of matrix dimensions");
00349      exit (-1);
00350    }
00351 
00352    int i = k / n_;
00353    int j = k % n_;
00354 #ifdef BOUNDS_CHECK
00355    check_bounds(i,j);
00356 #endif
00357    return v_[i][j]; 
00358 }
00359 
00360 
00361 inline Matrix_::const_reference Matrix_::operator[](int k) const
00362 {
00363    int i = k / n_;
00364    int j = k % n_;
00365 #ifdef BOUNDS_CHECK
00366    check_bounds(i,j);
00367 #endif
00368    return v_[i][j]; 
00369 }
00370 
00371 
00372 
00373 inline  double Matrix_::det()
00374 {
00375    assert(row()==3 && col()==3);
00376 
00377    return (
00378       v_[0][0]*v_[1][1]*v_[2][2]
00379       -v_[0][0]*v_[1][2]*v_[2][1]
00380       -v_[1][0]*v_[0][1]*v_[2][2]
00381       +v_[1][0]*v_[0][2]*v_[2][1]
00382       +v_[2][0]*v_[0][1]*v_[1][2]
00383       -v_[2][0]*v_[0][2]*v_[1][1] );   
00384 }
00385 
00386 // private members
00387 
00388 
00389 inline Matrix_ inverse(const Matrix_ &A)
00390 {
00391    unsigned M=A.row(), N=A.col();
00392    assert(M==3 && N==3);
00393    
00394    double det = 
00395       A.v_[0][0]*A.v_[1][1]*A.v_[2][2]
00396       -A.v_[0][0]*A.v_[1][2]*A.v_[2][1]
00397       -A.v_[1][0]*A.v_[0][1]*A.v_[2][2]
00398       +A.v_[1][0]*A.v_[0][2]*A.v_[2][1]
00399       +A.v_[2][0]*A.v_[0][1]*A.v_[1][2]
00400       -A.v_[2][0]*A.v_[0][2]*A.v_[1][1];
00401    
00402    assert(fabs(det) > 1E-7);  
00403  
00404    static Matrix_ tmp(3,3);
00405 
00406    tmp.v_[0][0] = A.v_[1][1]*A.v_[2][2] - A.v_[2][1]*A.v_[1][2];
00407    tmp.v_[0][1] = -A.v_[0][1]*A.v_[2][2] + A.v_[2][1]*A.v_[0][2];
00408    tmp.v_[0][2] = A.v_[0][1]*A.v_[1][2] - A.v_[1][1]*A.v_[0][2];
00409 
00410    tmp.v_[1][0] = -A.v_[1][0]*A.v_[2][2] + A.v_[2][0]*A.v_[1][2];
00411    tmp.v_[1][1] = A.v_[0][0]*A.v_[2][2] - A.v_[2][0]*A.v_[0][2];
00412    tmp.v_[1][2] = -A.v_[0][0]*A.v_[1][2] + A.v_[1][0]*A.v_[0][2];
00413    
00414    tmp.v_[2][0] = A.v_[1][0]*A.v_[2][1] - A.v_[2][0]*A.v_[1][1];
00415    tmp.v_[2][1] = -A.v_[0][0]*A.v_[2][1] + A.v_[2][0]*A.v_[0][1];
00416    tmp.v_[2][2] = A.v_[0][0]*A.v_[1][1] - A.v_[1][0]*A.v_[0][1];
00417    
00418    return (tmp*(1/det));
00419 }
00420 
00421 inline Matrix_ operator+(const Matrix_ &A, 
00422                            const Matrix_ &B)
00423 {
00424    unsigned M=A.row(), N=A.col();
00425    assert(M==B.row() && N==B.col());
00426 
00427    Matrix_ tmp(M, N);
00428 
00429    for (int i=0; i<M; i++)
00430       for (int j=0; j<N; j++)
00431          tmp.v_[i][j] = A.v_[i][j] + B.v_[i][j];
00432   
00433    return tmp;
00434 }
00435 
00436 
00437 inline Matrix_ operator-(const Matrix_ &A, 
00438                            const Matrix_ &B)
00439 {
00440    unsigned M=A.row(), N=A.col();
00441 
00442    assert(M==B.row() && N==B.col());
00443   
00444    Matrix_ tmp(M, N);
00445 
00446    for (int i=0; i<M; i++)
00447       for (int j=0; j<N; j++)
00448          tmp.v_[i][j] = A.v_[i][j] - B.v_[i][j];  
00449 
00450    return tmp;
00451 }
00452 
00453 
00454 
00455 inline Matrix_ operator-(const Matrix_ &A)
00456 {
00457    unsigned M=A.row(), N=A.col();
00458 
00459    Matrix_ tmp(M,N);
00460 
00461    for (int i=0; i<M; i++)
00462       for (int j=0; j<N; j++)
00463          tmp.v_[i][j] = -A.v_[i][j];
00464 
00465    return tmp;
00466 }
00467 
00468 
00469 inline Matrix_ operator*(const Matrix_ &A, 
00470                            const Matrix_ &B)
00471 {
00472    assert(A.col() == B.row());
00473    unsigned M = A.row();
00474    unsigned N = A.col();
00475    unsigned K = B.col();
00476 
00477    Matrix_ tmp(M,K);
00478    unsigned i,j,k;
00479    double sum; 
00480 
00481    for (i=0; i<M; i++)
00482    {
00483       for (k=0; k<K; k++)
00484       {
00485          for (sum=0, j=0; j<N; j++)
00486          {
00487             sum += A.v_[i][j]*B.v_[j][k];
00488          }        
00489          tmp.v_[i][k] = sum; 
00490       }
00491    }
00492    
00493    return tmp;
00494 }
00495 
00496 
00497 inline Matrix_ operator*(const Matrix_ &A, double s)
00498 {
00499    Matrix_ tmp(A);
00500    tmp *= s;
00501    return tmp;
00502 }
00503 
00504 
00505 inline Matrix_ operator*(double s, const Matrix_ &A)
00506 {
00507    return A*s;
00508 }
00509 
00510 
00511 
00512 inline  bool operator ==(const Matrix_ &A, const Matrix_ &B)
00513 {
00514    unsigned M=A.row(), N=A.col();
00515    if (M==B.row() && N == B.col())
00516    {
00517       for (int i=0; i<M; i++)
00518          for (int j=0; j<N; j++)
00519             if (A.v_[i][j] != B.v_[i][j]) return false;
00520       return true;
00521    }
00522    return false;
00523 }
00524 
00525 
00526 inline  bool operator !=(const Matrix_ &A, const Matrix_ &B)      
00527 {
00528    return !(A==B);
00529 }
00530 
00531 
00532 inline Matrix_ transpose(const Matrix_ &A)
00533 {
00534    unsigned M=A.row(), N=A.col();
00535    Matrix_ tmp(N,M);
00536 
00537    for (int i=0; i<M; i++)
00538       for (int j=0; j<N; j++)
00539          tmp.v_[j][i] = A.v_[i][j];
00540 
00541    return tmp;
00542 }
00543 
00544 /****************************  I/O  ********************************/
00545 
00546 inline std::ostream& operator<<(std::ostream &s, const Matrix_ &A)
00547 {
00548    unsigned M=A.row(), N=A.col();
00549 
00550    s << M << "x" << N << std::endl;
00551 
00552    for (unsigned i=0; i<M; i++)
00553    {
00554       for (unsigned j=0; j<N; j++)
00555          s  << A.v_[i][j] << " ";
00556       s << std::endl;
00557    }
00558    s << std::endl;
00559 
00560    return s;
00561 }
00562 
00563 }
00564 #endif

Generated on Thu Dec 1 10:13:38 2005 for COME - Biomechanical Joint Model by  doxygen 1.4.5