00001
00002
00003
00004
00005
00006 #ifndef _GMTL_MATRIXOPS_H_
00007 #define _GMTL_MATRIXOPS_H_
00008
00009 #include <iostream>
00010 #include <algorithm>
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)
00031 {
00032
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
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
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;
00085 zero( ret_mat );
00086
00087
00088
00089
00090 for (unsigned int i = 0; i < ROWS; ++i)
00091 for (unsigned int j = 0; j < COLS; ++j)
00092 for (unsigned int k = 0; k < INTERNAL; ++k)
00093 ret_mat( i, j ) += lhs( i, k ) * rhs( k, j );
00094
00095
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
00124
00125
00126 for (unsigned int i = 0; i < ROWS; ++i)
00127 for (unsigned int j = 0; j < COLS; ++j)
00128 result( i, j ) = lhs( i, j ) - rhs( i, j );
00129
00130
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
00146
00147
00148 for (unsigned int i = 0; i < ROWS; ++i)
00149 for (unsigned int j = 0; j < COLS; ++j)
00150 result( i, j ) = lhs( i, j ) + rhs( i, j );
00151
00152
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
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
00249 Matrix<DATA_TYPE, COLS, ROWS> temp = source;
00250
00251
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;
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
00297 Matrix<DATA_TYPE, ROWS, COLS> temp = src;
00298
00299
00300 const unsigned int size = Math::Min( ROWS, COLS );
00301
00302
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
00328 Matrix<DATA_TYPE, ROWS, COLS> src = source;
00329
00330
00331
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
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
00348
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
00361 if (COLS == 4)
00362 {
00363
00364
00365 result[3][0] = result[3][1] = result[3][2] = 0;
00366
00367
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
00374 if (ROWS == 4)
00375 {
00376
00377 const DATA_TYPE tw = (gmtl::Math::abs( src[3][3] ) > eps) ? 1.0f / src[3][3] : 0.0f;
00378
00379
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
00409
00410 const DATA_TYPE pivot_eps(1e-20);
00411
00412
00413
00414
00415
00416
00417 result = src;
00418 unsigned swapped[SIZE];
00419
00420 unsigned pivot;
00421
00422
00423
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)));
00428
00429
00430 for(unsigned pr=pivot+1;pr<SIZE;++pr)
00431 {
00432 const DATA_TYPE cur_val(gmtl::Math::abs(result(pr,pivot)));
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
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
00455 gmtlASSERT(gmtl::Math::isEqual(pivot_value,gmtl::Math::abs(result(pivot,pivot)),DATA_TYPE(0.00001)));
00456
00457
00458 const DATA_TYPE mult_factor(1.0f/pivot_value);
00459
00460
00461 for(unsigned c=0;c<SIZE;++c)
00462 { result(pivot,c) *= mult_factor; }
00463 result(pivot,pivot) = mult_factor;
00464
00465
00466
00467 for(unsigned row=0;row<SIZE;++row)
00468 {
00469 if(row==pivot)
00470 { continue; }
00471
00472 const DATA_TYPE sub_mult_factor(result(row,pivot));
00473
00474
00475
00476 result(row,pivot) = 0;
00477
00478
00479 for(unsigned col=0;col<SIZE;++col)
00480 { result(row,col) -= (sub_mult_factor*result(pivot,col)); }
00481 }
00482 }
00483
00484
00485
00486 unsigned p(SIZE);
00487 do
00488 {
00489 --p;
00490 gmtlASSERT(p<SIZE);
00491
00492
00493 if(swapped[p] != p)
00494 {
00495
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
00516
00517
00518
00519
00520
00521
00522
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
00534 for ( i = 0; i < n; i ++ )
00535 {
00536 r[ i] = c[ i] = 0;
00537 row[ i] = col[ i] = 0;
00538 }
00539
00540
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
00551 for ( k = 0; k < n; k++ )
00552 {
00553
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
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
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
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
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
00700
00701
00702
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 }
00740
00741 #endif