OpenWalnut  1.4.0
WMatrixFixed_test.h
00001 //---------------------------------------------------------------------------
00002 //
00003 // Project: OpenWalnut ( http://www.openwalnut.org )
00004 //
00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
00006 // For more information see http://www.openwalnut.org/copying
00007 //
00008 // This file is part of OpenWalnut.
00009 //
00010 // OpenWalnut is free software: you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as published by
00012 // the Free Software Foundation, either version 3 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // OpenWalnut is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public License
00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
00022 //
00023 //---------------------------------------------------------------------------
00024 
00025 #ifndef WMATRIXFIXED_TEST_H
00026 #define WMATRIXFIXED_TEST_H
00027 
00028 #include <cxxtest/TestSuite.h>
00029 
00030 #include <boost/array.hpp>
00031 
00032 #include "../WMatrixFixed.h"
00033 #include "../WVectorFixed.h"
00034 
00035 /**
00036  * Tests for WMatrixFixed.
00037  */
00038 class WMatrixFixedTest : public CxxTest::TestSuite
00039 {
00040 public:
00041     /**
00042      * Instantiation should throw nothing.
00043      */
00044     void testInstantiation( void )
00045     {
00046         typedef WMatrixFixed< double, 3, 2 > WMD32;
00047         typedef WMatrixFixed< float, 3, 2 > WMF32;
00048         typedef WMatrixFixed< double, 1, 1 > WMD11;
00049         typedef WMatrixFixed< float, 1, 1 > WMF11;
00050         typedef WMatrixFixed< double, 4, 4 > WMD44;
00051         typedef WMatrixFixed< float, 4, 4 > WMF44;
00052         typedef WMatrixFixed< int, 3, 2 > WMI32;
00053         typedef WMatrixFixed< std::size_t, 3, 2 > WMS32;
00054 
00055         TS_ASSERT_THROWS_NOTHING( WMD32 matrix() );
00056         TS_ASSERT_THROWS_NOTHING( WMF32 matrix() );
00057         TS_ASSERT_THROWS_NOTHING( WMD11 matrix() );
00058         TS_ASSERT_THROWS_NOTHING( WMF11 matrix() );
00059         TS_ASSERT_THROWS_NOTHING( WMD44 matrix() );
00060         TS_ASSERT_THROWS_NOTHING( WMF44 matrix() );
00061         TS_ASSERT_THROWS_NOTHING( WMI32 matrix() );
00062         TS_ASSERT_THROWS_NOTHING( WMS32 matrix() );
00063     }
00064 
00065     /**
00066      * Instantiation with copy constructor should throw nothing.
00067      */
00068     void testCopyInstantiation( void )
00069     {
00070         typedef WMatrixFixed< double, 3, 2 > WMD32;
00071         WMD32 matrix;
00072         TS_ASSERT_THROWS_NOTHING( WMD32 matrix2( matrix ) );
00073 
00074         typedef WMatrixFixed< double, 1, 1 > WMD11;
00075         WMD11 scalar;
00076         TS_ASSERT_THROWS_NOTHING( WMD11 scalar2( scalar ) );
00077 
00078         typedef WMatrixFixed< double, 1, 3 > WMD13;
00079         WMD13 vector;
00080         TS_ASSERT_THROWS_NOTHING( WMD13 vector2( vector ) );
00081 
00082         // access operator is tested in another place
00083         WMatrixFixed< int, 3, 3 > mat;
00084         mat( 0, 0 ) = 1;
00085         mat( 0, 1 ) = 2;
00086         mat( 0, 2 ) = 3;
00087         mat( 1, 0 ) = 4;
00088         mat( 1, 1 ) = 5;
00089         mat( 1, 2 ) = 6;
00090         mat( 2, 0 ) = 7;
00091         mat( 2, 1 ) = 8;
00092         mat( 2, 2 ) = 9;
00093 
00094         WMatrixFixed< int, 3, 3 > mat2( mat );
00095         for( std::size_t i = 0; i < 3; ++i )
00096         {
00097             for( std::size_t j = 0; j < 3; ++j )
00098             {
00099                 TS_ASSERT_EQUALS( mat( i, j ), mat2( i, j ) );
00100             }
00101         }
00102     }
00103 
00104     /**
00105      * Number of rows and columns should be returned correctly.
00106      */
00107     void testGetNbRowsAndCols( void )
00108     {
00109         const size_t nbRows = 3, nbCols = 2;
00110         WMatrixFixed< double, 3, 2 > matrix;
00111         TS_ASSERT_EQUALS( matrix.getRows(), nbRows );
00112         TS_ASSERT_EQUALS( matrix.getColumns(), nbCols );
00113     }
00114 
00115     /**
00116      * Tests the access operator for the standard storage type. Row major storage is assumed.
00117      */
00118     void testAccessOperator()
00119     {
00120         WMatrixFixed< int, 3, 3 > matrix;
00121         matrix( 0, 0 ) = 1;
00122         matrix( 0, 1 ) = 2;
00123         matrix( 0, 2 ) = 3;
00124         matrix( 1, 0 ) = 4;
00125         matrix( 1, 1 ) = 5;
00126         matrix( 1, 2 ) = 6;
00127         matrix( 2, 0 ) = 7;
00128         matrix( 2, 1 ) = 8;
00129         matrix( 2, 2 ) = 9;
00130 
00131         for( int i = 0; i < 9; ++i )
00132         {
00133             TS_ASSERT_EQUALS( matrix.m_values.m_values[ i ], i + 1 );
00134         }
00135     }
00136 
00137     /**
00138      * Check if at() correctly checks for out of bounds indices and returns
00139      * the same values as operator ().
00140      */
00141     void testAt()
00142     {
00143         WMatrixFixed< int, 3, 4 > matrix;
00144         matrix( 0, 0 ) = 1;
00145         matrix( 0, 1 ) = 2;
00146         matrix( 0, 2 ) = 3;
00147         matrix( 1, 0 ) = 4;
00148         matrix( 1, 1 ) = 5;
00149         matrix( 1, 2 ) = 6;
00150         matrix( 2, 0 ) = 7;
00151         matrix( 2, 1 ) = 8;
00152         matrix( 2, 2 ) = 9;
00153 
00154         matrix( 0, 3 ) = 10;
00155         matrix( 1, 3 ) = 11;
00156         matrix( 2, 3 ) = 12;
00157 
00158         for( std::size_t i = 0; i < 3; ++i )
00159         {
00160             for( std::size_t j = 0; j < 4; ++j )
00161             {
00162                 TS_ASSERT_EQUALS( matrix( i, j ), matrix.at( i, j ) );
00163             }
00164         }
00165 
00166         TS_ASSERT_THROWS( matrix.at( 0, 4 ), WOutOfBounds );
00167         TS_ASSERT_THROWS( matrix.at( 1, 5 ), WOutOfBounds );
00168         TS_ASSERT_THROWS( matrix.at( 1, 4 ), WOutOfBounds );
00169         TS_ASSERT_THROWS( matrix.at( 1, 100000 ), WOutOfBounds );
00170         TS_ASSERT_THROWS( matrix.at( 3, 1 ), WOutOfBounds );
00171         TS_ASSERT_THROWS( matrix.at( -1, 0 ), WOutOfBounds );
00172     }
00173 
00174     /**
00175      * Check if getRowVector() returns the correct contents.
00176      */
00177     void testGetRowVector()
00178     {
00179         WMatrixFixed< int, 3, 3 > matrix;
00180         matrix( 0, 0 ) = 1;
00181         matrix( 0, 1 ) = 2;
00182         matrix( 0, 2 ) = 3;
00183         matrix( 1, 0 ) = 4;
00184         matrix( 1, 1 ) = 5;
00185         matrix( 1, 2 ) = 6;
00186         matrix( 2, 0 ) = 7;
00187         matrix( 2, 1 ) = 8;
00188         matrix( 2, 2 ) = 9;
00189 
00190         WMatrixFixed< int, 3, 1 > rowVector;
00191         rowVector( 0, 0 ) = matrix( 0, 0 );
00192         rowVector( 1, 0 ) = matrix( 0, 1 );
00193         rowVector( 2, 0 ) = matrix( 0, 2 );
00194 
00195         TS_ASSERT_EQUALS( matrix.getRowVector( 0 )( 0, 0 ),  rowVector( 0, 0 ) );
00196         TS_ASSERT_EQUALS( matrix.getRowVector( 0 )( 0, 1 ),  rowVector( 1, 0 ) );
00197         TS_ASSERT_EQUALS( matrix.getRowVector( 0 )( 0, 2 ),  rowVector( 2, 0 ) );
00198     }
00199 
00200     /**
00201      * Check if getColumnVector() returns the correct contents.
00202      */
00203     void testGetColVector()
00204     {
00205         WMatrixFixed< int, 3, 3 > matrix;
00206         matrix( 0, 0 ) = 1;
00207         matrix( 0, 1 ) = 2;
00208         matrix( 0, 2 ) = 3;
00209         matrix( 1, 0 ) = 4;
00210         matrix( 1, 1 ) = 5;
00211         matrix( 1, 2 ) = 6;
00212         matrix( 2, 0 ) = 7;
00213         matrix( 2, 1 ) = 8;
00214         matrix( 2, 2 ) = 9;
00215 
00216         WMatrixFixed< int, 3, 1 > colVector;
00217         colVector( 0, 0 ) = matrix( 0, 1 );
00218         colVector( 1, 0 ) = matrix( 1, 1 );
00219         colVector( 2, 0 ) = matrix( 2, 1 );
00220 
00221         TS_ASSERT_EQUALS( matrix.getColumnVector( 1 )( 0, 0 ), colVector.at( 0, 0 ) );
00222         TS_ASSERT_EQUALS( matrix.getColumnVector( 1 )( 1, 0 ), colVector.at( 1, 0 ) );
00223         TS_ASSERT_EQUALS( matrix.getColumnVector( 1 )( 2, 0 ), colVector.at( 2, 0 ) );
00224     }
00225 
00226     /**
00227      * Check if setRowVector() sets the matrix contents correctly.
00228      */
00229     void testSetRowVector()
00230     {
00231         WMatrixFixed< int, 3, 1 > rowVector;
00232         rowVector( 0, 0 ) = 1;
00233         rowVector( 1, 0 ) = 2;
00234         rowVector( 2, 0 ) = 3;
00235 
00236         WMatrixFixed< int, 3, 3 > matrix;
00237         matrix.setRowVector( 0, rowVector );
00238 
00239         TS_ASSERT_EQUALS( matrix( 0, 0 ), rowVector( 0, 0 ) );
00240         TS_ASSERT_EQUALS( matrix( 0, 1 ), rowVector( 1, 0 ) );
00241         TS_ASSERT_EQUALS( matrix( 0, 2 ), rowVector( 2, 0 ) );
00242     }
00243 
00244     /**
00245      * Check if setColumnVector() sets the matrix contents correctly.
00246      */
00247     void testSetColVector()
00248     {
00249         WMatrixFixed< int, 3, 1 > colVector;
00250         colVector( 0, 0 ) = 2;
00251         colVector( 1, 0 ) = 5;
00252         colVector( 2, 0 ) = 8;
00253 
00254         WMatrixFixed< int, 3, 3 > matrix;
00255         matrix.setColumnVector( 1, colVector );
00256 
00257         TS_ASSERT_EQUALS( matrix( 0, 1 ), colVector( 0, 0 ) );
00258         TS_ASSERT_EQUALS( matrix( 1, 1 ), colVector( 1, 0 ) );
00259         TS_ASSERT_EQUALS( matrix( 2, 1 ), colVector( 2, 0 ) );
00260     }
00261 
00262     /**
00263      * The zero function should return a matrix that contains only zeros.
00264      */
00265     void testZero()
00266     {
00267         typedef WMatrixFixed< double, 1, 3 > WMD13;
00268         TS_ASSERT_EQUALS( WMD13::zero()( 0, 0 ), 0.0 );
00269         TS_ASSERT_EQUALS( WMD13::zero()( 0, 1 ), 0.0 );
00270         TS_ASSERT_EQUALS( WMD13::zero()( 0, 2 ), 0.0 );
00271 
00272         typedef WMatrixFixed< unsigned char, 2, 2 > WMU32;
00273         TS_ASSERT_EQUALS( WMU32::zero()( 0, 0 ), 0 );
00274         TS_ASSERT_EQUALS( WMU32::zero()( 0, 1 ), 0 );
00275         TS_ASSERT_EQUALS( WMU32::zero()( 1, 0 ), 0 );
00276         TS_ASSERT_EQUALS( WMU32::zero()( 1, 1 ), 0 );
00277     }
00278 
00279     /**
00280      * Tests the identity function.
00281      */
00282     void testIdentity()
00283     {
00284         typedef WMatrixFixed< unsigned char, 4, 5 > WMU45;
00285         typedef WMatrixFixed< unsigned char, 5, 4 > WMU54;
00286 
00287         // rows < cols
00288         for( int i = 0; i < 4; i++ )
00289         {
00290             for( int j = 0; j < 5; ++j )
00291             {
00292                 if( i == j )
00293                 {
00294                     TS_ASSERT_EQUALS( WMU45::identity()( i, j ), 1 );
00295                 }
00296                 else
00297                 {
00298                     TS_ASSERT_EQUALS( WMU45::identity()( i, j ), 0 );
00299                 }
00300             }
00301         }
00302 
00303         // rows > cols
00304         for( int i = 0; i < 5; i++ )
00305         {
00306             for( int j = 0; j < 4; ++j )
00307             {
00308                 if( i == j )
00309                 {
00310                     TS_ASSERT_EQUALS( WMU54::identity()( i, j ), 1 );
00311                 }
00312                 else
00313                 {
00314                     TS_ASSERT_EQUALS( WMU54::identity()( i, j ), 0 );
00315                 }
00316             }
00317         }
00318     }
00319 
00320     /**
00321      * Assignment from matrices with matching or different integral types should work correctly.
00322      */
00323     void testAssignmentMatchingOrDifferentType()
00324     {
00325         // matching type
00326         {
00327             WMatrixFixed< double, 3, 3 > matrix2;
00328             matrix2 = m_matrix;
00329             for( std::size_t i = 0; i < 3; ++i )
00330             {
00331                 for( std::size_t j = 0; j < 3; ++j )
00332                 {
00333                     TS_ASSERT_EQUALS( m_matrix( i, j ), matrix2( i, j ) );
00334                 }
00335             }
00336         }
00337         // differing type
00338         {
00339             WMatrixFixed< int, 3, 3 > matrix2;
00340             matrix2 = m_matrix;
00341 
00342             TS_ASSERT_EQUALS( matrix2( 0, 0 ), 1 );
00343             TS_ASSERT_EQUALS( matrix2( 0, 1 ), 0.0 );
00344             TS_ASSERT_EQUALS( matrix2( 0, 2 ), 3 );
00345             TS_ASSERT_EQUALS( matrix2( 1, 0 ), 4000 );
00346             TS_ASSERT_EQUALS( matrix2( 1, 1 ), 5 );
00347             TS_ASSERT_EQUALS( matrix2( 1, 2 ), -5343 );
00348             TS_ASSERT_EQUALS( matrix2( 2, 0 ), 1 );
00349             TS_ASSERT_EQUALS( matrix2( 2, 1 ), 0 );
00350             TS_ASSERT_EQUALS( matrix2( 2, 2 ), 0 );
00351         }
00352     }
00353 
00354     /**
00355      * A class used for a test with different data storage, we use column major order.
00356      */
00357     template< typename ValueT, size_t Rows, size_t Cols >
00358     class DifferentStorageType
00359     {
00360     public:
00361         /**
00362          * Returns a reference to the component of an row and column in order to provide access to the component. It does not check for validity of
00363          * the indices.
00364          *
00365          * \param row the row, staring with 0
00366          * \param col the column, starting with 0
00367          *
00368          * \return A reference to the component of an row and column.
00369          */
00370         ValueT& operator()( size_t row, size_t col ) throw()
00371         {
00372             return m_values[ row + col * Rows ];
00373         }
00374 
00375         /**
00376          * Returns a const reference to the component of an row and column in order to provide access to the component.
00377          * It does not check for validity of
00378          * the indices.
00379          *
00380          * \param row the row, staring with 0
00381          * \param col the column, starting with 0
00382          *
00383          * \return A const reference to the component of an row and column.
00384          */
00385         const ValueT& operator()( size_t row, size_t col ) const throw()
00386         {
00387             return m_values[ row + col * Rows ];
00388         }
00389 
00390         /**
00391          * Replaces the values in this array.
00392          *
00393          * \tparam RHSValueT the value type. This is casted to ValueT.
00394          * \tparam RHSValueStoreT The value store given
00395          * \param rhs the values to set.
00396          *
00397          * \return this
00398          */
00399         template < typename RHSValueT, ValueStoreTemplate RHSValueStoreT >
00400         ValueStore< ValueT, Rows, Cols >& operator=( RHSValueStoreT< RHSValueT, Rows, Cols > const& rhs )
00401         {
00402             for( size_t row = 0; row < Rows; ++row )
00403             {
00404                 for( size_t col = 0; col < Cols; ++col )
00405                 {
00406                     ( row, col ) = rhs( row, col );
00407                 }
00408             }
00409         }
00410 
00411         //! The value array. Stored column-major.
00412         // this needs to be public for testing purposes
00413         boost::array< ValueT, Rows * Cols > m_values;
00414     };
00415 
00416     /**
00417      * Assignment from matrices with different storage types should work correctly.
00418      */
00419     void testAssignmentDifferentStorage()
00420     {
00421         WMatrixFixed< double, 3, 3, DifferentStorageType > matrix;
00422         matrix = m_matrix;
00423 
00424         TS_ASSERT_EQUALS( matrix.m_values.m_values[ 0 ], 1.52234 );
00425         TS_ASSERT_EQUALS( matrix.m_values.m_values[ 1 ], 4e3 );
00426         TS_ASSERT_EQUALS( matrix.m_values.m_values[ 2 ], 1 );
00427         TS_ASSERT_EQUALS( matrix.m_values.m_values[ 3 ], -0.4534 );
00428         TS_ASSERT_EQUALS( matrix.m_values.m_values[ 4 ], 5.666 );
00429         TS_ASSERT_EQUALS( matrix.m_values.m_values[ 5 ], 0 );
00430         TS_ASSERT_EQUALS( matrix.m_values.m_values[ 6 ], 3.0 );
00431         TS_ASSERT_EQUALS( matrix.m_values.m_values[ 7 ], -5343.959 );
00432         TS_ASSERT_EQUALS( matrix.m_values.m_values[ 8 ], 0.1 );
00433 
00434         for( std::size_t i = 0; i < 3; ++i )
00435         {
00436             for( std::size_t j = 0; j < 3; ++j )
00437             {
00438                 TS_ASSERT_EQUALS( matrix( i, j ), m_matrix( i, j ) );
00439             }
00440         }
00441     }
00442 
00443     /**
00444      * Test self-assignment.
00445      */
00446     void testSelfAssignment()
00447     {
00448         TS_ASSERT_THROWS_NOTHING( m_matrix = m_matrix );
00449 
00450         m_matrix = m_matrix;
00451 
00452         TS_ASSERT_EQUALS( m_matrix( 0, 0 ), 1.52234 );
00453         TS_ASSERT_EQUALS( m_matrix( 0, 1 ), -0.4534 );
00454         TS_ASSERT_EQUALS( m_matrix( 0, 2 ), 3.0 );
00455         TS_ASSERT_EQUALS( m_matrix( 1, 0 ), 4e3 );
00456         TS_ASSERT_EQUALS( m_matrix( 1, 1 ), 5.666 );
00457         TS_ASSERT_EQUALS( m_matrix( 1, 2 ), -5343.959 );
00458         TS_ASSERT_EQUALS( m_matrix( 2, 0 ), 1 );
00459         TS_ASSERT_EQUALS( m_matrix( 2, 1 ), 0 );
00460         TS_ASSERT_EQUALS( m_matrix( 2, 2 ), 0.1 );
00461     }
00462 
00463     /**
00464      * Matrices should be converted to eigen3 matrices correctly.
00465      * Conversion to eigen3 and re-conversion to WMatrix should yield the original matrix.
00466      */
00467     void testEigen3Coversion()
00468     {
00469         Eigen::Matrix< double, 3, 3 > emat = m_matrix;
00470         for( std::size_t i = 0; i < 3; ++i )
00471         {
00472             for( std::size_t j = 0; j < 3; ++j )
00473             {
00474                 TS_ASSERT_EQUALS( emat( i, j ), m_matrix( i, j ) );
00475             }
00476         }
00477 
00478         WMatrixFixed< double, 3, 3 > matrix2( emat );
00479         for( std::size_t i = 0; i < 3; ++i )
00480         {
00481             for( std::size_t j = 0; j < 3; ++j )
00482             {
00483                 TS_ASSERT_EQUALS( matrix2( i, j ), m_matrix( i, j ) );
00484             }
00485         }
00486     }
00487 
00488     /**
00489      * Test conversion between several matrix types
00490      */
00491     void testConversion()
00492     {
00493         WMatrixFixed< double, 2, 2 > md;
00494         md( 0, 0 ) = 0.0;
00495         md( 1, 0 ) = 1.0;
00496         md( 0, 1 ) = 2.0;
00497         md( 1, 1 ) = 3.0;
00498         WMatrixFixed< int, 2, 2 > mi( md );
00499 
00500         TS_ASSERT( mi( 0, 0 ) == 0 );
00501         TS_ASSERT( mi( 1, 0 ) == 1 );
00502         TS_ASSERT( mi( 0, 1 ) == 2 );
00503         TS_ASSERT( mi( 1, 1 ) == 3 );
00504     }
00505 
00506     /**
00507      * Test matrix multiplication.
00508      */
00509     void testMatrixMultiplication()
00510     {
00511         // note we do not need to check for matching number of rows/columns as this is done by the compiler
00512         typedef WMatrixFixed< int, 3, 4 > WMI34;
00513         WMI34 matrix;
00514         matrix( 0, 0 ) = 1;
00515         matrix( 0, 1 ) = 2;
00516         matrix( 0, 2 ) = 3;
00517         matrix( 0, 3 ) = -3;
00518         matrix( 1, 0 ) = 2;
00519         matrix( 1, 1 ) = -5;
00520         matrix( 1, 2 ) = 0;
00521         matrix( 1, 3 ) = 9;
00522         matrix( 2, 0 ) = 0;
00523         matrix( 2, 1 ) = 1;
00524         matrix( 2, 2 ) = 1;
00525         matrix( 2, 3 ) = 2;
00526 
00527         // matrix-vector
00528         {
00529             typedef WMatrixFixed< int, 4, 1 > WMI41;
00530             WMI41 vec;
00531             vec[ 0 ] = -1;
00532             vec[ 1 ] = 2;
00533             vec[ 2 ] = 0;
00534             vec[ 3 ] = 1;
00535 
00536             typedef WMatrixFixed< int, 4, 4 > WMI44;
00537             TS_ASSERT_EQUALS( WMI44::identity() * vec, vec );
00538             TS_ASSERT_EQUALS( WMI44::zero() * vec, WMI41::zero() );
00539 
00540             WMatrixFixed< int, 3, 1 > res = matrix * vec;
00541 
00542             TS_ASSERT_EQUALS( res[ 0 ], 0 );
00543             TS_ASSERT_EQUALS( res[ 1 ], -3 );
00544             TS_ASSERT_EQUALS( res[ 2 ], 4 );
00545         }
00546 
00547         // matrix-matrix
00548         {
00549             typedef WMatrixFixed< int, 4, 4 > WMI44;
00550 
00551             TS_ASSERT_EQUALS( WMI44::zero() * WMI44::zero(), WMI44::zero() );
00552             TS_ASSERT_EQUALS( WMI44::zero() * WMI44::identity(), WMI44::zero() );
00553             TS_ASSERT_EQUALS( WMI44::identity() * WMI44::zero(), WMI44::zero() );
00554             TS_ASSERT_EQUALS( WMI44::identity() * WMI44::identity(), WMI44::identity() );
00555 
00556             TS_ASSERT_EQUALS( matrix * WMI44::identity(), matrix );
00557             TS_ASSERT_EQUALS( matrix * WMI44::zero(), WMI34::zero() );
00558 
00559             typedef WMatrixFixed< int, 3, 3 > WMI33;
00560             WMI33 mat;
00561             mat( 0, 0 ) = mat( 2, 2 ) = 1;
00562             mat( 1, 1 ) = 0;
00563             mat( 0, 1 ) = mat( 1, 0 ) = -2;
00564             mat( 0, 2 ) = mat( 2, 0 ) = 3;
00565             mat( 1, 2 ) = mat( 2, 1 ) = 2;
00566 
00567             WMI34 res = mat * matrix;
00568             TS_ASSERT_EQUALS( res( 0, 0 ), -3 );
00569             TS_ASSERT_EQUALS( res( 1, 2 ), -4 );
00570             TS_ASSERT_EQUALS( res( 2, 0 ), 7 );
00571             TS_ASSERT_EQUALS( res( 2, 3 ), 11 );
00572             TS_ASSERT_EQUALS( res( 1, 3 ), 10 );
00573 
00574             // special test for self-assigning multiplication of a matrix with itself
00575             mat *= mat;
00576             TS_ASSERT_EQUALS( mat( 0, 0 ), 14 );
00577             TS_ASSERT_EQUALS( mat( 2, 2 ), 14 );
00578             TS_ASSERT_EQUALS( mat( 0, 1 ), 4 );
00579             TS_ASSERT_EQUALS( mat( 2, 1 ), -4 );
00580             TS_ASSERT_EQUALS( mat( 1, 2 ), -4 );
00581         }
00582     }
00583 
00584     /**
00585      * Matrix-scalar multiplication.
00586      */
00587     void testMatrixTimesScalar()
00588     {
00589         WMatrix3d mat = m_matrix * 2.0;
00590 
00591         for( int i = 0; i < 3; i++ )
00592         {
00593             for( int j = 0; j < 3; ++j )
00594             {
00595                 TS_ASSERT_EQUALS( mat( i, j ), 2 * m_matrix( i, j ) );
00596             }
00597         }
00598 
00599         mat *= 2;
00600         for( int i = 0; i < 3; i++ )
00601         {
00602             for( int j = 0; j < 3; ++j )
00603             {
00604                 TS_ASSERT_EQUALS( mat( i, j ), 4 * m_matrix( i, j ) );
00605             }
00606         }
00607     }
00608 
00609     /**
00610      * Matrix addition and subtraction.
00611      */
00612     void testMatrixAdditionAndSubtraction()
00613     {
00614         WMatrixFixed< int, 3, 4 > matrix;
00615         matrix( 0, 0 ) = 1;
00616         matrix( 0, 1 ) = 2;
00617         matrix( 0, 2 ) = 3;
00618         matrix( 1, 0 ) = 4;
00619         matrix( 1, 1 ) = 5;
00620         matrix( 1, 2 ) = 6;
00621         matrix( 2, 0 ) = 7;
00622         matrix( 2, 1 ) = 8;
00623         matrix( 2, 2 ) = 9;
00624         matrix( 0, 3 ) = 10;
00625         matrix( 1, 3 ) = 11;
00626         matrix( 2, 3 ) = 12;
00627 
00628         WMatrixFixed< int, 3, 4 > mat = matrix + matrix;
00629 
00630         TS_ASSERT_EQUALS( mat, matrix * 2 );
00631         TS_ASSERT_EQUALS( mat - matrix, matrix );
00632     }
00633 
00634     /**
00635      * Test the dot product.
00636      */
00637     void testDot()
00638     {
00639         typedef WMatrixFixed< int, 6, 1 > WMI61;
00640 
00641         WMI61 v;
00642         v[ 0 ] = 0;
00643         v[ 1 ] = 1;
00644         v[ 2 ] = 2;
00645         v[ 3 ] = 4;
00646         v[ 4 ] = 1;
00647         v[ 5 ] = 2;
00648 
00649         WMI61 w;
00650         w[ 0 ] = 73;
00651         w[ 1 ] = 1;
00652         w[ 2 ] = 1;
00653         w[ 3 ] = 1;
00654         w[ 4 ] = 5;
00655         w[ 5 ] = 6;
00656 
00657         int i = dot( v, w );
00658         WMatrixFixed< int, 1, 1 > j = transpose( v ) * w;
00659 
00660         TS_ASSERT_EQUALS( i, 24 );
00661         TS_ASSERT_EQUALS( i, j( 0, 0 ) );
00662     }
00663 
00664     /**
00665      * Test vector length.
00666      */
00667     void testLength()
00668     {
00669         WVector3d vec;
00670         vec[ 0 ] = 0.0;
00671         vec[ 1 ] = 4.0;
00672         vec[ 2 ] = 3.0;
00673 
00674         TS_ASSERT_DELTA( length( vec ), 5.0, 1e-10 );
00675         TS_ASSERT_DELTA( length( transpose( vec ) ), 5.0, 1e-10 );
00676 
00677         vec[ 0 ] = 1.0;
00678         vec[ 1 ] = 1.0;
00679         vec[ 2 ] = 1.0;
00680 
00681         TS_ASSERT_DELTA( length( vec ), sqrt( 3.0 ), 1e-10 );
00682         TS_ASSERT_DELTA( length( transpose( vec ) ), sqrt( 3.0 ), 1e-10 );
00683     }
00684 
00685     /**
00686      * Test vector distance.
00687      */
00688     void testDistance()
00689     {
00690         WVector3d vec1;
00691         vec1[ 0 ] = 0.0;
00692         vec1[ 1 ] = 4.0;
00693         vec1[ 2 ] = 3.0;
00694 
00695         WVector3d vec2;
00696         vec2[ 0 ] = 0.0;
00697         vec2[ 1 ] = 0.0;
00698         vec2[ 2 ] = 0.0;
00699 
00700         TS_ASSERT_DELTA( distance( vec1, vec2 ), 5.0, 1e-10 );
00701         TS_ASSERT_DELTA( distance( transpose( vec1 ), transpose( vec2 ) ), 5.0, 1e-10 );
00702 
00703         vec1[ 0 ] = 0.0;
00704         vec1[ 1 ] = 4.0;
00705         vec1[ 2 ] = 3.0;
00706 
00707         vec2[ 0 ] = 0.0;
00708         vec2[ 1 ] = 1.0;
00709         vec2[ 2 ] = 4.0;
00710 
00711         TS_ASSERT_DELTA( distance( vec1, vec2 ), sqrt( 10.0 ), 1e-10 );
00712         TS_ASSERT_DELTA( distance( transpose( vec1 ), transpose( vec2 ) ), sqrt( 10.0 ), 1e-10 );
00713     }
00714 
00715     /**
00716      * Test vector normalization.
00717      */
00718     void testNormalize()
00719     {
00720         WVector3d vec;
00721 
00722         vec[ 0 ] = 2.0;
00723         vec[ 1 ] = 0.0;
00724         vec[ 2 ] = 0.0;
00725 
00726         TS_ASSERT_EQUALS( normalize( vec )[ 0 ], 1.0 );
00727         TS_ASSERT_DELTA( length( normalize( vec ) ), 1.0, 1e-10 );
00728 
00729         vec[ 0 ] = -3.0;
00730         vec[ 1 ] = 1.0;
00731         vec[ 2 ] = 5.0;
00732 
00733         TS_ASSERT_DELTA( length( normalize( vec ) ), 1.0, 1e-10 );
00734     }
00735 
00736     /**
00737      * Test matrix inversion.
00738      */
00739     void testMatrixInverse()
00740     {
00741         WMatrix3d matrix = invert( m_matrix );
00742         matrix *= m_matrix;
00743         for( int i = 0; i < 3; i++ )
00744         {
00745             for( int j = 0; j < 3; ++j )
00746             {
00747                 if( i == j )
00748                 {
00749                     TS_ASSERT_DELTA( WMatrix3d::identity()( i, j ), 1, 1e-10 );
00750                 }
00751                 else
00752                 {
00753                     TS_ASSERT_DELTA( WMatrix3d::identity()( i, j ), 0, 1e-10 );
00754                 }
00755             }
00756         }
00757 
00758         typedef WMatrixFixed< float, 1, 1 > WMF11;
00759         WMF11 mat;
00760         mat( 0, 0 ) = 2.0f;
00761 
00762         WMF11 mat2 = invert( mat );
00763         TS_ASSERT_EQUALS( mat2( 0, 0 ), 0.5f );
00764     }
00765 
00766     /**
00767      * Test for equality comparison of two matrices.
00768      */
00769     void testEqualityOperators()
00770     {
00771         WMatrixFixed< double, 3, 3 > matrix = m_matrix;
00772 
00773         TS_ASSERT( matrix == m_matrix );
00774         TS_ASSERT( ( matrix != m_matrix ) == false );
00775 
00776         m_matrix( 0, 0 ) += 0.1;
00777 
00778         TS_ASSERT( matrix != m_matrix );
00779         TS_ASSERT( ( matrix == m_matrix ) == false );
00780 
00781         m_matrix( 1, 1 ) += 0.1;
00782 
00783         TS_ASSERT( matrix != m_matrix );
00784         TS_ASSERT( ( matrix == m_matrix ) == false );
00785 
00786         m_matrix( 0, 0 ) -= 0.1;
00787 
00788         TS_ASSERT( matrix != m_matrix );
00789         TS_ASSERT( ( matrix == m_matrix ) == false );
00790     }
00791 
00792     /**
00793      * Test transpose method.
00794      */
00795     void testTranspose()
00796     {
00797         {
00798             WMatrixFixed< double, 3, 3 > mat = transpose( m_matrix );
00799             for( std::size_t i = 0; i < 3; ++i )
00800             {
00801                 for( std::size_t j = 0; j < 3; ++j )
00802                 {
00803                     TS_ASSERT_EQUALS( mat.at( j, i ), m_matrix.at( i, j ) );
00804                 }
00805             }
00806         }
00807         {
00808             WMatrixFixed< int, 3, 4 > matrix;
00809             matrix( 0, 0 ) = 1;
00810             matrix( 0, 1 ) = 2;
00811             matrix( 0, 2 ) = 3;
00812             matrix( 1, 0 ) = 4;
00813             matrix( 1, 1 ) = 5;
00814             matrix( 1, 2 ) = 6;
00815             matrix( 2, 0 ) = 7;
00816             matrix( 2, 1 ) = 8;
00817             matrix( 2, 2 ) = 9;
00818             matrix( 0, 3 ) = 10;
00819             matrix( 1, 3 ) = 11;
00820             matrix( 2, 3 ) = 12;
00821 
00822             WMatrixFixed< int, 4, 3 > mat = transpose( matrix );
00823             for( std::size_t i = 0; i < 3; ++i )
00824             {
00825                 for( std::size_t j = 0; j < 4; ++j )
00826                 {
00827                     TS_ASSERT_EQUALS( mat.at( j, i ), matrix.at( i, j ) );
00828                 }
00829             }
00830         }
00831 
00832         TS_ASSERT_EQUALS( transpose( transpose( m_matrix ) ), m_matrix );
00833     }
00834 
00835     /**
00836      * Test stream operators.
00837      */
00838     void testStreamOperators()
00839     {
00840         WMatrixFixed< int, 3, 4 > matrix;
00841         matrix( 0, 0 ) = 1;
00842         matrix( 0, 1 ) = 2;
00843         matrix( 0, 2 ) = 3;
00844         matrix( 1, 0 ) = 4;
00845         matrix( 1, 1 ) = 5;
00846         matrix( 1, 2 ) = 6;
00847         matrix( 2, 0 ) = 7;
00848         matrix( 2, 1 ) = 8;
00849         matrix( 2, 2 ) = 9;
00850         matrix( 0, 3 ) = 10;
00851         matrix( 1, 3 ) = 11;
00852         matrix( 2, 3 ) = 12;
00853 
00854         std::stringstream s;
00855 
00856         s << matrix;
00857 
00858         TS_ASSERT_EQUALS( s.str(), "1;2;3;10;4;5;6;11;7;8;9;12;" );
00859 
00860         WMatrixFixed< int, 3, 4 > matrix2;
00861         s >> matrix2;
00862 
00863         TS_ASSERT_EQUALS( matrix, matrix2 );
00864     }
00865 
00866 private:
00867     /**
00868      * Set up a matrix used for a lot of tests.
00869      */
00870     void setUp()
00871     {
00872         m_matrix( 0, 0 ) = 1.52234;
00873         m_matrix( 0, 1 ) = -0.4534;
00874         m_matrix( 0, 2 ) = 3.0;
00875         m_matrix( 1, 0 ) = 4e3;
00876         m_matrix( 1, 1 ) = 5.666;
00877         m_matrix( 1, 2 ) = -5343.959;
00878         m_matrix( 2, 0 ) = 1;
00879         m_matrix( 2, 1 ) = 0;
00880         m_matrix( 2, 2 ) = 0.1;
00881     }
00882 
00883     //! A matrix used for a lot of tests.
00884     WMatrixFixed< double, 3, 3 > m_matrix;
00885 };
00886 
00887 #endif  // WMATRIXFIXED_TEST_H