h o m e d o c u m e n t a t i o n c l a s s h i e r a r c h y

VecMat.h

00001 //
00002 //  Filename         : VecMat.h
00003 //  Author(s)        : Sylvain Paris
00004 //                     Emmanuel Turquin
00005 //                     Stephane Grabli 
00006 //  Purpose          : Vectors and Matrices definition and manipulation
00007 //  Date of creation : 12/06/2003
00008 //
00010 
00011 
00012 //
00013 //  Copyright (C) : Please refer to the COPYRIGHT file distributed 
00014 //   with this source distribution. 
00015 //
00016 //  This program is free software; you can redistribute it and/or
00017 //  modify it under the terms of the GNU General Public License
00018 //  as published by the Free Software Foundation; either version 2
00019 //  of the License, or (at your option) any later version.
00020 //
00021 //  This program is distributed in the hope that it will be useful,
00022 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00023 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024 //  GNU General Public License for more details.
00025 //
00026 //  You should have received a copy of the GNU General Public License
00027 //  along with this program; if not, write to the Free Software
00028 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00029 //
00031 
00032 #ifndef  VECMAT_H
00033 # define VECMAT_H
00034 
00035 # include <math.h>
00036 # include <vector>
00037 # include <iostream>
00038 
00039 namespace VecMat {
00040 
00041   namespace Internal {
00042 
00043     template <bool B>
00044     struct is_false {};
00045 
00046     template <>
00047     struct is_false<false> {
00048       static inline void ensure() {}
00049     };
00050 
00051   } // end of namespace Internal
00052 
00053   //
00054   //  Vector class
00055   //    - T: value type
00056   //    - N: dimension
00057   //
00059 
00060   template <class T, unsigned N>
00061   class Vec
00062   {
00063   public:
00064 
00065     typedef T value_type;
00066     
00067     // constructors
00068 
00069     inline Vec() {
00070       for (unsigned i = 0; i < N; i++)
00071         this->_coord[i] = 0;
00072     }
00073 
00074     ~Vec() {
00075       Internal::is_false<(N == 0)>::ensure();
00076     }
00077 
00078     template <class U>
00079     explicit inline Vec(const U tab[N]) {
00080       for (unsigned i = 0; i < N; i++)
00081         this->_coord[i] = (T)tab[i];
00082     }
00083 
00084     template <class U>
00085     explicit inline Vec(const std::vector<U>& tab) {
00086       for (unsigned i = 0; i < N; i++)
00087         this->_coord[i] = (T)tab[i];
00088     }
00089 
00090     template <class U>
00091     explicit inline Vec(const Vec<U, N>& v) {
00092       for (unsigned i = 0; i < N; i++)
00093         this->_coord[i] = (T)v[i];
00094     }
00095 
00096     // accessors
00097 
00098     inline value_type  operator[](const unsigned i) const {
00099       return this->_coord[i];
00100     }
00101 
00102     inline value_type& operator[](const unsigned i) {
00103       return this->_coord[i];
00104     }
00105 
00106     static inline unsigned dim() {
00107       return N;
00108     }
00109     
00110     // various useful methods
00111 
00112     inline value_type norm() const {
00113       return (T)sqrt((float)squareNorm());
00114     }
00115 
00116     inline value_type squareNorm() const {
00117       return (*this) * (*this);
00118     }
00119 
00120     inline Vec<T, N>& normalize() {
00121       value_type n = norm();
00122       for (unsigned i = 0; i < N; i++)
00123         this->_coord[i] /= n;
00124       return *this;
00125     }
00126 
00127     inline Vec<T, N>& normalizeSafe() {
00128       value_type n = norm();
00129       if (n)
00130         for (unsigned i=0; i < N; i++)
00131           this->_coord[i] /= n;
00132       return *this;
00133     }
00134 
00135     // classical operators
00136     inline Vec<T, N> operator+(const Vec<T, N>& v) const{
00137     Vec<T, N> res(v);
00138     res += *this;
00139     return res;
00140     } 
00141 
00142     inline Vec<T, N> operator-(const Vec<T,N>& v) const{
00143     Vec<T, N> res(*this);
00144     res -= v;
00145     return res;
00146     } 
00147 
00148     inline Vec<T, N> operator*(const typename Vec<T,N>::value_type r) const{
00149     Vec<T, N> res(*this);
00150     res *= r;
00151     return res;
00152     } 
00153 
00154     inline Vec<T, N> operator/(const typename Vec<T,N>::value_type r) const{
00155     Vec<T, N> res(*this);
00156     if (r)
00157       res /= r;
00158     return res;
00159     } 
00160 
00161     // dot product
00162     inline value_type operator*(const Vec<T, N>& v) const{
00163     value_type sum = 0;
00164     for (unsigned i = 0; i < N; i++)
00165       sum += (*this)[i] * v[i];
00166     return sum;
00167     } 
00168     
00169     template <class U>
00170     inline Vec<T, N>& operator=(const Vec<U, N>& v) {
00171       if (this != &v)
00172         for (unsigned i = 0; i < N; i++)
00173           this->_coord[i] = (T)v[i];
00174       return *this;
00175     }
00176 
00177     template <class U>
00178     inline Vec<T, N>& operator+=(const Vec<U, N>& v) {
00179       for (unsigned i = 0 ; i < N; i++)
00180         this->_coord[i] += (T)v[i];
00181       return *this;
00182     }
00183 
00184     template <class U>
00185     inline Vec<T, N>& operator-=(const Vec<U, N>& v) {
00186       for (unsigned i = 0 ; i < N; i++)
00187         this->_coord[i] -= (T)v[i];
00188       return *this;
00189     }
00190 
00191     template <class U>
00192     inline Vec<T, N>& operator*=(const U r) {
00193       for (unsigned i = 0 ; i < N; i++)
00194         this->_coord[i] *= r;
00195       return *this;
00196     }
00197 
00198     template <class U>
00199     inline Vec<T, N>& operator/=(const U r) {
00200       if (r)
00201         for (unsigned i = 0 ; i < N; i++)
00202           this->_coord[i] /= r;
00203       return *this;
00204     }
00205 
00206 
00207     inline bool operator==(const Vec<T, N>& v) const {
00208       for(unsigned i = 0; i < N; i++)
00209         if (this->_coord[i] != v[i])
00210           return false;
00211       return true;
00212     }
00213 
00214     inline bool operator!=(const Vec<T, N>& v) const {
00215       for(unsigned i = 0; i < N; i++)
00216         if (this->_coord[i] != v[i])
00217           return true;
00218       return false;
00219     }
00220 
00221     inline bool operator<(const Vec<T, N>& v) const {
00222       for (unsigned i = 0; i<N; i++) {
00223         if (this->_coord[i] < v[i])
00224           return true;
00225         if (this->_coord[i] > v[i])
00226           return false;
00227         if (this->_coord[i] == v[i])
00228           continue;
00229       }
00230       return false;  
00231     }
00232 
00233     inline bool operator>(const Vec<T, N>& v) const {
00234       for (unsigned i=0; i<N; i++) {
00235         if(this->_coord[i] > v[i])
00236           return true;
00237         if(this->_coord[i] < v[i])
00238           return false;
00239         if(this->_coord[i] == v[i])
00240           continue;
00241       }
00242       return false;  
00243     }
00244 
00245   protected:
00246 
00247     value_type _coord[N];
00248     enum {
00249       _dim = N,
00250     };
00251   };
00252 
00253 
00254   //
00255   //  Vec2 class (2D Vector)
00256   //    - T: value type
00257   //
00259 
00260   template <class T>
00261   class Vec2 : public Vec<T, 2>
00262   {
00263   public:
00264 
00265     typedef typename Vec<T, 2>::value_type value_type;
00266 
00267     inline Vec2() : Vec<T, 2>() {}
00268 
00269     template <class U>
00270     explicit inline Vec2(const U tab[2]) : Vec<T, 2>(tab) {}
00271 
00272     template <class U>
00273     explicit inline Vec2(const std::vector<U>& tab) : Vec<T, 2>(tab) {}
00274 
00275     template <class U>
00276     inline Vec2(const Vec<U, 2>& v) : Vec<T, 2>(v) {}
00277 
00278     inline Vec2(const value_type x,
00279                 const value_type y = 0) : Vec<T, 2>() {
00280       this->_coord[0] = (T)x;
00281       this->_coord[1] = (T)y;
00282     }
00283     
00284     inline value_type x() const {
00285       return this->_coord[0];
00286     }
00287 
00288     inline value_type& x() {
00289       return this->_coord[0];
00290     }
00291 
00292     inline value_type y() const {
00293       return this->_coord[1];
00294     }
00295 
00296     inline value_type& y() {
00297       return this->_coord[1];
00298     }
00299 
00300     inline void setX(const value_type v) {
00301       this->_coord[0] = v;
00302     }
00303 
00304     inline void setY(const value_type v) {
00305       this->_coord[1] = v;
00306     }
00307 
00308     // FIXME: hack swig -- no choice
00309     inline Vec2<T> operator+(const Vec2<T>& v) const{
00310     Vec2<T> res(v);
00311     res += *this;
00312     return res;
00313     } 
00314 
00315     inline Vec2<T> operator-(const Vec2<T>& v) const{
00316     Vec2<T> res(*this);
00317     res -= v;
00318     return res;
00319     } 
00320 
00321     inline Vec2<T> operator*(const value_type r) const{
00322     Vec2<T> res(*this);
00323     res *= r;
00324     return res;
00325     } 
00326 
00327     inline Vec2<T> operator/(const value_type r) const{
00328     Vec2<T> res(*this);
00329     if (r)
00330       res /= r;
00331     return res;
00332     } 
00333 
00334     // dot product
00335     inline value_type operator*(const Vec2<T>& v) const{
00336     value_type sum = 0;
00337     for (unsigned i = 0; i < 2; i++)
00338       sum += (*this)[i] * v[i];
00339     return sum;
00340     } 
00341   };
00342 
00343 
00344   //
00345   //  HVec3 class (3D Vector in homogeneous coordinates)
00346   //    - T: value type
00347   //
00349 
00350   template <class T>
00351   class HVec3 : public Vec<T, 4>
00352   {
00353   public:
00354 
00355     typedef typename Vec<T, 4>::value_type value_type;
00356 
00357     inline HVec3() : Vec<T, 4>() {}
00358 
00359     template <class U>
00360     explicit inline HVec3(const U tab[4]) : Vec<T, 4>(tab) {}
00361 
00362     template <class U>
00363     explicit inline HVec3(const std::vector<U>& tab) : Vec<T, 4>(tab) {}
00364 
00365     template<class U>
00366     inline HVec3(const Vec<U, 4>& v) : Vec<T, 4>(v) {}
00367   
00368     inline HVec3(const value_type sx,
00369                  const value_type sy = 0,
00370                  const value_type sz = 0,
00371                  const value_type s = 1) {
00372       this->_coord[0] = sx;
00373       this->_coord[1] = sy;
00374       this->_coord[2] = sz;
00375       this->_coord[3] = s;
00376     }
00377     
00378     template <class U>
00379     inline HVec3(const Vec<U, 3>& sv,
00380                  const U s = 1) {
00381       this->_coord[0] = (T)sv[0];
00382       this->_coord[1] = (T)sv[1];
00383       this->_coord[2] = (T)sv[2];
00384       this->_coord[3] = (T)s;
00385     }
00386     
00387     inline value_type sx() const {
00388       return this->_coord[0];
00389     }
00390 
00391     inline value_type& sx() {
00392       return this->_coord[0];
00393     }
00394 
00395     inline value_type sy() const {
00396       return this->_coord[1];
00397     }
00398 
00399     inline value_type& sy() {
00400       return this->_coord[1];
00401     }
00402 
00403     inline value_type sz() const {
00404       return this->_coord[2];
00405     }
00406 
00407     inline value_type& sz() {
00408       return this->_coord[2];
00409     }
00410 
00411     inline value_type s() const {
00412       return this->_coord[3];
00413     }
00414 
00415     inline value_type& s() {
00416       return this->_coord[3];
00417     }
00418 
00419     // Acces to non-homogeneous coordinates in 3D
00420 
00421     inline value_type x() const {
00422       return this->_coord[0] / this->_coord[3];
00423     }
00424 
00425     inline value_type y() const {
00426       return this->_coord[1] / this->_coord[3];
00427     }
00428 
00429     inline value_type z() const {
00430       return this->_coord[2] / this->_coord[3];
00431     }
00432   };
00433 
00434 
00435   //
00436   //  Vec3 class (3D Vec)
00437   //    - T: value type
00438   //
00440 
00441   template <class T>
00442   class Vec3 : public Vec<T, 3>
00443   {
00444   public:
00445     
00446     typedef typename Vec<T, 3>::value_type value_type;
00447 
00448     inline Vec3() : Vec<T, 3>() {}
00449 
00450     template <class U>
00451     explicit inline Vec3(const U tab[3]) : Vec<T, 3>(tab) {}
00452 
00453     template <class U>
00454     explicit inline Vec3(const std::vector<U>& tab) : Vec<T, 3>(tab) {}
00455 
00456     template<class U>
00457     inline Vec3(const Vec<U, 3>& v) : Vec<T, 3>(v) {}
00458   
00459     template<class U>
00460       inline Vec3(const HVec3<U>& v) {
00461       this->_coord[0] = (T)v.x();
00462       this->_coord[1] = (T)v.y();
00463       this->_coord[2] = (T)v.z();
00464     }
00465 
00466     inline Vec3(const value_type x,
00467                 const value_type y = 0,
00468                 const value_type z = 0) : Vec<T, 3>() {
00469       this->_coord[0] = x;
00470       this->_coord[1] = y;
00471       this->_coord[2] = z;
00472     }
00473     
00474     inline value_type x() const {
00475       return this->_coord[0];
00476     }
00477 
00478     inline value_type& x() {
00479       return this->_coord[0];
00480     }
00481 
00482     inline value_type y() const {
00483       return this->_coord[1];
00484     }
00485 
00486     inline value_type& y() {
00487       return this->_coord[1];
00488     }
00489 
00490     inline value_type z() const {
00491       return this->_coord[2];
00492     }
00493 
00494     inline value_type& z() {
00495       return this->_coord[2];
00496     }
00497 
00498     inline void setX(const value_type v) {
00499       this->_coord[0] = v;
00500     }
00501 
00502     inline void setY(const value_type v) {
00503       this->_coord[1] = v;
00504     }
00505 
00506     inline void setZ(const value_type v) {
00507       this->_coord[2] = v;
00508     }
00509 
00510     // classical operators
00511     // FIXME: hack swig -- no choice
00512     inline Vec3<T> operator+(const Vec3<T>& v) const{
00513     Vec3<T> res(v);
00514     res += *this;
00515     return res;
00516     } 
00517 
00518     inline Vec3<T> operator-(const Vec3<T>& v) const{
00519     Vec3<T> res(*this);
00520     res -= v;
00521     return res;
00522     } 
00523 
00524     inline Vec3<T> operator*(const value_type r) const{
00525     Vec3<T> res(*this);
00526     res *= r;
00527     return res;
00528     } 
00529 
00530     inline Vec3<T> operator/(const value_type r) const{
00531     Vec3<T> res(*this);
00532     if (r)
00533       res /= r;
00534     return res;
00535     } 
00536 
00537     // dot product
00538     inline value_type operator*(const Vec3<T>& v) const{
00539     value_type sum = 0;
00540     for (unsigned i = 0; i < 3; i++)
00541       sum += (*this)[i] * v[i];
00542     return sum;
00543     } 
00544 
00545     // cross product for 3D Vectors
00546     // FIXME: hack swig -- no choice
00547     inline Vec3<T> operator^(const Vec3<T>& v) const{
00548     Vec3<T> res((*this)[1] * v[2] - (*this)[2] * v[1],
00549                 (*this)[2] * v[0] - (*this)[0] * v[2],
00550                 (*this)[0] * v[1] - (*this)[1] * v[0]);
00551     return res;
00552     } 
00553 
00554     // cross product for 3D Vectors
00555     template <typename U>
00556     inline Vec3<T> operator^(const Vec<U, 3>& v) const{
00557     Vec3<T> res((*this)[1] * v[2] - (*this)[2] * v[1],
00558                 (*this)[2] * v[0] - (*this)[0] * v[2],
00559                 (*this)[0] * v[1] - (*this)[1] * v[0]);
00560     return res;
00561     } 
00562   };
00563 
00564 
00565   //
00566   //  Matrix class
00567   //    - T: value type
00568   //    - M: rows
00569   //    - N: cols
00570   //
00572   
00573   // Dirty, but icc under Windows needs this
00574 # define _SIZE (M * N)
00575 
00576   template <class T, unsigned M, unsigned N>
00577   class Matrix
00578   {
00579   public:
00580 
00581     typedef T value_type;
00582     
00583     inline Matrix() {
00584       for (unsigned i = 0; i < _SIZE; i++)
00585         this->_coord[i] = 0;
00586     }
00587 
00588     ~Matrix() {
00589       Internal::is_false<(M == 0)>::ensure();
00590       Internal::is_false<(N == 0)>::ensure();
00591     }
00592 
00593     template <class U>
00594     explicit inline Matrix(const U tab[_SIZE]) {
00595       for (unsigned i = 0; i < _SIZE; i++)
00596         this->_coord[i] = tab[i];
00597     }
00598 
00599     template <class U>
00600     explicit inline Matrix(const std::vector<U>& tab) {
00601       for (unsigned i = 0; i < _SIZE; i++)
00602         this->_coord[i] = tab[i];
00603     }
00604 
00605     template <class U>
00606     inline Matrix(const Matrix<U, M, N>& m) {
00607       for (unsigned i = 0; i < M; i++)
00608         for (unsigned j = 0; j < N; j++)
00609           this->_coord[i * N + j] = (T)m(i, j);
00610     }
00611 
00612     inline value_type operator()(const unsigned i, const unsigned j) const {
00613       return this->_coord[i * N + j];
00614     }
00615 
00616     inline value_type& operator()(const unsigned i, const unsigned j) {
00617       return this->_coord[i * N + j];
00618     }
00619 
00620     static inline unsigned rows() {
00621       return M;
00622     }
00623 
00624     static inline unsigned cols() {
00625       return N;
00626     }
00627 
00628     inline Matrix<T, M, N>& transpose() const {
00629       Matrix<T, N, M> res;
00630       for (unsigned i = 0; i < M; i++)
00631         for (unsigned j = 0; j < N; j++)
00632           res(j,i) = this->_coord[i * N + j];
00633       return res;
00634     }
00635 
00636     template <class U>
00637     inline Matrix<T, M, N>& operator=(const Matrix<U, M, N>& m) {
00638       if (this != &m)
00639         for (unsigned i = 0; i < M; i++)
00640           for (unsigned j = 0; j < N; j++)
00641             this->_coord[i * N + j] = (T)m(i, j);
00642       return *this;
00643     }
00644 
00645     template <class U>
00646     inline Matrix<T, M, N>& operator+=(const Matrix<U, M, N>& m) {
00647       for (unsigned i = 0; i < M; i++)
00648         for (unsigned j = 0; j < N; j++)
00649           this->_coord[i * N + j] += (T)m(i, j);
00650       return *this;
00651     }
00652 
00653     template <class U>
00654     inline Matrix<T, M, N>& operator-=(const Matrix<U, M, N>& m) {
00655       for (unsigned i = 0; i < M; i++)
00656         for (unsigned j = 0; j < N; j++)
00657           this->_coord[i * N + j] -= (T)m(i, j);
00658       return *this;
00659     }
00660 
00661     template <class U>
00662     inline Matrix<T, M, N>& operator*=(const U lambda) {
00663       for (unsigned i = 0; i < M; i++)
00664         for (unsigned j = 0; j < N; j++)
00665           this->_coord[i * N + j] *= lambda;
00666       return *this;
00667     }
00668 
00669     template <class U>
00670     inline Matrix<T, M, N>& operator/=(const U lambda) {
00671       if (lambda)
00672         for (unsigned i = 0; i < M; i++)
00673           for (unsigned j = 0; j < N; j++)
00674             this->_coord[i * N + j] /= lambda;
00675       return *this;
00676     }
00677 
00678   protected:
00679 
00680     value_type _coord[_SIZE];
00681   };
00682 
00683 
00684   //
00685   //  SquareMatrix class
00686   //    - T: value type
00687   //    - N: rows & cols
00688   //
00690 
00691   // Dirty, but icc under Windows needs this
00692 # define __SIZE (N * N)
00693 
00694   template <class T, unsigned N>
00695   class SquareMatrix : public Matrix<T, N, N>
00696   {
00697   public:
00698 
00699     typedef T value_type;
00700   
00701     inline SquareMatrix() : Matrix<T, N, N>() {}
00702 
00703     template <class U>
00704     explicit inline SquareMatrix(const U tab[__SIZE]) : Matrix<T, N, N>(tab) {}
00705 
00706     template <class U>
00707     explicit inline SquareMatrix(const std::vector<U>& tab) : Matrix<T, N, N>(tab) {}
00708 
00709     template <class U>
00710     inline SquareMatrix(const Matrix<U, N, N>& m) : Matrix<T, N, N>(m) {}
00711 
00712     static inline SquareMatrix<T, N> identity() {
00713       SquareMatrix<T, N> res;
00714       for (unsigned i = 0; i < N; i++)
00715         res(i, i) = 1;
00716       return res;
00717     }
00718   };
00719 
00720 
00721   //
00722   // Vector external functions
00723   //
00725 
00726   //  template <class T, unsigned N>
00727   //  inline Vec<T, N> operator+(const Vec<T, N>& v1,
00728   //                            const Vec<T, N>& v2) {
00729   //    Vec<T, N> res(v1);
00730   //    res += v2;
00731   //    return res;
00732   //  }
00733   //
00734   //  template <class T, unsigned N>
00735   //  inline Vec<T, N> operator-(const Vec<T, N>& v1,
00736   //                            const Vec<T, N>& v2) {
00737   //    Vec<T, N> res(v1);
00738   //    res -= v2;
00739   //    return res;
00740   //  }
00741   //  template <class T, unsigned N>
00742   //    inline Vec<T, N> operator*(const Vec<T, N>& v,
00743   //                            const typename Vec<T, N>::value_type r) {
00744   //    Vec<T, N> res(v);
00745   //    res *= r;
00746   //    return res;
00747   //  }
00748   
00749   template <class T, unsigned N>
00750     inline Vec<T, N> operator*(const typename Vec<T, N>::value_type r,
00751                                 const Vec<T, N>& v) {
00752     Vec<T, N> res(v);
00753     res *= r;
00754     return res;
00755   }
00756   //
00757   //  template <class T, unsigned N>
00758   //  inline Vec<T, N> operator/(const Vec<T, N>& v,
00759   //                            const typename Vec<T, N>::value_type r) {
00760   //    Vec<T, N> res(v);
00761   //    if (r)
00762   //      res /= r;
00763   //    return res;
00764   //  }
00765   //
00766   // dot product
00767   //  template <class T, unsigned N>
00768   //    inline typename Vec<T, N>::value_type operator*(const Vec<T, N>& v1,
00769   //    const Vec<T, N>& v2) {
00770   //    typename Vec<T, N>::value_type sum = 0;
00771   //    for (unsigned i = 0; i < N; i++)
00772   //      sum += v1[i] * v2[i];
00773   //    return sum;
00774   //  }
00775   //
00776   //  // cross product for 3D Vectors
00777   //  template <typename T>
00778   //  inline Vec3<T> operator^(const Vec<T, 3>& v1,
00779   //                       const Vec<T, 3>& v2) {
00780   //    Vec3<T> res(v1[1] * v2[2] - v1[2] * v2[1],
00781   //            v1[2] * v2[0] - v1[0] * v2[2],
00782   //            v1[0] * v2[1] - v1[1] * v2[0]);
00783   //    return res;
00784   //  }
00785 
00786   // stream operator
00787   template <class T, unsigned N>
00788   inline std::ostream& operator<<(std::ostream& s,
00789                                   const Vec<T, N>& v) {
00790     unsigned i;
00791     s << "[";
00792     for (i = 0; i < N - 1; i++)
00793       s << v[i] << ", ";
00794     s << v[i] << "]";
00795     return s;
00796   }
00797 
00798 
00799   //
00800   // Matrix external functions
00801   //
00803 
00804   template <class T, unsigned M, unsigned N>
00805   inline Matrix<T, M, N>
00806   operator+(const Matrix<T, M, N>& m1,
00807             const Matrix<T, M, N>& m2) {
00808     Matrix<T, M, N> res(m1);
00809     res += m2;
00810     return res;
00811   }
00812 
00813   template <class T, unsigned M, unsigned N>
00814   inline Matrix<T, M, N>
00815   operator-(const Matrix<T, M, N>& m1,
00816             const Matrix<T, M, N>& m2) {
00817     Matrix<T, M, N> res(m1);
00818     res -= m2;
00819     return res;
00820   }
00821 
00822   template <class T, unsigned M, unsigned N>
00823   inline Matrix<T, M, N>
00824   operator*(const Matrix<T, M, N>& m1,
00825             const typename Matrix<T, M, N>::value_type lambda) {
00826     Matrix<T, M, N> res(m1);
00827     res *= lambda;
00828     return res;
00829   }
00830 
00831   template <class T, unsigned M, unsigned N>
00832   inline Matrix<T, M, N>
00833   operator*(const typename Matrix<T, M, N>::value_type lambda,
00834             const Matrix<T, M, N>& m1) {
00835     Matrix<T, M, N> res(m1);
00836     res *= lambda;
00837     return res;
00838   }
00839 
00840   template <class T, unsigned M, unsigned N>
00841   inline Matrix<T, M, N>
00842   operator/(const Matrix<T, M, N>& m1,
00843             const typename Matrix<T, M, N>::value_type lambda) {
00844     Matrix<T, M, N> res(m1);
00845     res /= lambda;
00846     return res;
00847   }
00848 
00849   template <class T, unsigned M, unsigned N, unsigned P>
00850   inline Matrix<T, M, P>
00851   operator*(const Matrix<T, M, N>& m1,
00852             const Matrix<T, N, P>& m2) {
00853     unsigned i, j, k;
00854     Matrix<T, M, P> res;
00855     typename  Matrix<T, N, P>::value_type scale;
00856   
00857     for (j = 0; j < P; j++) {
00858       for (k = 0; k < N; k++) {
00859         scale = m2(k, j);
00860         for (i = 0; i < N; i++)
00861           res(i, j) += m1(i, k) * scale;
00862       }
00863     }
00864     return res;
00865   }
00866 
00867   template <class T, unsigned M, unsigned N>
00868   inline Vec<T, M>
00869   operator*(const Matrix<T, M, N>& m,
00870             const Vec<T, N>& v) {
00871   
00872     Vec<T, M> res;
00873     typename Matrix<T, M, N>::value_type scale;
00874   
00875     for (unsigned j = 0; j < M; j++) {
00876       scale = v[j];
00877       for (unsigned i = 0; i < N; i++)
00878         res[i] += m(i, j) * scale;
00879     }
00880     return res;
00881   }
00882 
00883   // stream operator
00884   template <class T, unsigned M, unsigned N>
00885   inline std::ostream& operator<<(std::ostream& s,
00886                                   const Matrix<T, M, N>& m) {
00887     unsigned i, j;
00888     for (i = 0; i < M; i++) {
00889       s << "[";
00890       for (j = 0; j < N - 1; j++)
00891         s << m(i, j) << ", ";
00892       s << m(i, j) << "]" << std::endl;
00893     }
00894     return s;
00895   }
00896 
00897 } // end of namespace VecMat
00898 
00899 #endif // VECMAT_H