Matrix.h

Go to the documentation of this file.
00001 
00020 #pragma once
00021 
00022 #include "standard.h"
00023 
00024 #pragma warning( push, 3 )
00025 #include <numeric> // inner_product
00026 #include <xutility> // swap
00027 #pragma warning ( pop )
00028 
00029 #include <malloc.h> // alloca
00030 #include <assert.h>
00031 
00033 #ifndef COMPILETIME_ASSERT
00034 #define COMPILETIME_ASSERT(assertion) do { if (0) { char ch[(assertion)] = { 'a' }; ch;} } while (false)
00035 #endif
00036 
00037 // COMPILETIME_ASSERT gives us meaningless warnings unless we disable them
00038 #pragma warning ( disable:4127 ) // conditional expression is constant
00039 
00040 
00041 // -------------------------------------------------------------------
00042 // The two types of matrices exposed by these templates:
00043 
00045 template < int cols, int rows, typename T > 
00046 class Matrix; 
00047 
00049 template< int size, typename T >
00050 class SymmetricMatrix; 
00051 
00053 template< int height, typename T >
00054 class ColVector;
00055 
00056 
00061 template< int size, typename T >
00062 class DataBlock
00063 {
00064     protected:
00065 
00066         inline DataBlock() {}
00067             inline DataBlock<size,T> add(const DataBlock< size, T > &d) const
00068             {
00069                     DataBlock<size,T> rtn;
00070 
00071                     for (int i = 0; i < size; i++)
00072                             rtn.array[i] = array[i] + d.array[i];
00073 
00074                     return rtn;
00075             }
00076 
00077             inline void addToMe(const DataBlock< size, T> &d)
00078             {
00079                     for (int i = 0; i < size; i++)
00080                             array[i] = array[i] + d.array[i];
00081             }
00082 
00083             inline void subtractFromMe(const DataBlock< size, T> &d)
00084             {
00085                     for (int i = 0; i < size; i++)
00086                             array[i] = array[i] - d[i];
00087             }
00088 
00089             inline DataBlock<size,T> subtract (const DataBlock< size, T> &d) const
00090             {
00091                     DataBlock<size,T> rtn;
00092                     for (int i = 0; i < size; i++)
00093                             rtn.array[i] = array[i] - d.array[i];               
00094 
00095                     return rtn;
00096             }
00097 
00098             inline bool isEqualTo (const DataBlock< size, T> &d) const
00099             {
00100                     return (memcmp (array, d.array, sizeof(array)) == 0);
00101             }
00102 
00103             inline void copyFrom (const DataBlock<size, T> &d)
00104             {
00105                     memcpy (&array[0], &d.array[0], sizeof(array));
00106             }
00107 
00108             /* multiplication methods for ints, floats, and doubles */
00109 
00110             inline DataBlock<size,T> multiply (int n) const
00111             {
00112                     DataBlock<size,T> rtn;
00113                     for (int i = 0; i < size; i++)
00114                             rtn.array[i] = array[i] * n;                
00115 
00116                     return rtn;
00117             }
00118 
00119             inline DataBlock<size,T> multiply (float n) const
00120             {
00121                     DataBlock<size,T> rtn;
00122                     for (int i = 0; i < size; i++)
00123                             rtn.array[i] = array[i] * n;                
00124 
00125                     return rtn;
00126             }
00127 
00128 
00129             inline DataBlock<size,T> multiply (double n) const
00130             {
00131                     DataBlock<size,T> rtn;
00132                     for (int i = 0; i < size; i++)
00133                             rtn.array[i] = (T)(array[i] * n);           
00134 
00135                     return rtn;
00136             }
00137 
00138             /* division methods for ints, floats, and doubles */
00139 
00140             inline DataBlock<size,T> divide (int n) const
00141             {
00142                     DataBlock<size,T> rtn;
00143             T inverse = 1. / n;
00144 
00145                     for (int i = 0; i < size; i++)
00146                             rtn.array[i] = array[i] * inverse;          
00147 
00148                     return rtn;
00149             }
00150 
00151             inline DataBlock<size,T> divide (float n) const
00152             {
00153                     DataBlock<size,T> rtn;
00154             T inverse = 1. / n;
00155 
00156                     for (int i = 0; i < size; i++)
00157                             rtn.array[i] = array[i] * inverse;          
00158 
00159                     return rtn;
00160             }
00161 
00162             inline DataBlock<size,T> divide (double n) const
00163             {
00164                     DataBlock<size,T> rtn;
00165 
00166             T inverse = (T)(1. / n);
00167 
00168                     for (int i = 0; i < size; i++)
00169                             rtn.array[i] = array[i] * inverse;          
00170 
00171                     return rtn;
00172             }
00173 
00174 
00175             T array[size];
00176     public:
00177 
00178             inline T * getData()
00179             { return array; }
00180             
00181             inline setToZero()
00182             {
00183                     memset(array, 0, sizeof(array));
00184             }
00185 };
00186 
00189 #define TRIANGULAR(i) ( ((i + 1)*i) / 2)
00190 
00203 template< int size, typename T >
00204 class SymmetricMatrix : public DataBlock< TRIANGULAR(size), T >
00205 {
00206     private:
00207             typedef SymmetricMatrix< size, T > _Myt;
00208             typedef DataBlock< TRIANGULAR(size), T > parentType;
00209             typedef Matrix< size, size, T > MtxAsymmetric;
00210 
00211     public:
00212 
00213             SymmetricMatrix() {}
00214             SymmetricMatrix(const parentType &p) {copyFrom (p);}
00215             SymmetricMatrix(const MtxAsymmetric &m)
00216             {
00217                     this->operator=(m);
00218             }
00219             const enum {nColumns = size};
00220             const enum {nRows = size};
00221 
00222             //---------------------------------------------
00223 
00224             _Myt operator-(const _Myt &m)  const { return this->subtract(m);}
00225             _Myt operator+(const _Myt &m)  const { return this->add(m);}
00226             _Myt operator*(int n)          const { return this->multiply(n); }
00227             _Myt operator*(float f)        const { return this->multiply(f); }
00228             _Myt operator*(double f)       const { return this->multiply(f); }
00229             _Myt operator/(int n)          const { return this->divide(n); }
00230             _Myt operator/(float n)        const { return this->divide(n); }
00231             _Myt operator/(double n)       const { return this->divide(n); }
00232             bool operator==(_Myt &m)       const { return this->isEqualTo (m); }
00233             void operator+=(_Myt &m)      { this->addToMe (m); }
00234             void operator-=(_Myt &m)      { this->subtractFromMe (m); }
00235             void operator=(const _Myt &m) { this->copyFrom (m); }
00236             inline T &  operator()(int col, int row) { return elementAt(col,row);}
00237         inline T &  operator[](int n) { return array[n]; }
00238         inline T   operator[](int n) const { return array[n]; }
00239             void print(char *str = "") const { printMatrix(*this,str); } 
00240 
00241             template <int N>
00242             Matrix< N, nRows, T> operator* (const SymmetricMatrix<N, T> &m) const
00243             {
00244                     
00245                     // If it fails to compile here, that means that you've tried to 
00246                     // multiply two matrices whose sizes don't match. The first
00247                     // Matrix should have as many columns as the second Matrix's rows
00248             COMPILETIME_ASSERT (cols == N);
00249 
00250             return multMatrix< _Myt, Matrix< N, N, T >, T, rows, N>(*this, m);
00251             }
00252 
00253             template <int theirCols, int theirRows>
00254             Matrix< theirCols, nRows, T> operator* (const Matrix< theirCols, theirRows, T> &m) const
00255             {
00256                     
00257                     // If it fails to compile here, that means that you've tried to 
00258                     // multiply two matrices whose sizes don't match. The first
00259                     // Matrix should have as many columns as the second Matrix's rows
00260             COMPILETIME_ASSERT (cols == theirRows);
00261 
00262             return multMatrix< _Myt, Matrix< theirCols, theirRows, T >, T, nRows, theirCols>(*this, m);
00263             }
00264 
00265             //---------------------------------------------
00266 
00267             void operator=(const Matrix<size, size, T> &m)
00268             {
00269                     for (int col = 0; col < nColumns; col++)
00270                             for (int row = col; row < nRows; row++)
00271                                     elementAt (col,row) = m.elementAt(col,row);
00272             }
00273 
00274             inline T & elementAt (int col, int row) 
00275             {
00276                     assert (col >= 0 && row >= 0 && col < nColumns && row < nRows);
00277 
00278                     return (col > row)?
00279                             array[row*nRows + col - TRIANGULAR(row)]: // swapped
00280                             array[col*nRows + row - TRIANGULAR(col)]; // not swapped
00281             }
00282 
00283             inline T elementAt (int col, int row) const
00284             {
00285                     assert (col >= 0 && row >= 0 && col < nColumns && row < nRows);
00286 
00287                     return (col > row)?
00288                             array[row*nRows + col - TRIANGULAR(row)]: // swapped
00289                             array[col*nRows + row - TRIANGULAR(col)]; // not swapped
00290             }
00291 };
00292 
00293 // -------------------------------------------------------------------
00294 // Matrix: this class holds a regular matrix.  It supports most
00295 // operations with...
00296 //
00297 //     * other "SymmetricMatrix" objects
00298 //     * "Matrix" objects
00299 //     * floats and doubles
00300 
00301 template < int cols, int rows, typename T >
00302 class Matrix : public DataBlock< cols*rows, T >
00303 {
00304     private:
00305             typedef Matrix< cols, rows, T > _Myt;
00306             typedef DataBlock< cols*rows, T> parentType;
00307             typedef SymmetricMatrix< cols, T > MtxSymmetric;
00308 
00309     public:
00310             Matrix() {}
00311             Matrix(const parentType &p) {copyFrom (p);}
00312             Matrix(const MtxSymmetric &m)
00313             {
00314             COMPILETIME_ASSERT(nRows == nColumns);
00315                     this->operator=(m);
00316             }
00317 
00318             const enum {nColumns = cols};
00319             const enum {nRows = rows};
00320 
00321             //---------------------------------------------
00322 
00323             _Myt operator-(const _Myt &m)  const { return this->subtract(m);}
00324             _Myt operator+(const _Myt &m)  const { return this->add(m);}
00325             _Myt operator*(int n)          const { return this->multiply(n); }
00326             _Myt operator*(float f)        const { return this->multiply(f); }
00327             _Myt operator*(double f)       const { return this->multiply(f); }
00328             _Myt operator/(int n)          const { return this->divide(n); }
00329             _Myt operator/(float n)        const { return this->divide(n); }
00330             _Myt operator/(double n)       const { return this->divide(n); }
00331             bool operator==(_Myt &m)       const { return this->isEqualTo (m); }
00332             void operator+=(_Myt &m)      { this->addToMe (m); }
00333             void operator-=(_Myt &m)      { this->subtractFromMe (m); }
00334             void operator=(const _Myt &m) { this->copyFrom (m); }
00335             inline T &  operator()(int col, int row) { return elementAt(col,row);}
00336         inline T &  operator[](int n) { return array[n]; }
00337         inline T   operator[](int n) const { return array[n]; }
00338             void print(char *str = "") const { printMatrix(*this,str); } 
00339 
00340         template <int N>
00341             Matrix< N, nRows, T> operator* (const SymmetricMatrix<N, T> &m) const
00342             {
00343                     
00344                     // If it fails to compile here, that means that you've tried to 
00345                     // multiply two matrices whose sizes don't match. The first
00346                     // Matrix should have as many columns as the second Matrix's rows
00347             COMPILETIME_ASSERT (cols == N);
00348 
00349             return multMatrix< _Myt, Matrix< N, N, T >, T, rows, N>(*this, m);
00350             }
00351 
00352             template <int theirCols, int theirRows>
00353             Matrix< theirCols, nRows, T> operator* (const Matrix< theirCols, theirRows, T> &m) const
00354             {
00355                     
00356                     // If it fails to compile here, that means that you've tried to 
00357                     // multiply two matrices whose sizes don't match. The first
00358                     // Matrix should have as many columns as the second Matrix's rows
00359             COMPILETIME_ASSERT (cols==theirRows);
00360 
00361             return multMatrix< _Myt, Matrix< theirCols, theirRows, T >, T, nRows, theirCols>(*this, m);
00362             }
00363             //---------------------------------------------
00364 
00365             void operator=(const SymmetricMatrix<cols, T> &m)
00366             {
00367                     for (int col = 0; col < cols; col++)
00368                             for (int row = 0; row < rows; row++)
00369                                     elementAt (col,row) = m.elementAt (col,row);
00370             }
00371 
00372 
00373 
00374         T determinant()
00375         {
00376             COMPILETIME_ASSERT(nRows==nColumns);
00377             COMPILETIME_ASSERT(nRows>1);
00378 
00379             if (nRows == 1)
00380             {
00381                 return 0;
00382             }
00383 
00384             if (nRows == 2)
00385             {
00386                 return (elementAt(0,0) * elementAt(1,1) - 
00387                         elementAt(1,0) * elementAt(0,1));
00388             }
00389 
00390             T total = 0.;
00391             for (int i = 0; i < nColumns; i++)
00392             {
00393                 Submatrix sub;
00394                 sub = getSubmatrix(i, 0);
00395 
00396                 T det = sub.determinant();
00397 
00398                 if (0 == i % 2)
00399                     total += det;
00400                 else
00401                     total -= det;
00402             }
00403 
00404             return total;
00405         }
00406         
00407         inline T & elementAt (int col, int row)
00408             {
00409                     assert (col >= 0 && row >= 0 && col < nColumns && row < nRows);
00410 
00411                     return array[col*rows + row];
00412             }
00413 
00414             inline T  elementAt (int col, int row) const
00415             {
00416                     assert (col >= 0 && row >= 0 && col < nColumns && row < nRows);
00417 
00418                     return array[col*rows + row];
00419             }
00420 
00421             Matrix <rows, cols, T> getTranspose() const
00422             {
00423                     Matrix<rows, cols, T> rtn;
00424                     for (int row = 0; row < rows; row++)
00425                             for (int col = 0; col < cols; col++)
00426                                     rtn(row,col) = elementAt(col,row);
00427 
00428                     return rtn;
00429             }
00430 
00431 
00432             void setToIdentity()
00433             {
00434             COMPILETIME_ASSERT(nRows==nColumns);
00435                     setToZero();
00436                     
00437                     for (int n = 0; n < cols; n++)
00438                             elementAt (n,n) = 1;
00439             }
00440 
00441             bool getInverse(Matrix<cols,rows,T> &answer) const
00442             {
00443             COMPILETIME_ASSERT(nRows==nColumns);
00444                     
00445                     Matrix<cols,rows,T> mtx;
00446                     mtx = *this;
00447                     answer.setToIdentity();
00448                     
00449                     // for each column...
00450                     for (int col = 0; col < nColumns; col++)
00451                     {
00452                             int rowMax = col;
00453                             
00454                             for (int row=col+1; row<nRows; row++)
00455                             {
00456                                     if (mtx(row,col) > mtx(rowMax, col))
00457                                             rowMax = row;
00458                             }
00459                             
00460                             if (mtx(rowMax, col) == 0) 
00461                             {
00462                                     return false;
00463                             }
00464                             
00465                             // Swap row "rowMax" with row "c"
00466                             for (int cc=0; cc<nColumns; cc++)
00467                             {
00468                                     T tmp = mtx(col,cc);
00469                                     mtx(col,cc) = mtx(rowMax,cc);
00470                                     mtx(rowMax,cc) = tmp;
00471                                     tmp = answer(col,cc);
00472                                     answer(col,cc) = answer(rowMax,cc);
00473                                     answer(rowMax,cc) = tmp;
00474                             }
00475                             
00476                             // Now everything we do is on row "c".
00477                             // Set the max cell to 1 by dividing the entire row by that value
00478                             T tmp = mtx(col,col);
00479                             for (cc=0; cc<nColumns; cc++)
00480                             {
00481                                     mtx(col,cc) =  mtx(col,cc) / tmp;
00482                                     answer(col,cc) = answer(col,cc) / tmp;
00483                             }
00484                             
00485                             // Now do the other rows, so that this column only has a 1 and 0's
00486                             for (row = 0; row < nRows; row++)
00487                             {
00488                                     if (row != col)
00489                                     {
00490                                             tmp = mtx (row,col);
00491                                             for (cc=0; cc<nColumns; cc++)
00492                                             {
00493                                                     mtx(row,cc) = mtx(row,cc) - mtx(col,cc) * tmp;
00494                                                     answer(row,cc) = answer(row,cc) - answer(col,cc)*tmp;
00495                                             }
00496                                     }
00497                             }
00498                             
00499                     }
00500                     return true;
00501             }
00502 
00503     private:
00504         typedef Matrix< (nColumns>2?nColumns-1:nColumns), (nRows>2?nRows-1:nRows), T > Submatrix;
00505         Submatrix getSubmatrix (int colToDelete, int rowToDelete)
00506         {
00507             COMPILETIME_ASSERT(nRows==nColumns);
00508             COMPILETIME_ASSERT(nRows>1);
00509 
00510             Submatrix rtn;
00511 
00512             int curSpot = 0;
00513             for (int col = 0; col < nColumns; col++)
00514             {
00515                 for (int row = 0; row < nRows; row++)
00516                 {
00517                     if (row != rowToDelete && col != colToDelete)
00518                     {
00519                         rtn[curSpot] = elementAt(col,row);
00520                         curSpot++;
00521                     }
00522                 }
00523             }   
00524 
00525             return rtn;
00526         }
00527 };
00528 
00529 
00530 
00531 // -------------------------------------------------------------------
00532 // ColVector: a column-based vector.
00533 
00534 template< int height, typename T >
00535 class ColVector : public Matrix< 1, height, T >
00536 {
00537 public:
00538         typedef Matrix<1,height,T> parentType;
00539     typedef ColVector< height, T > _Myt;
00540 
00541     inline ColVector(parentType &p) { parentType::operator=(p); }
00542     inline void operator=(const parentType &p) { parentType::operator=(p); }
00543 
00544     // accessors
00545     template< typename C >
00546     inline _Myt operator/(const C n)      const { return parentType::operator/(n); }
00547 
00548     template< typename C >
00549     inline _Myt operator+(const C n)      const { return parentType::operator+(n); }
00550 
00551     template< typename C >
00552     inline _Myt operator-(const C n)      const { return parentType::operator-(n); }
00553 
00554     inline _Myt operator*(int n)          const { return parentType::operator*(n);}
00555     inline _Myt operator*(float n)        const { return parentType::operator*(n);}
00556     inline _Myt operator*(double n)       const { return parentType::operator*(n);}
00557 
00558         inline bool operator==(const _Myt &m) const { return parentType::operator==((parentType)m);}
00559 
00560     // mutators
00561     inline void operator+=(const _Myt &m)       {        parentType::operator+=((parentType)m);}
00562     inline void operator-=(const _Myt &m)       {        parentType::operator-=((parentType)m);}
00563     inline void operator= (const _Myt &m)       {        parentType::operator=((parentType)m);}
00564     
00565     
00566     template <int theirCols, int theirRows>
00567     inline Matrix< theirCols, height, T> operator* (const Matrix< theirCols, theirRows, T> &m) const
00568     {
00569         
00570         // If it fails to compile here, that means that you've tried to 
00571         // multiply two matrices whose sizes don't match. The first
00572         // Matrix should have as many columns as the second Matrix's rows
00573         COMPILETIME_ASSERT (1==theirRows);
00574         
00575         return multMatrix< _Myt, Matrix< theirCols, theirRows, T >, T, nRows, theirCols>(*this, m);
00576     }
00577     
00578     Matrix <height, 1, T> getTranspose() const
00579         {
00580                 Matrix<height, 1, T> rtn;
00581         memcpy(rtn.getData(), const_cast<_Myt*>(this)->getData(), sizeof(array));
00582                 return rtn;
00583         }
00584 
00585     // constructors
00586     ColVector () {}
00587 
00588     ColVector (T a) 
00589     { 
00590         COMPILETIME_ASSERT (nRows == 1); array[0] = a; 
00591     }
00592 
00593     ColVector (T a, T b) 
00594     { 
00595         COMPILETIME_ASSERT (nRows == 2); 
00596         array[0] = a; array[1] = b;
00597     }
00598 
00599     ColVector (T a, T b, T c) 
00600     { 
00601         COMPILETIME_ASSERT (nRows == 3); array[0] = a; 
00602         array[0] = a; array[1] = b; array[2] = c;
00603     }
00604 
00605     ColVector (T a, T b, T c, T d) 
00606     { 
00607         COMPILETIME_ASSERT (nRows == 4); array[0] = a; 
00608         array[0] = a; array[1] = b; array[2] = c; array[3] = d;
00609     }
00610     
00611     // accessors
00612     T getLength () const
00613     { 
00614         return (T)sqrt(getLengthSquared()); 
00615     }
00616     
00617     T getLengthSquared() const
00618     {
00619         return (T)std::inner_product(&array[0], &array[nRows], &array[0], 0.);
00620     }
00621 
00622     ColVector<3, T>  crossProduct    (const ColVector<height, T> &vx2) const
00623     {
00624         const ColVector<3, T> &vx1 = *this;
00625         ColVector<3, T> v;
00626         
00627         v[0] = vx1[1]*vx2[2] - vx1[2]*vx2[1];
00628         v[1] = vx1[2]*vx2[0] - vx1[0]*vx2[2];
00629         v[2] = vx1[0]*vx2[1] - vx1[1]*vx2[0];
00630         return v;
00631     }
00632 
00633     _Myt getReflection(const _Myt & normal) const
00634     {
00635         _Myt rtn;
00636         rtn = *this - normal * 2. * this->dotProduct(normal);
00637 
00638         return rtn;
00639     }
00640 
00641     T dotProduct (const _Myt &v) const
00642     {
00643         T rtn = 0;
00644         for (int i = 0; i < height; i++)
00645             rtn += array[i] * v[i];
00646 
00647         return rtn;
00648     }
00649 
00650     void normalize()
00651     {   
00652         T len = getLength(); 
00653         if (len) {
00654             for (int i = 0; i < nRows; i++)
00655                 array[i] /= len;
00656         }
00657         else
00658             assert(!"ColVector::normalize(): can't normalize a zero vector.");
00659     }
00660         
00661 #if 0 // this is too dangerous to be used in practice
00662     ColVector( T first, ... )
00663     {
00664         va_list marker;
00665         
00666         array[0] = first;
00667 
00668         va_start( marker, first );     /* Initialize variable arguments. */
00669         for (int i = 1; i < nRows; i++)
00670         {
00671             array[i] = va_arg( marker, T);
00672         }
00673         va_end( marker );              /* Reset variable arguments.      */
00674     }
00675 #endif
00676 
00677 };
00678 
00679 
00680 
00681 
00682 template< int height, typename T >
00683 class Position : public Matrix< 1, height, T >
00684 {
00685     public:
00686             typedef Matrix< 1,height,T > parentType;
00687         typedef Position< height, T > _Myt;
00688 
00689         inline Position(parentType &p) { parentType::operator=(p); }
00690         inline void operator=(const parentType &p) { parentType::operator=(p); }
00691 
00692         // constructors
00693         Position () {}
00694 
00695         Position (T a) 
00696         { 
00697             COMPILETIME_ASSERT (nRows == 1); array[0] = a; 
00698         }
00699 
00700         Position (T a, T b) 
00701         { 
00702             COMPILETIME_ASSERT (nRows == 2); 
00703             array[0] = a; array[1] = b;
00704         }
00705 
00706         Position (T a, T b, T c) 
00707         { 
00708             COMPILETIME_ASSERT (nRows == 3); array[0] = a; 
00709             array[0] = a; array[1] = b; array[2] = c;
00710         }
00711 
00712         Position (T a, T b, T c, T d) 
00713         { 
00714             COMPILETIME_ASSERT (nRows == 4); array[0] = a; 
00715             array[0] = a; array[1] = b; array[2] = c; array[3] = d;
00716         }
00717 
00718         _Myt linearlyInterpolate (const _Myt & p, double t) 
00719         {
00720             return ((*this)*(1-t) + (p*t));
00721         }
00722 
00723             inline bool operator==(const _Myt &m) const { return parentType::operator==((parentType)m);}
00724         inline void operator= (const _Myt &m)       {        parentType::operator=((parentType)m);}
00725 
00726         Matrix <height, 1, T> getTranspose() const
00727             {
00728                     Matrix<height, 1, T> rtn;
00729             memcpy(rtn.getData(), const_cast<_Myt*>(this)->getData(), sizeof(array));
00730                     return rtn;
00731             }
00732 
00733         template< typename C >
00734         inline ColVector< height, T > operator-(const C n)      const { return parentType::operator-(n); }
00735 
00736     // it doesn't really make sense to perform the following operations on a position.
00737     // what does it mean to add two places in space? nothing. interpolating makes sense,
00738     // but that operation is provided above.
00739 
00740         // accessors
00741         template< typename C >
00742         inline _Myt operator/(const C n)      const { return parentType::operator/(n); }
00743 
00744         template< typename C >
00745         inline _Myt operator+(const C &n)      const { return parentType::operator+(n); }
00746 
00747 
00748         inline _Myt operator*(int n)          const { return parentType::operator*(n);}
00749         inline _Myt operator*(float n)        const { return parentType::operator*(n);}
00750         inline _Myt operator*(double n)       const { return parentType::operator*(n);}
00751 
00752         // mutators
00753         inline void operator+=(const _Myt &m)       {        parentType::operator+=((parentType)m);}
00754         inline void operator-=(const _Myt &m)       {        parentType::operator-=((parentType)m);}
00755     
00756     
00757         template <int theirCols, int theirRows>
00758         inline Matrix< theirCols, height, T> operator* (const Matrix< theirCols, theirRows, T> &m) const
00759         {
00760         
00761             // If it fails to compile here, that means that you've tried to 
00762             // multiply two matrices whose sizes don't match. The first
00763             // Matrix should have as many columns as the second Matrix's rows
00764             COMPILETIME_ASSERT (1==theirRows);
00765         
00766             return multMatrix< _Myt, Matrix< theirCols, theirRows, T >, T, nRows, theirCols>(*this, m);
00767         }    
00768 };
00769 
00770 
00771 
00772 // -------------------------------------------------------------------
00773 // multMatrix: matrix support function. Performs matrix
00774 // multiplication.
00775 
00776 template< typename A, typename B, typename T, int rows1, int cols2>
00777 inline Matrix< cols2, rows1, T> multMatrix (A m1, B m2)
00778 {
00779     Matrix< m2.nColumns, m1.nRows, T> rtn;
00780     int row1, col2;
00781     for (row1 = 0; row1 < m1.nRows; row1++)
00782     {
00783         for (col2 = 0; col2 < B::nColumns; col2++)
00784         {
00785             T result = 0;
00786 
00787             for (int i = 0; i < A::nColumns; i++)
00788                 result += m1.elementAt (i, row1) * m2.elementAt (col2, i);
00789 
00790             rtn (col2, row1) = result;
00791         }
00792     }
00793 
00794     return rtn;
00795 }
00796 
00797 
00798 // -------------------------------------------------------------------
00799 // printMatrix: matrix support function. Prints a matrix out to the
00800 // debugging output window in VC++
00801 
00802 template < typename T >
00803 void printMatrix (const T & mtx, const char *str)
00804 {
00805     MTRACE("\n---- %s -----", str);
00806     
00807     if (T::nRows == 1)
00808     {
00809         if (T::nColumns == 1)
00810             MTRACE("scalar");
00811         else
00812             MTRACE("%d element row vector", T::nColumns);
00813     }
00814     else
00815     {
00816         if (T::nColumns == 1)
00817             MTRACE("%d element col vector", T::nRows);
00818         else
00819             MTRACE("%d cols x %d rows matrix", T::nColumns, T::nRows);
00820     }
00821     
00822     MTRACE(" ----------\n");
00823     for (int row = 0; row < T::nRows; row++)
00824     {
00825         for (int col = 0; col < T::nColumns; col++)
00826             MTRACE ("%.3lf ", mtx.elementAt(col,row));
00827         
00828         MTRACE("\n");
00829     }
00830 }
00831 
00832 

Generated on Tue May 21 03:34:51 2002 for Archimedes by doxygen1.2.15