• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

MatrixOps.h

Go to the documentation of this file.
00001 // GMTL is (C) Copyright 2001-2010 by Allen Bierbaum
00002 // Distributed under the GNU Lesser General Public License 2.1 with an
00003 // addendum covering inlined code. (See accompanying files LICENSE and
00004 // LICENSE.addendum or http://www.gnu.org/copyleft/lesser.txt)
00005 
00006 #ifndef _GMTL_MATRIXOPS_H_
00007 #define _GMTL_MATRIXOPS_H_
00008 
00009 #include <iostream>         // for std::cerr
00010 #include <algorithm>        // needed for std::swap
00011 #include <gmtl/Matrix.h>
00012 #include <gmtl/Math.h>
00013 #include <gmtl/Vec.h>
00014 #include <gmtl/VecOps.h>
00015 #include <gmtl/Util/Assert.h>
00016 
00017 namespace gmtl
00018 {
00027    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00028    inline Matrix<DATA_TYPE, ROWS, COLS>& identity( Matrix<DATA_TYPE, ROWS, COLS>& result )
00029    {
00030       if(result.mState != Matrix<DATA_TYPE, ROWS, COLS>::IDENTITY)   // if not already ident
00031       {
00032          // TODO: mp
00033          for (unsigned int r = 0; r < ROWS; ++r)
00034          for (unsigned int c = 0; c < COLS; ++c)
00035             result( r, c ) = (DATA_TYPE)0.0;
00036 
00037          // TODO: mp
00038          for (unsigned int x = 0; x < Math::Min( COLS, ROWS ); ++x)
00039             result( x, x ) = (DATA_TYPE)1.0;
00040 
00041          result.mState = Matrix<DATA_TYPE, ROWS, COLS>::IDENTITY;
00042 //         result.mState = Matrix<DATA_TYPE, ROWS, COLS>::FULL;
00043       }
00044 
00045       return result;
00046    }
00047 
00048 
00052    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00053    inline Matrix<DATA_TYPE, ROWS, COLS>& zero( Matrix<DATA_TYPE, ROWS, COLS>& result )
00054    {
00055       if (result.mState == Matrix<DATA_TYPE, ROWS, COLS>::IDENTITY)
00056       {
00057          for (unsigned int x = 0; x < Math::Min( ROWS, COLS ); ++x)
00058          {
00059             result( x, x ) = (DATA_TYPE)0;
00060          }
00061       }
00062       else
00063       {
00064          for (unsigned int x = 0; x < ROWS*COLS; ++x)
00065          {
00066             result.mData[x] = (DATA_TYPE)0;
00067          }
00068       }
00069       result.mState = Matrix<DATA_TYPE, ROWS, COLS>::ORTHOGONAL;
00070       return result;
00071    }
00072 
00073 
00079    template <typename DATA_TYPE, unsigned ROWS, unsigned INTERNAL, unsigned COLS>
00080    inline Matrix<DATA_TYPE, ROWS, COLS>& mult( Matrix<DATA_TYPE, ROWS, COLS>& result,
00081                  const Matrix<DATA_TYPE, ROWS, INTERNAL>& lhs,
00082                  const Matrix<DATA_TYPE, INTERNAL, COLS>& rhs )
00083    {
00084       Matrix<DATA_TYPE, ROWS, COLS> ret_mat; // prevent aliasing
00085       zero( ret_mat );
00086 
00087       // p. 150 Numerical Analysis (second ed.)
00088       // if A is m x p, and B is p x n, then AB is m x n
00089       // (AB)ij  =  [k = 1 to p] (a)ik (b)kj     (where:  1 <= i <= m, 1 <= j <= n)
00090       for (unsigned int i = 0; i < ROWS; ++i)           // 1 <= i <= m
00091       for (unsigned int j = 0; j < COLS; ++j)           // 1 <= j <= n
00092       for (unsigned int k = 0; k < INTERNAL; ++k)       // [k = 1 to p]
00093          ret_mat( i, j ) += lhs( i, k ) * rhs( k, j );
00094 
00095       // track state
00096       ret_mat.mState = combineMatrixStates( lhs.mState, rhs.mState );
00097       return result = ret_mat;
00098    }
00099 
00105    template <typename DATA_TYPE, unsigned ROWS, unsigned INTERNAL, unsigned COLS>
00106    inline Matrix<DATA_TYPE, ROWS, COLS> operator*( const Matrix<DATA_TYPE, ROWS, INTERNAL>& lhs,
00107                                                    const Matrix<DATA_TYPE, INTERNAL, COLS>& rhs )
00108    {
00109       Matrix<DATA_TYPE, ROWS, COLS> temporary;
00110       return mult( temporary, lhs, rhs );
00111    }
00112 
00118    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00119    inline Matrix<DATA_TYPE, ROWS, COLS>& sub( Matrix<DATA_TYPE, ROWS, COLS>& result,
00120                  const Matrix<DATA_TYPE, ROWS, COLS>& lhs,
00121                  const Matrix<DATA_TYPE, ROWS, COLS>& rhs )
00122    {
00123       // p. 150 Numerical Analysis (second ed.)
00124       // if A is m x n, and B is m x n, then AB is m x n
00125       // (A - B)ij  = (a)ij - (b)ij     (where:  1 <= i <= m, 1 <= j <= n)
00126       for (unsigned int i = 0; i < ROWS; ++i)           // 1 <= i <= m
00127       for (unsigned int j = 0; j < COLS; ++j)           // 1 <= j <= n
00128          result( i, j ) = lhs( i, j ) - rhs( i, j );
00129 
00130       // track state
00131       result.mState = combineMatrixStates( lhs.mState, rhs.mState );
00132       return result;
00133    }
00134 
00140    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00141    inline Matrix<DATA_TYPE, ROWS, COLS>& add( Matrix<DATA_TYPE, ROWS, COLS>& result,
00142                  const Matrix<DATA_TYPE, ROWS, COLS>& lhs,
00143                  const Matrix<DATA_TYPE, ROWS, COLS>& rhs )
00144    {
00145       // p. 150 Numerical Analysis (second ed.)
00146       // if A is m x n, and B is m x n, then AB is m x n
00147       // (A - B)ij  = (a)ij + (b)ij     (where:  1 <= i <= m, 1 <= j <= n)
00148       for (unsigned int i = 0; i < ROWS; ++i)           // 1 <= i <= m
00149       for (unsigned int j = 0; j < COLS; ++j)           // 1 <= j <= n
00150          result( i, j ) = lhs( i, j ) + rhs( i, j );
00151 
00152       // track state
00153       result.mState = combineMatrixStates( lhs.mState, rhs.mState );
00154       return result;
00155    }
00156 
00161    template <typename DATA_TYPE, unsigned SIZE>
00162    inline Matrix<DATA_TYPE, SIZE, SIZE>& postMult( Matrix<DATA_TYPE, SIZE, SIZE>& result,
00163                                                      const Matrix<DATA_TYPE, SIZE, SIZE>& operand )
00164    {
00165       return mult( result, result, operand );
00166    }
00167 
00172    template <typename DATA_TYPE, unsigned SIZE>
00173    inline Matrix<DATA_TYPE, SIZE, SIZE>& preMult( Matrix<DATA_TYPE, SIZE, SIZE>& result,
00174                                                   const Matrix<DATA_TYPE, SIZE, SIZE>& operand )
00175    {
00176       return mult( result, operand, result );
00177    }
00178 
00184    template <typename DATA_TYPE, unsigned SIZE>
00185    inline Matrix<DATA_TYPE, SIZE, SIZE>& operator*=( Matrix<DATA_TYPE, SIZE, SIZE>& result,
00186                                                      const Matrix<DATA_TYPE, SIZE, SIZE>& operand )
00187    {
00188       return postMult( result, operand );
00189    }
00190 
00195    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00196    inline Matrix<DATA_TYPE, ROWS, COLS>& mult( Matrix<DATA_TYPE, ROWS, COLS>& result, const Matrix<DATA_TYPE, ROWS, COLS>& mat, const DATA_TYPE& scalar )
00197    {
00198       for (unsigned i = 0; i < ROWS * COLS; ++i)
00199          result.mData[i] = mat.mData[i] * scalar;
00200       result.mState = mat.mState;
00201       return result;
00202    }
00203 
00208    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00209    inline Matrix<DATA_TYPE, ROWS, COLS>& mult( Matrix<DATA_TYPE, ROWS, COLS>& result, DATA_TYPE scalar )
00210    {
00211       for (unsigned i = 0; i < ROWS * COLS; ++i)
00212          result.mData[i] *= scalar;
00213       return result;
00214    }
00215 
00220    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00221    inline Matrix<DATA_TYPE, ROWS, COLS>& operator*=( Matrix<DATA_TYPE, ROWS, COLS>& result, const DATA_TYPE& scalar )
00222    {
00223       return mult( result, scalar );
00224    }
00225 
00230    template <typename DATA_TYPE, unsigned SIZE>
00231    Matrix<DATA_TYPE, SIZE, SIZE>& transpose( Matrix<DATA_TYPE, SIZE, SIZE>& result )
00232    {
00233       // p. 27 game programming gems #1
00234       for (unsigned c = 0; c < SIZE; ++c)
00235          for (unsigned r = c + 1; r < SIZE; ++r)
00236             std::swap( result( r, c ), result( c, r ) );
00237 
00238       return result;
00239    }
00240 
00245    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00246    Matrix<DATA_TYPE, ROWS, COLS>& transpose( Matrix<DATA_TYPE, ROWS, COLS>& result, const Matrix<DATA_TYPE, COLS, ROWS>& source )
00247    {
00248       // in case result is == source... :(
00249       Matrix<DATA_TYPE, COLS, ROWS> temp = source;
00250 
00251       // p. 149 Numerical Analysis (second ed.)
00252       for (unsigned i = 0; i < ROWS; ++i)
00253       {
00254          for (unsigned j = 0; j < COLS; ++j)
00255          {
00256             result( i, j ) = temp( j, i );
00257          }
00258       }
00259       result.mState = temp.mState;
00260       return result;
00261    }
00262 
00270    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00271    inline Matrix<DATA_TYPE, ROWS, COLS>& invertTrans( Matrix<DATA_TYPE, ROWS, COLS>& result,
00272                                                        const Matrix<DATA_TYPE, ROWS, COLS>& src )
00273    {
00274       gmtlASSERT( ROWS == COLS || COLS == ROWS+1 && "invertTrans supports NxN or Nx(N-1) matrices only" );
00275 
00276       if (&result != &src)
00277          result = src; // could optimise this a little more (skip the trans copy), favor simplicity for now...
00278       for (unsigned x = 0; x < (ROWS-1+(COLS-ROWS)); ++x)
00279       {
00280          result[x][3] = -result[x][3];
00281       }
00282       return result;
00283    }
00284 
00292    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00293    inline Matrix<DATA_TYPE, ROWS, COLS>& invertOrthogonal( Matrix<DATA_TYPE, ROWS, COLS>& result,
00294                                                        const Matrix<DATA_TYPE, ROWS, COLS>& src )
00295    {
00296       // in case result is == source... :(
00297       Matrix<DATA_TYPE, ROWS, COLS> temp = src;
00298 
00299       // if 3x4, 2x3, etc...  can't transpose the last column
00300       const unsigned int size = Math::Min( ROWS, COLS );
00301 
00302       // p. 149 Numerical Analysis (second ed.)
00303       for (unsigned i = 0; i < size; ++i)
00304       {
00305          for (unsigned j = 0; j < size; ++j)
00306          {
00307             result( i, j ) = temp( j, i );
00308          }
00309       }
00310       result.mState = temp.mState;
00311       return result;
00312    }
00313 
00321    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00322    inline Matrix<DATA_TYPE, ROWS, COLS>& invertAffine( Matrix<DATA_TYPE, ROWS, COLS>& result,
00323                                                        const Matrix<DATA_TYPE, ROWS, COLS>& source )
00324    {
00325       static const float eps = 0.00000001f;
00326 
00327       // in case &result is == &source... :(
00328       Matrix<DATA_TYPE, ROWS, COLS> src = source;
00329 
00330       // The rotational part of the matrix is simply the transpose of the
00331       // original matrix.
00332       for (int x = 0; x < 3; ++x)
00333       for (int y = 0; y < 3; ++y)
00334       {
00335          result[x][y] = src[y][x];
00336       }
00337 
00338       // do non-uniform scale inversion
00339       if (src.mState & Matrix<DATA_TYPE, ROWS, COLS>::NON_UNISCALE)
00340       {
00341          DATA_TYPE l0 = gmtl::lengthSquared( gmtl::Vec<DATA_TYPE, 3>( result[0][0], result[0][1], result[0][2] ) );
00342          DATA_TYPE l1 = gmtl::lengthSquared( gmtl::Vec<DATA_TYPE, 3>( result[1][0], result[1][1], result[1][2] ) );
00343          DATA_TYPE l2 = gmtl::lengthSquared( gmtl::Vec<DATA_TYPE, 3>( result[2][0], result[2][1], result[2][2] ) );
00344          if (gmtl::Math::abs( l0 ) > eps) l0 = 1.0f / l0;
00345          if (gmtl::Math::abs( l1 ) > eps) l1 = 1.0f / l1;
00346          if (gmtl::Math::abs( l2 ) > eps) l2 = 1.0f / l2;
00347          // apply the inverse scale to the 3x3
00348          // for each axis: normalize it (1/length), and then mult by inverse scale (1/length)
00349          result[0][0] *= l0;
00350          result[0][1] *= l0;
00351          result[0][2] *= l0;
00352          result[1][0] *= l1;
00353          result[1][1] *= l1;
00354          result[1][2] *= l1;
00355          result[2][0] *= l2;
00356          result[2][1] *= l2;
00357          result[2][2] *= l2;
00358       }
00359 
00360       // handle matrices with translation
00361       if (COLS == 4)
00362       {
00363          // The right column vector of the matrix should always be [ 0 0 0 s ]
00364          // this represents some shear values
00365          result[3][0] = result[3][1] = result[3][2] = 0;
00366 
00367          // The translation components of the original matrix.
00368          const DATA_TYPE& tx = src[0][3];
00369          const DATA_TYPE& ty = src[1][3];
00370          const DATA_TYPE& tz = src[2][3];
00371 
00372 
00373          // Rresult = -(Tm * Rm) to get the translation part of the inverse
00374          if (ROWS == 4)
00375          {
00376             // invert scale.
00377             const DATA_TYPE tw = (gmtl::Math::abs( src[3][3] ) > eps) ? 1.0f / src[3][3] : 0.0f;
00378 
00379             // handle uniform scale in Nx4 matrices
00380             result[0][3] = -( result[0][0] * tx + result[0][1] * ty + result[0][2] * tz ) * tw;
00381             result[1][3] = -( result[1][0] * tx + result[1][1] * ty + result[1][2] * tz ) * tw;
00382             result[2][3] = -( result[2][0] * tx + result[2][1] * ty + result[2][2] * tz ) * tw;
00383             result[3][3] = tw;
00384          }
00385          else if (ROWS == 3)
00386          {
00387             result[0][3] = -( result[0][0] * tx + result[0][1] * ty + result[0][2] * tz );
00388             result[1][3] = -( result[1][0] * tx + result[1][1] * ty + result[1][2] * tz );
00389             result[2][3] = -( result[2][0] * tx + result[2][1] * ty + result[2][2] * tz );
00390          }
00391       }
00392 
00393 
00394 
00395       result.mState = src.mState;
00396 
00397       return result;
00398    }
00399 
00405    template <typename DATA_TYPE, unsigned SIZE>
00406    inline Matrix<DATA_TYPE, SIZE, SIZE>& invertFull_GJ( Matrix<DATA_TYPE, SIZE, SIZE>& result, const Matrix<DATA_TYPE, SIZE, SIZE>& src )
00407    {
00408       //gmtlASSERT( ROWS == COLS && "invertFull only works with nxn matrices" );
00409 
00410       const DATA_TYPE pivot_eps(1e-20);         // Epsilon for the pivot value test (delta with test against zero)
00411 
00412       // Computer inverse of matrix using a Gaussian-Jordan elimination.
00413       // Uses max pivot at each point
00414       // See: "Essential Mathmatics for Games" for description
00415 
00416       // Do this invert in place
00417       result = src;
00418       unsigned swapped[SIZE];       // Track swaps. swapped[3] = 2 means that row 3 was swapped with row 2
00419 
00420       unsigned pivot;
00421 
00422       // --- Gaussian elimination step --- //
00423       // For each column and row
00424       for(pivot=0; pivot<SIZE;++pivot)
00425       {
00426          unsigned    pivot_row(pivot);
00427          DATA_TYPE   pivot_value(gmtl::Math::abs(result(pivot_row, pivot)));    // Initialize to beginning of current row
00428 
00429          // find pivot row - (max pivot element)
00430          for(unsigned pr=pivot+1;pr<SIZE;++pr)
00431          {
00432             const DATA_TYPE cur_val(gmtl::Math::abs(result(pr,pivot)));   // get value at current point
00433             if (cur_val > pivot_value)
00434             {
00435                pivot_row = pr;
00436                pivot_value = cur_val;
00437             }
00438          }
00439 
00440          if(gmtl::Math::isEqual(DATA_TYPE(0),pivot_value,pivot_eps))
00441          {
00442             std::cerr << "*** pivot = " << pivot_value << " in mat_inv. ***\n";
00443             result.setError();
00444             return result;
00445          }
00446 
00447          // Check for swap of pivot rows
00448          swapped[pivot] = pivot_row;
00449          if(pivot_row != pivot)
00450          {
00451             for(unsigned c=0;c<SIZE;++c)
00452             {  std::swap(result(pivot,c), result(pivot_row,c)); }
00453          }
00454          // ASSERT: row to use in now in "row" (check that row starts with max pivot value found)
00455          gmtlASSERT(gmtl::Math::isEqual(pivot_value,gmtl::Math::abs(result(pivot,pivot)),DATA_TYPE(0.00001)));
00456 
00457          // Compute pivot factor
00458          const DATA_TYPE mult_factor(1.0f/pivot_value);
00459 
00460          // Set pivot row values
00461          for(unsigned c=0;c<SIZE;++c)
00462          {  result(pivot,c) *= mult_factor; }
00463          result(pivot,pivot) = mult_factor;    // Copy the 1/pivot since we are inverting in place
00464 
00465          // Clear pivot column in other rows (since we are in place)
00466          // - Subtract current row times result(r,col) so that column element becomes 0
00467          for(unsigned row=0;row<SIZE;++row)
00468          {
00469             if(row==pivot)     // Don't subtract from our row
00470             { continue; }
00471 
00472             const DATA_TYPE sub_mult_factor(result(row,pivot));
00473 
00474             // Clear the pivot column's element (for invers in place)
00475             // ends up being set to -sub_mult_factor*pivotInverse
00476             result(row,pivot) = 0;
00477 
00478             // subtract the pivot row from this row
00479             for(unsigned col=0;col<SIZE;++col)
00480             {   result(row,col) -= (sub_mult_factor*result(pivot,col)); }
00481          }
00482       } // end: gaussian substitution
00483 
00484 
00485       // Now undo the swaps in column direction in reverse order
00486       unsigned p(SIZE);
00487       do
00488       {
00489          --p;
00490          gmtlASSERT(p<SIZE);
00491 
00492          // If row was swapped
00493          if(swapped[p] != p)
00494          {
00495             // Swap the column with same index
00496             for(unsigned r=0; r<SIZE; ++r)
00497             { std::swap(result(r, p), result(r, swapped[p])); }
00498          }
00499       }
00500       while(p>0);
00501 
00502       return result;
00503    }
00504 
00505 
00511    template <typename DATA_TYPE, unsigned SIZE>
00512    inline Matrix<DATA_TYPE, SIZE, SIZE>& invertFull_orig( Matrix<DATA_TYPE, SIZE, SIZE>& result, const Matrix<DATA_TYPE, SIZE, SIZE>& src )
00513    {
00514       /*---------------------------------------------------------------------------*
00515        | mat_inv: Compute the inverse of a n x n matrix, using the maximum pivot   |
00516        |          strategy.  n <= MAX1.                                            |
00517        *---------------------------------------------------------------------------*
00518 
00519          Parameters:
00520              a        a n x n square matrix
00521              b        inverse of input a.
00522              n        dimenstion of matrix a.
00523       */
00524 
00525       const DATA_TYPE* a = src.getData();
00526       DATA_TYPE* b = result.mData;
00527 
00528       int   n(SIZE);
00529       int    i, j, k;
00530       int    r[SIZE], c[SIZE], row[SIZE], col[SIZE];
00531       DATA_TYPE  m[SIZE][SIZE*2], pivot, max_m, tmp_m, fac;
00532 
00533       /* Initialization */
00534       for ( i = 0; i < n; i ++ )
00535       {
00536          r[ i] = c[ i] = 0;
00537          row[ i] = col[ i] = 0;
00538       }
00539 
00540       /* Set working matrix */
00541       for ( i = 0; i < n; i++ )
00542       {
00543          for ( j = 0; j < n; j++ )
00544          {
00545             m[ i][ j] = a[ i * n + j];
00546             m[ i][ j + n] = ( i == j ) ? (DATA_TYPE)1.0 : (DATA_TYPE)0.0 ;
00547          }
00548       }
00549 
00550       /* Begin of loop */
00551       for ( k = 0; k < n; k++ )
00552       {
00553          /* Choosing the pivot */
00554          for ( i = 0, max_m = 0; i < n; i++ )
00555          {
00556             if ( row[ i]  )
00557                continue;
00558             for ( j = 0; j < n; j++ )
00559             {
00560                if ( col[ j] )
00561                   continue;
00562                tmp_m = gmtl::Math::abs( m[ i][ j]);
00563                if ( tmp_m > max_m)
00564                {
00565                   max_m = tmp_m;
00566                   r[ k] = i;
00567                   c[ k] = j;
00568                }
00569             }
00570          }
00571          row[ r[k] ] = col[ c[k] ] = 1;
00572          pivot = m[ r[ k] ][ c[ k] ];
00573 
00574 
00575          if ( gmtl::Math::abs( pivot) <= 1e-20)
00576          {
00577             std::cerr << "*** pivot = " << pivot << " in mat_inv. ***\n";
00578             result.setError();
00579             return result;
00580          }
00581 
00582          /* Normalization */
00583          for ( j = 0; j < 2*n; j++ )
00584          {
00585             if ( j == c[ k] )
00586                m[ r[ k]][ j] = (DATA_TYPE)1.0;
00587             else
00588                m[ r[ k]][ j] /= pivot;
00589          }
00590 
00591          /* Reduction */
00592          for ( i = 0; i < n; i++ )
00593          {
00594             if ( i == r[ k] )
00595                continue;
00596 
00597             for ( j=0, fac = m[ i][ c[k]]; j < 2*n; j++ )
00598             {
00599                if ( j == c[ k] )
00600                   m[ i][ j] = (DATA_TYPE)0.0;
00601                else
00602                   m[ i][ j] -= fac * m[ r[k]][ j];
00603             }
00604          }
00605       }
00606 
00607       /* Assign inverse to a matrix */
00608       for ( i = 0; i < n; i++ )
00609          for ( j = 0; j < n; j++ )
00610             row[ i] = ( c[ j] == i ) ? r[ j] : row[ i];
00611 
00612       for ( i = 0; i < n; i++ )
00613          for ( j = 0; j < n; j++ )
00614             b[ i * n +  j] = m[ row[ i]][ j + n];
00615 
00616       // It worked
00617       result.mState = src.mState;
00618       return result;
00619    }
00620 
00621 
00625    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00626    inline Matrix<DATA_TYPE, ROWS, COLS>& invertFull( Matrix<DATA_TYPE, ROWS, COLS>& result, const Matrix<DATA_TYPE, ROWS, COLS>& src )
00627    {
00628       return invertFull_orig(result,src);
00629    }
00630 
00641    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00642    inline Matrix<DATA_TYPE, ROWS, COLS>& invert( Matrix<DATA_TYPE, ROWS, COLS>& result, const Matrix<DATA_TYPE, ROWS, COLS>& src )
00643    {
00644       if (src.mState == Matrix<DATA_TYPE, ROWS, COLS>::IDENTITY )
00645          return result = src;
00646       else if (src.mState == Matrix<DATA_TYPE, ROWS, COLS>::TRANS)
00647          return invertTrans( result, src );
00648       else if (src.mState == Matrix<DATA_TYPE, ROWS, COLS>::ORTHOGONAL)
00649          return invertOrthogonal( result, src );
00650       else if (src.mState == Matrix<DATA_TYPE, ROWS, COLS>::AFFINE ||
00651                src.mState == (Matrix<DATA_TYPE, ROWS, COLS>::AFFINE | Matrix<DATA_TYPE, ROWS, COLS>::NON_UNISCALE))
00652          return invertAffine( result, src );
00653       else
00654          return invertFull_orig( result, src );
00655    }
00656 
00667    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00668    inline Matrix<DATA_TYPE, ROWS, COLS>& invert( Matrix<DATA_TYPE, ROWS, COLS>& result )
00669    {
00670       return invert( result, result );
00671    }
00672 
00686    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00687    inline bool operator==( const Matrix<DATA_TYPE, ROWS, COLS>& lhs, const Matrix<DATA_TYPE, ROWS, COLS>& rhs )
00688    {
00689       for (unsigned int i = 0; i < ROWS*COLS; ++i)
00690       {
00691          if (lhs.mData[i] != rhs.mData[i])
00692          {
00693             return false;
00694          }
00695       }
00696 
00697       return true;
00698 
00699       /*  Would like this
00700       return( lhs[0] == rhs[0] &&
00701               lhs[1] == rhs[1] &&
00702               lhs[2] == rhs[2] );
00703       */
00704    }
00705 
00712    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00713    inline bool operator!=( const Matrix<DATA_TYPE, ROWS, COLS>& lhs, const Matrix<DATA_TYPE, ROWS, COLS>& rhs )
00714    {
00715       return bool( !(lhs == rhs) );
00716    }
00717 
00725    template <typename DATA_TYPE, unsigned ROWS, unsigned COLS>
00726    inline bool isEqual( const Matrix<DATA_TYPE, ROWS, COLS>& lhs, const Matrix<DATA_TYPE, ROWS, COLS>& rhs, const DATA_TYPE eps = 0 )
00727    {
00728       gmtlASSERT( eps >= (DATA_TYPE)0 );
00729 
00730       for (unsigned int i = 0; i < ROWS*COLS; ++i)
00731       {
00732          if (!Math::isEqual( lhs.mData[i], rhs.mData[i], eps ))
00733             return false;
00734       }
00735       return true;
00736    }
00739 } // end of namespace gmtl
00740 
00741 #endif

Generated on Sun Sep 19 2010 14:35:14 for GenericMathTemplateLibrary by  doxygen 1.7.1