OpenWalnut  1.4.0
WTensorBase_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 WTENSORBASE_TEST_H
00026 #define WTENSORBASE_TEST_H
00027 
00028 // unset the WASSERT_AS_CASSERT flag (just in case), so WAssert throws a WException
00029 // note that this may be overwritten by defines in WTensorBase.h
00030 // or any files included from there
00031 #ifdef WASSERT_AS_CASSERT
00032 #define WASSERT_FLAG_CHANGED
00033 #undefine WASSERT_AS_CASSERT
00034 #endif
00035 
00036 #include <string>
00037 #include <vector>
00038 
00039 #include <cxxtest/TestSuite.h>
00040 #include "../WTensorBase.h"
00041 #include "../WMatrix.h"
00042 #include "../WValue.h"
00043 #include "../../WException.h"
00044 
00045 /**
00046  * Test class for WTensorBase.
00047  *
00048  * \note We cannot test invalid template parameters here, as these should lead to compiler errors.
00049  */
00050 class WTensorBaseTest : public CxxTest::TestSuite
00051 {
00052 public:
00053     // remember we are testing class templates
00054     // we'll need to instantiate every operation/member function at least once
00055     // in order to verify that everything compiles
00056     /**
00057      * The standard constructor should allocate enough memory and set all elements to zero.
00058      */
00059     void testTensorBaseConstructor()
00060     {
00061         // define tensor types
00062         typedef WTensorBase< 1, 2, double > T12;
00063         typedef WTensorBase< 2, 3, float > T23;
00064         typedef WTensorBase< 4, 2, int > T42;
00065         typedef WTensorBase< 6, 3, double > T63;
00066         typedef WTensorBase< 0, 0, int > T00;
00067 
00068         // standard constructor should never throw
00069         TS_ASSERT_THROWS_NOTHING( T12 t12() );
00070         T12 t12;
00071 
00072         // number of data elements should be 2
00073         // note that dataSize is private, direct access is only for testing purposes
00074         std::size_t ds = T12::dataSize;
00075         TS_ASSERT_EQUALS( ds, 2 );
00076 
00077         // test if all elements were set to zero
00078         // note that m_data is private
00079         for( std::size_t k = 0; k < 2; ++k )
00080         {
00081             TS_ASSERT_EQUALS( t12.m_data[ k ], 0.0 );
00082         }
00083 
00084         // do the same for some more tensors
00085         TS_ASSERT_THROWS_NOTHING( T23 t23() );
00086         T23 t23;
00087         ds = T23::dataSize;
00088         TS_ASSERT_EQUALS( ds, 9 );
00089         for( std::size_t k = 0; k < 9; ++k )
00090         {
00091             TS_ASSERT_EQUALS( t23.m_data[ k ], 0.0f );
00092         }
00093 
00094         TS_ASSERT_THROWS_NOTHING( T42 t42() );
00095         T42 t42;
00096         ds = T42::dataSize;
00097         TS_ASSERT_EQUALS( ds, 16 );
00098         for( std::size_t k = 0; k < 16; ++k )
00099         {
00100             TS_ASSERT_EQUALS( t42.m_data[ k ], 0 );
00101         }
00102 
00103         TS_ASSERT_THROWS_NOTHING( T63 t63() );
00104         T63 t63;
00105         ds = T63::dataSize;
00106         TS_ASSERT_EQUALS( ds, 729 );
00107         for( std::size_t k = 0; k < 729; ++k )
00108         {
00109             TS_ASSERT_EQUALS( t63.m_data[ k ], 0.0 );
00110         }
00111 
00112         TS_ASSERT_THROWS_NOTHING( T00 t00() );
00113         T00 t00;
00114         TS_ASSERT_EQUALS( t00.m_data, 0 );
00115     }
00116 
00117     /**
00118      * The copy constructor should copy all values.
00119      */
00120     void testWTensorBaseCopyConstructor()
00121     {
00122         typedef WTensorBase< 2, 3, int > T23;
00123         typedef WTensorBase< 5, 4, double > T54;
00124         typedef WTensorBase< 3, 3, float > T33;
00125         typedef WTensorBase< 0, 2, int > T02;
00126 
00127         {
00128             // create a tensor and fill in some values
00129             T23 t;
00130 
00131             t.m_data[ 2 ] = 3;
00132             t.m_data[ 3 ] = 2;
00133             t.m_data[ 7 ] = -1;
00134 
00135             // also test the first and last elements to avoid off-by-one error
00136             t.m_data[ 8 ] = -25;
00137             t.m_data[ 0 ] = 26;
00138 
00139             TS_ASSERT_THROWS_NOTHING( T23 m( t ) );
00140             T23 m( t );
00141 
00142             // the data arrays of t and m should be the same
00143             TS_ASSERT_SAME_DATA( &t.m_data[ 0 ], &m.m_data[ 0 ], 9 * sizeof( int ) );
00144 
00145             // copy from a const ref
00146             T23 const& w = t;
00147             T23 const r( w );
00148 
00149             // the data arrays of r and t should be the same
00150             TS_ASSERT_SAME_DATA( &r.m_data[ 0 ], &t.m_data[ 0 ], 9 * sizeof( int ) );
00151         }
00152 
00153         // now test some other tensors
00154         {
00155             T54 t;
00156 
00157             t.m_data[ 2 ] = 3.0;
00158             t.m_data[ 3 ] = 2.4;
00159             t.m_data[ 7 ] = -1.0;
00160             t.m_data[ 675 ] = 20.0;
00161             t.m_data[ 239 ] = -134.243;
00162             t.m_data[ 964 ] = 567.534;
00163             t.m_data[ 1001 ] = -5.4276;
00164             t.m_data[ 543 ] = 1233.4;
00165             t.m_data[ 827 ] = -9878.765;
00166 
00167             t.m_data[ 1023 ] = -265.63;
00168             t.m_data[ 0 ] = 2453.0;
00169 
00170             TS_ASSERT_THROWS_NOTHING( T54 m( t ) );
00171             T54 m( t );
00172 
00173             TS_ASSERT_SAME_DATA( &t.m_data[ 0 ], &m.m_data[ 0 ], 1024 * sizeof( double ) );
00174         }
00175 
00176         {
00177             T33 t;
00178 
00179             t.m_data[ 2 ] = 3.0f;
00180             t.m_data[ 3 ] = 2.0f;
00181             t.m_data[ 7 ] = -1.0f;
00182             t.m_data[ 16 ] = 200.0f;
00183             t.m_data[ 23 ] = -13.4243f;
00184             t.m_data[ 19 ] = 5675.34f;
00185             t.m_data[ 10 ] = -54276.0f;
00186             t.m_data[ 24 ] = 123.34f;
00187             t.m_data[ 18 ] = -98787.65f;
00188 
00189             t.m_data[ 26 ] = -26.563f;
00190             t.m_data[ 0 ] = 245.3f;
00191 
00192             TS_ASSERT_THROWS_NOTHING( T33 m( t ) );
00193             T33 m( t );
00194 
00195             TS_ASSERT_SAME_DATA( &t.m_data[ 0 ], &m.m_data[ 0 ], 27 * sizeof( float ) );
00196         }
00197 
00198         {
00199             T02 t;
00200             t.m_data = -5;
00201 
00202             TS_ASSERT_THROWS_NOTHING( T02 m( t ) );
00203             T02 m( t );
00204 
00205             TS_ASSERT_EQUALS( m.m_data, t.m_data );
00206         }
00207     }
00208 
00209     /**
00210      * Test the copy operator.
00211      */
00212     void testWTensorBaseCopyOperatorSimple()
00213     {
00214         // this is essentially the same test as with the copy constructor,
00215         // only this time we use the copy operator
00216         typedef WTensorBase< 2, 3, int > T23;
00217         typedef WTensorBase< 5, 4, double > T54;
00218         typedef WTensorBase< 3, 3, float > T33;
00219         typedef WTensorBase< 0, 3, double > T03;
00220 
00221         {
00222             // create a tensor and fill in some values
00223             T23 t, m;
00224 
00225             t.m_data[ 2 ] = 3;
00226             t.m_data[ 3 ] = 2;
00227             t.m_data[ 7 ] = -1;
00228 
00229             // also test the first and last elements to avoid off-by-one error
00230             t.m_data[ 8 ] = -25;
00231             t.m_data[ 0 ] = 26;
00232 
00233             // force operator =
00234             TS_ASSERT_THROWS_NOTHING( m.operator = ( t ) );
00235             m.operator = ( t );
00236 
00237             // the data arrays of t and m should be the same
00238             TS_ASSERT_SAME_DATA( &t.m_data[ 0 ], &m.m_data[ 0 ], 9 * sizeof( int ) );
00239 
00240             // copy from a const ref
00241             T23 const& w = t;
00242             T23 r;
00243             r.operator = ( w );
00244 
00245             // the data arrays of r and t should be the same
00246             TS_ASSERT_SAME_DATA( &r.m_data[ 0 ], &t.m_data[ 0 ], 9 * sizeof( int ) );
00247         }
00248 
00249         // now test some other tensors
00250         {
00251             T54 t, m;
00252 
00253             t.m_data[ 2 ] = 3.0;
00254             t.m_data[ 3 ] = 2.4;
00255             t.m_data[ 7 ] = -1.0;
00256             t.m_data[ 675 ] = 20.0;
00257             t.m_data[ 239 ] = -134.243;
00258             t.m_data[ 964 ] = 567.534;
00259             t.m_data[ 1001 ] = -5.4276;
00260             t.m_data[ 543 ] = 1233.4;
00261             t.m_data[ 827 ] = -9878.765;
00262 
00263             t.m_data[ 1023 ] = -265.63;
00264             t.m_data[ 0 ] = 2453.0;
00265 
00266             TS_ASSERT_THROWS_NOTHING( m.operator = ( t ) );
00267             m.operator = ( t );
00268 
00269             TS_ASSERT_SAME_DATA( &t.m_data[ 0 ], &m.m_data[ 0 ], 1024 * sizeof( double ) );
00270         }
00271 
00272         {
00273             T33 t, m;
00274 
00275             t.m_data[ 2 ] = 3.0f;
00276             t.m_data[ 3 ] = 2.0f;
00277             t.m_data[ 7 ] = -1.0f;
00278             t.m_data[ 16 ] = 200.0f;
00279             t.m_data[ 23 ] = -13.4243f;
00280             t.m_data[ 19 ] = 5675.34f;
00281             t.m_data[ 10 ] = -54276.0f;
00282             t.m_data[ 24 ] = 123.34f;
00283             t.m_data[ 18 ] = -98787.65f;
00284 
00285             t.m_data[ 26 ] = -26.563f;
00286             t.m_data[ 0 ] = 245.3f;
00287 
00288             TS_ASSERT_THROWS_NOTHING( m.operator = ( t ) );
00289             m.operator = ( t );
00290 
00291             TS_ASSERT_SAME_DATA( &t.m_data[ 0 ], &m.m_data[ 0 ], 27 * sizeof( float ) );
00292         }
00293 
00294         {
00295             T03 t;
00296 
00297             t.m_data = -4;
00298 
00299             TS_ASSERT_THROWS_NOTHING( T03 m( t ) );
00300 
00301             T03 m( t );
00302 
00303             TS_ASSERT_EQUALS( m.m_data, t.m_data );
00304         }
00305 
00306         // test multiple assignments in one statement
00307         {
00308             T33 t, m, u, z;
00309 
00310             t.m_data[ 2 ] = 3.0f;
00311             t.m_data[ 3 ] = 2.0f;
00312             t.m_data[ 7 ] = -1.0f;
00313             t.m_data[ 16 ] = 200.0f;
00314             t.m_data[ 23 ] = -13.4243f;
00315             t.m_data[ 19 ] = 5675.34f;
00316             t.m_data[ 10 ] = -54276.0f;
00317             t.m_data[ 24 ] = 123.34f;
00318             t.m_data[ 18 ] = -98787.65f;
00319 
00320             t.m_data[ 26 ] = -26.563f;
00321             t.m_data[ 0 ] = 245.3f;
00322 
00323             z = u = m = t;
00324 
00325             TS_ASSERT_SAME_DATA( &t.m_data[ 0 ], &m.m_data[ 0 ], 27 * sizeof( float ) );
00326             TS_ASSERT_SAME_DATA( &m.m_data[ 0 ], &u.m_data[ 0 ], 27 * sizeof( float ) );
00327             TS_ASSERT_SAME_DATA( &u.m_data[ 0 ], &z.m_data[ 0 ], 27 * sizeof( float ) );
00328         }
00329     }
00330 
00331     /**
00332      * Test if the copy operator handles assignments of variables to themselves correctly.
00333      */
00334     void testWTensorBaseCopyOperatorSelfCopy()
00335     {
00336         typedef WTensorBase< 3, 3, double > T33;
00337         typedef WTensorBase< 0, 0, int > T00;
00338 
00339         {
00340             T33 t;
00341 
00342             // set some elements
00343             t.m_data[ 0 ] = 347.856;
00344             t.m_data[ 26 ] = -4.0;
00345             t.m_data[ 4 ] = -564.4;
00346 
00347             // create a copy of t for comparison
00348             T33 m( t );
00349 
00350             // now try copying t onto itself
00351             // this should not throw anything, as the WTensor documentation states that Data_T
00352             // ( in this case double ) shouldn't throw on assignment
00353             // this is also the reason that there is no test with a datatype whose operator = throws
00354             TS_ASSERT_THROWS_NOTHING( t.operator = ( t ) );
00355             t.operator = ( t );
00356 
00357             // t and m should still be equal
00358             TS_ASSERT_SAME_DATA( &t.m_data[ 0 ], &m.m_data[ 0 ], 27 * sizeof( double ) );
00359         }
00360 
00361         {
00362             T00 t;
00363 
00364             t.m_data = -57;
00365 
00366             T00 m( t );
00367 
00368             TS_ASSERT_THROWS_NOTHING( t.operator = ( t ) );
00369             t.operator = ( t );
00370 
00371             TS_ASSERT_EQUALS( m.m_data, t.m_data );
00372         }
00373     }
00374 
00375     /**
00376      * Test if the access operator correctly throws Exceptions only when the input indices are invalid.
00377      */
00378     void testWTensorBaseArrayAccessErrorConditions()
00379     {
00380         typedef WTensorBase< 4, 4, double > T44;
00381         typedef WTensorBase< 1, 4, int > T14;
00382         typedef WTensorBase< 3, 2, float > T32;
00383         typedef WTensorBase< 0, 654, int > T0;
00384 
00385         {
00386             // instantiate a tensor
00387             T44 t;
00388 
00389             // now create an index array
00390             int idx[] = { 0, 1, 2, 3 };
00391             // this should work
00392             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
00393 
00394             // try some invalid indices, indices of a tensor of dimension 4 may only be 0, 1, 2 or 3
00395             idx[ 3 ] = 4; // idx == [ 0, 1, 2, 4 ]
00396             TS_ASSERT_THROWS( t[ idx ], WException );
00397 
00398             // indices are cast to std::size_t (which should be unsigned)
00399             idx[ 3 ] = -1; // idx == [ 0, 1, 2, -1 ]
00400             TS_ASSERT_THROWS( t[ idx ], WException );
00401 
00402             idx[ 3 ] = 2;
00403             idx[ 0 ] = 4537; // idx == [ 4537, 1, 2, 2 ]
00404             TS_ASSERT_THROWS( t[ idx ], WException );
00405 
00406             idx[ 0 ] = -434; // idx == [ -434, 1, 2, 2 ]
00407             TS_ASSERT_THROWS( t[ idx ], WException );
00408 
00409             // some indices that should be valid
00410             idx[ 0 ] = 3;
00411             idx[ 1 ] = 3;
00412             idx[ 2 ] = 3;
00413             idx[ 3 ] = 3;
00414             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
00415 
00416             idx[ 0 ] = 0;
00417             idx[ 1 ] = 0;
00418             idx[ 2 ] = 0;
00419             idx[ 3 ] = 0;
00420             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
00421 
00422             idx[ 0 ] = 1;
00423             idx[ 1 ] = 3;
00424             idx[ 2 ] = 2;
00425             idx[ 3 ] = 1;
00426             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
00427 
00428             idx[ 0 ] = 0;
00429             idx[ 1 ] = 0;
00430             idx[ 2 ] = 2;
00431             idx[ 3 ] = 0;
00432             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
00433 
00434             // a larger array should also work, all unneeded values should be ignored
00435             std::size_t idx2[] = { 0, 1, 2, 3, 8, 54643 };
00436             TS_ASSERT_THROWS_NOTHING( t[ idx2 ] );
00437 
00438             // note that the length of the index array cannot be checked
00439         }
00440 
00441         // now do the same for another tensor
00442         {
00443             T14 t;
00444 
00445             int idx[] = { 0 };
00446             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
00447 
00448             idx[ 0 ] = 4;
00449             TS_ASSERT_THROWS( t[ idx ], WException );
00450 
00451             idx[ 0 ] = 4537;
00452             TS_ASSERT_THROWS( t[ idx ], WException );
00453 
00454             idx[ 0 ] = 1;
00455             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
00456 
00457             idx[ 0 ] = 2;
00458             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
00459 
00460             idx[ 0 ] = 3;
00461             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
00462 
00463             std::size_t idx2[] = { 0, 1, 2, 3, 8, 54643 };
00464             TS_ASSERT_THROWS_NOTHING( t[ idx2 ] );
00465         }
00466 
00467         // and another one
00468         {
00469             T32 t;
00470 
00471             // note that only values 0 and 1 are valid indices
00472             int idx[] = { 0, 1, 1 };
00473             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
00474 
00475             idx[ 2 ] = 3;
00476             TS_ASSERT_THROWS( t[ idx ], WException );
00477 
00478             idx[ 0 ] = -1;
00479             TS_ASSERT_THROWS( t[ idx ], WException );
00480 
00481             idx[ 2 ] = 2;
00482             idx[ 0 ] = 4537;
00483             TS_ASSERT_THROWS( t[ idx ], WException );
00484 
00485             idx[ 0 ] = 0;
00486             idx[ 1 ] = 1;
00487             idx[ 2 ] = 0;
00488             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
00489 
00490             idx[ 0 ] = 0;
00491             idx[ 1 ] = 0;
00492             idx[ 2 ] = 0;
00493             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
00494 
00495             idx[ 0 ] = 1;
00496             idx[ 1 ] = 0;
00497             idx[ 2 ] = 1;
00498             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
00499 
00500             idx[ 0 ] = 0;
00501             idx[ 1 ] = 0;
00502             idx[ 2 ] = 1;
00503             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
00504 
00505             std::size_t idx2[] = { 0, 1, 1, 3, 8, 54643 };
00506             TS_ASSERT_THROWS_NOTHING( t[ idx2 ] );
00507         }
00508 
00509         {
00510             T0 t;
00511 
00512             std::size_t idx[] = { 0, 1 };
00513             std::size_t* idx2 = NULL;
00514 
00515             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
00516             TS_ASSERT_THROWS_NOTHING( t[ idx2 ] );
00517         }
00518     }
00519 
00520     /**
00521      * Test if the array access operator returns the correct elements.
00522      */
00523     void testWTensorBaseArrayAccess()
00524     {
00525         typedef WTensorBase< 2, 3, std::size_t > T23;
00526         typedef WTensorBase< 3, 4, std::size_t > T34;
00527         typedef WTensorBase< 0, 1, std::size_t > T01;
00528 
00529         // now test if operator [] returns the correct elements
00530         {
00531             // create a new tensor
00532             T23 t;
00533 
00534             // enumerate all elements
00535             for( std::size_t k = 0; k < T23::dataSize; ++k )
00536             {
00537                 t.m_data[ k ] = k;
00538             }
00539 
00540             // the order of elements should be
00541             // 0 1 2
00542             // 3 4 5
00543             // 6 7 8
00544             std::size_t idx[] = { 0, 0 };
00545             TS_ASSERT_EQUALS( t[ idx ], 0 );
00546             idx[ 1 ] = 1; // idx == [ 0, 1 ]
00547             TS_ASSERT_EQUALS( t[ idx ], 1 );
00548             idx[ 1 ] = 2; // idx == [ 0, 2 ]
00549             TS_ASSERT_EQUALS( t[ idx ], 2 );
00550             idx[ 0 ] = 1; // idx == [ 1, 2 ]
00551             TS_ASSERT_EQUALS( t[ idx ], 5 );
00552             idx[ 1 ] = 1; // idx == [ 1, 1 ]
00553             TS_ASSERT_EQUALS( t[ idx ], 4 );
00554             idx[ 1 ] = 0; // idx == [ 1, 0 ]
00555             TS_ASSERT_EQUALS( t[ idx ], 3 );
00556             idx[ 0 ] = 2; // idx == [ 2, 0 ]
00557             TS_ASSERT_EQUALS( t[ idx ], 6 );
00558             idx[ 1 ] = 1; // idx == [ 2, 1 ]
00559             TS_ASSERT_EQUALS( t[ idx ], 7 );
00560             idx[ 1 ] = 2; // idx == [ 2, 2 ]
00561             TS_ASSERT_EQUALS( t[ idx ], 8 );
00562 
00563             // const refs should also work
00564             T23 const& w = t;
00565             idx[ 0 ] = idx[ 1 ] = 0;
00566             TS_ASSERT_EQUALS( w[ idx ], 0 );
00567             idx[ 1 ] = 1; // idx == [ 0, 1 ]
00568             TS_ASSERT_EQUALS( w[ idx ], 1 );
00569             idx[ 1 ] = 2; // idx == [ 0, 2 ]
00570             TS_ASSERT_EQUALS( w[ idx ], 2 );
00571             idx[ 0 ] = 1; // idx == [ 1, 2 ]
00572             TS_ASSERT_EQUALS( w[ idx ], 5 );
00573             idx[ 1 ] = 1; // idx == [ 1, 1 ]
00574             TS_ASSERT_EQUALS( w[ idx ], 4 );
00575             idx[ 1 ] = 0; // idx == [ 1, 0 ]
00576             TS_ASSERT_EQUALS( w[ idx ], 3 );
00577             idx[ 0 ] = 2; // idx == [ 2, 0 ]
00578             TS_ASSERT_EQUALS( w[ idx ], 6 );
00579             idx[ 1 ] = 1; // idx == [ 2, 1 ]
00580             TS_ASSERT_EQUALS( w[ idx ], 7 );
00581             idx[ 1 ] = 2; // idx == [ 2, 2 ]
00582             TS_ASSERT_EQUALS( w[ idx ], 8 );
00583         }
00584         {
00585             // create a new tensor
00586             T34 t;
00587 
00588             // enumerate all elements
00589             for( std::size_t k = 0; k < T34::dataSize; ++k )
00590             {
00591                 t.m_data[ k ] = k;
00592             }
00593 
00594             // order should be
00595             //
00596             // idx[0] == 0  idx[0] == 1   idx[0] == 2   idx[0] == 3
00597             //
00598             // 0  1  2  3   16 17 18 19   32 33 34 35   48 49 50 51     idx[1] == 0
00599             // 4  5  6  7   20 21 22 23   36 37 38 39   52 53 54 55     idx[1] == 1
00600             // 8  9 10 11   24 25 26 27   40 41 42 43   56 57 58 59     idx[1] == 2
00601             //12 13 14 15   28 29 30 31   44 45 46 47   60 61 62 63     idx[1] == 3
00602 
00603             std::size_t idx[] = { 0, 0, 0 };
00604             TS_ASSERT_EQUALS( t[ idx ], 0 );
00605             idx[ 1 ] = 2; // idx == [ 0, 2, 0 ]
00606             TS_ASSERT_EQUALS( t[ idx ], 8 );
00607             idx[ 2 ] = 3; // idx == [ 0, 2, 3 ]
00608             TS_ASSERT_EQUALS( t[ idx ], 11 );
00609             idx[ 0 ] = 1; // idx == [ 1, 2, 3 ]
00610             TS_ASSERT_EQUALS( t[ idx ], 27 );
00611             idx[ 1 ] = 1; // idx == [ 1, 1, 3 ]
00612             TS_ASSERT_EQUALS( t[ idx ], 23 );
00613             idx[ 0 ] = 3; // idx == [ 3, 1, 3 ]
00614             TS_ASSERT_EQUALS( t[ idx ], 55 );
00615             idx[ 2 ] = 0; // idx == [ 3, 1, 0 ]
00616             TS_ASSERT_EQUALS( t[ idx ], 52 );
00617             idx[ 1 ] = 3; // idx == [ 3, 3, 0 ]
00618             TS_ASSERT_EQUALS( t[ idx ], 60 );
00619             idx[ 1 ] = 2; // idx == [ 3, 2, 0 ]
00620             TS_ASSERT_EQUALS( t[ idx ], 56 );
00621         }
00622 
00623         // zero order tensor
00624         {
00625             T01 t;
00626             t.m_data = 65;
00627 
00628             std::size_t idx[] = { 0, 1 };
00629             std::size_t* idx2 = NULL;
00630 
00631             TS_ASSERT_EQUALS( t[ idx ], 65 );
00632             TS_ASSERT_EQUALS( t[ idx2 ], 65 );
00633         }
00634     }
00635 
00636     /**
00637      * Test the std::vector version of operator [] for correct handling of
00638      * various input vector sizes.
00639      */
00640     void testWTensorBaseVectorAccess()
00641     {
00642         typedef WTensorBase< 4, 4, double > T44;
00643         typedef WTensorBase< 1, 4, double > T14;
00644         typedef WTensorBase< 6, 2, double > T62;
00645         typedef WTensorBase< 0, 1, double > T01;
00646 
00647         {
00648             T44 t;
00649 
00650             // test a vector of invalid size
00651             std::vector< int > idx;
00652 
00653             // this should throw a WException (using the WAssert macro)
00654             TS_ASSERT_THROWS( t[ idx ], WException );
00655 
00656             idx.push_back( 0 ); // idx == [ 0 ]
00657             TS_ASSERT_THROWS( t[ idx ], WException );
00658             idx.push_back( 1 ); // idx == [ 0, 1 ]
00659             TS_ASSERT_THROWS( t[ idx ], WException );
00660             idx.push_back( 2 ); // idx == [ 0, 1, 2 ]
00661             TS_ASSERT_THROWS( t[ idx ], WException );
00662 
00663             idx.push_back( 3 ); // idx == [ 0, 1, 2, 3 ]
00664             // now idx has the correct size and all valid indices
00665             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
00666 
00667             // a larger vector should also work
00668             idx.push_back( 456 ); // idx == [ 0, 0, 2, 0, 456 ]
00669 
00670             // this should simply ignore all values after the 4th
00671             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
00672 
00673             idx.push_back( -1 );
00674             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
00675 
00676             // bounds checking on the indices is done by the array version of operator [],
00677             // which is called by the vector version
00678             // I'll add some tests here though, in case this changes in the future
00679             idx[ 0 ] = -1;
00680             TS_ASSERT_THROWS( t[ idx ], WException );
00681 
00682             idx[ 0 ] = 4;
00683             TS_ASSERT_THROWS( t[ idx ], WException );
00684 
00685             idx[ 0 ] = 3;
00686             idx[ 3 ] = -1;
00687             TS_ASSERT_THROWS( t[ idx ], WException );
00688 
00689             idx[ 3 ] = 4;
00690             TS_ASSERT_THROWS( t[ idx ], WException );
00691 
00692             idx[ 3 ] = 2;
00693             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
00694         }
00695         {
00696             T14 t;
00697 
00698             std::vector< int > idx;
00699             TS_ASSERT_THROWS( t[ idx ], WException );
00700 
00701             idx.push_back( 0 ); // idx == [ 0 ]
00702             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
00703 
00704             idx.push_back( 3 ); // idx == [ 0, 3 ]
00705             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
00706 
00707             idx.push_back( 456 ); // idx == [ 0, 3, 456 ]
00708             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
00709 
00710             idx.push_back( -1 );
00711             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
00712         }
00713         {
00714             T62 t;
00715 
00716             std::vector< int > idx;
00717             TS_ASSERT_THROWS( t[ idx ], WException );
00718 
00719             idx.push_back( 0 ); // idx == [ 0 ]
00720             TS_ASSERT_THROWS( t[ idx ], WException );
00721             idx.push_back( 1 ); // idx == [ 0, 1 ]
00722             TS_ASSERT_THROWS( t[ idx ], WException );
00723             idx.push_back( 0 ); // idx == [ 0, 1, 0 ]
00724             TS_ASSERT_THROWS( t[ idx ], WException );
00725             idx.push_back( 1 );
00726             TS_ASSERT_THROWS( t[ idx ], WException );
00727             idx.push_back( 1 );
00728             TS_ASSERT_THROWS( t[ idx ], WException );
00729             idx.push_back( 0 );
00730             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
00731 
00732             idx.push_back( 456 );
00733             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
00734 
00735             idx.push_back( -1 );
00736             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
00737         }
00738         {
00739             T01 t;
00740 
00741             std::vector< int > idx;
00742 
00743             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
00744 
00745             idx.push_back( 4 );
00746             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
00747 
00748             T01 const w;
00749             TS_ASSERT_THROWS_NOTHING( w[ idx ] );
00750         }
00751     }
00752 
00753     /**
00754      * Test if operator == works correctly.
00755      */
00756     void testWTensorBaseCompareOperator()
00757     {
00758         typedef WTensorBase< 1, 7, double > T17;
00759         typedef WTensorBase< 3, 2, int > T32;
00760         typedef WTensorBase< 0, 0, float > T00;
00761 
00762         {
00763             T17 t, m;
00764 
00765             // two tensors of the same type should be initialized to the same values
00766             TS_ASSERT( t == m );
00767             TS_ASSERT( m == t );
00768 
00769             // a tensor should always be equal to itself
00770             TS_ASSERT( t == t );
00771             TS_ASSERT( m == m );
00772 
00773             // change some values
00774             std::size_t idx[] = { 4 };
00775             t[ idx ] = 5.0;
00776 
00777             TS_ASSERT( !( t == m ) );
00778             TS_ASSERT( !( m == t ) );
00779             TS_ASSERT( t == t );
00780             TS_ASSERT( m == m );
00781 
00782             m[ idx ] = 5.0;
00783 
00784             TS_ASSERT( t == m );
00785             TS_ASSERT( m == t );
00786             TS_ASSERT( t == t );
00787             TS_ASSERT( m == m );
00788 
00789             idx[ 0 ] = 2;
00790             m[ idx ] = 543543.0;
00791 
00792             TS_ASSERT( !( t == m ) );
00793             TS_ASSERT( !( m == t ) );
00794             TS_ASSERT( t == t );
00795             TS_ASSERT( m == m );
00796 
00797             // copying a tensor should lead to the respective tensors being equal
00798             t = m;
00799             TS_ASSERT( t == m );
00800             TS_ASSERT( m == t );
00801             TS_ASSERT( t == t );
00802             TS_ASSERT( m == m );
00803 
00804             // test const
00805             T17 const ct, cm;
00806             TS_ASSERT( ct == cm );
00807             TS_ASSERT( cm == ct );
00808             TS_ASSERT( ct == ct );
00809             TS_ASSERT( cm == cm );
00810         }
00811         {
00812             T32 t, m;
00813 
00814             std::size_t idx[] = { 0, 0, 0 };
00815 
00816             // two tensors of the same type should be initialized to the same values
00817             TS_ASSERT( t == m );
00818             TS_ASSERT( m == t );
00819 
00820             // a tensor should always be equal to itself
00821             TS_ASSERT( t == t );
00822             TS_ASSERT( m == m );
00823 
00824             idx[ 1 ] = 1;
00825 
00826             m[ idx ] = -5643;
00827 
00828             TS_ASSERT( !( t == m ) );
00829             TS_ASSERT( !( m == t ) );
00830             TS_ASSERT( t == t );
00831             TS_ASSERT( m == m );
00832 
00833             t = m;
00834 
00835             TS_ASSERT( t == m );
00836             TS_ASSERT( m == t );
00837             TS_ASSERT( t == t );
00838             TS_ASSERT( m == m );
00839 
00840             idx[ 1 ] = 0;
00841 
00842             t[ idx ] = 564;
00843 
00844             TS_ASSERT( !( t == m ) );
00845             TS_ASSERT( !( m == t ) );
00846             TS_ASSERT( t == t );
00847             TS_ASSERT( m == m );
00848 
00849             t.m_data[ 0 ] = 5;
00850             t.m_data[ 1 ] = -65464;
00851             t.m_data[ 2 ] = 89;
00852             t.m_data[ 3 ] = 3276;
00853             t.m_data[ 4 ] = -3276;
00854             t.m_data[ 5 ] = 47;
00855             t.m_data[ 6 ] = 68;
00856             t.m_data[ 7 ] = -239;
00857 
00858             m.m_data[ 0 ] = -5;
00859             m.m_data[ 1 ] = 65464;
00860             m.m_data[ 2 ] = -89;
00861             m.m_data[ 3 ] = -3276;
00862             m.m_data[ 4 ] = 3276;
00863             m.m_data[ 5 ] = -47;
00864             m.m_data[ 6 ] = -68;
00865             m.m_data[ 7 ] = 239;
00866 
00867             TS_ASSERT( !( t == m ) );
00868             TS_ASSERT( !( m == t ) );
00869             TS_ASSERT( t == t );
00870             TS_ASSERT( m == m );
00871         }
00872         {
00873             T00 t, m;
00874 
00875             // two tensors of the same type should be initialized to the same values
00876             TS_ASSERT( t == m );
00877             TS_ASSERT( m == t );
00878 
00879             // a tensor should always be equal to itself
00880             TS_ASSERT( t == t );
00881             TS_ASSERT( m == m );
00882 
00883             t.m_data = 2;
00884 
00885             TS_ASSERT( !( t == m ) );
00886             TS_ASSERT( !( m == t ) );
00887             TS_ASSERT( t == t );
00888             TS_ASSERT( m == m );
00889 
00890             m.m_data = 2;
00891 
00892             TS_ASSERT( t == m );
00893             TS_ASSERT( m == t );
00894             TS_ASSERT( t == t );
00895             TS_ASSERT( m == m );
00896         }
00897     }
00898 
00899     /**
00900      * Test if operator != works correctly.
00901      */
00902     void testWTensorBaseCompareOperator2()
00903     {
00904         typedef WTensorBase< 3, 3, int > T33;
00905         typedef WTensorBase< 0, 0, int > T00;
00906 
00907         {
00908             T33 t, m;
00909 
00910             // two new instances should never not be equal
00911             TS_ASSERT( !( t != m ) );
00912             TS_ASSERT( !( m != t ) );
00913 
00914             // a tensor should never not be equal to itself
00915             TS_ASSERT( !( t != t ) );
00916             TS_ASSERT( !( m != m ) );
00917 
00918             // change some elements
00919             t.m_data[ 23 ] = -23467;
00920 
00921             TS_ASSERT( t != m );
00922             TS_ASSERT( m != t );
00923             TS_ASSERT( !( t != t ) );
00924             TS_ASSERT( !( m != m ) );
00925 
00926             t = m;
00927             TS_ASSERT( !( t != m ) );
00928             TS_ASSERT( !( m != t ) );
00929 
00930             t.m_data[ 0 ] = 1;
00931             TS_ASSERT( t != m );
00932             TS_ASSERT( m != t );
00933             TS_ASSERT( !( t != t ) );
00934             TS_ASSERT( !( m != m ) );
00935 
00936             t = m;
00937             TS_ASSERT( !( t != m ) );
00938             TS_ASSERT( !( m != t ) );
00939             TS_ASSERT( !( t != t ) );
00940             TS_ASSERT( !( m != m ) );
00941 
00942             t.m_data[ 26 ] = -1;
00943             TS_ASSERT( t != m );
00944             TS_ASSERT( m != t );
00945             TS_ASSERT( !( t != t ) );
00946             TS_ASSERT( !( m != m ) );
00947 
00948             // test const
00949             T33 const ct, cm;
00950             TS_ASSERT( !( ct != cm ) );
00951             TS_ASSERT( !( cm != ct ) );
00952             TS_ASSERT( !( ct != ct ) );
00953             TS_ASSERT( !( cm != cm ) );
00954         }
00955         {
00956             T00 t, m;
00957 
00958             TS_ASSERT( !( t != m ) );
00959             TS_ASSERT( !( m != t ) );
00960             TS_ASSERT( !( t != t ) );
00961             TS_ASSERT( !( m != m ) );
00962 
00963             t.m_data = 2;
00964 
00965             TS_ASSERT( t != m );
00966             TS_ASSERT( m != t );
00967             TS_ASSERT( !( t != t ) );
00968             TS_ASSERT( !( m != m ) );
00969 
00970             m.m_data = 2;
00971 
00972             TS_ASSERT( !( t != m ) );
00973             TS_ASSERT( !( m != t ) );
00974             TS_ASSERT( !( t != t ) );
00975             TS_ASSERT( !( m != m ) );
00976         }
00977     }
00978 };
00979 
00980 /**
00981  * Test class for WTensorBaseSym.
00982  *
00983  * \note We cannot test invalid template parameters here, as these should lead to compiler errors.
00984  */
00985 class WTensorBaseSymTest : public CxxTest::TestSuite
00986 {
00987 public:
00988     /**
00989      * The standard constructor should allocate enough memory and set all elements to zero.
00990      */
00991     void testTensorBaseSymConstructor()
00992     {
00993         // define tensor types
00994         typedef WTensorBaseSym< 1, 2, double > T12;
00995         typedef WTensorBaseSym< 2, 3, float > T23;
00996         typedef WTensorBaseSym< 4, 2, int > T42;
00997         typedef WTensorBaseSym< 6, 3, double > T63;
00998         typedef WTensorBaseSym< 0, 0, int > T00;
00999 
01000         // standard constructor should never throw
01001         TS_ASSERT_THROWS_NOTHING( T12 t12() );
01002         T12 t12;
01003 
01004         // number of data elements should be 2
01005         // note that dataSize is private, direct access is only for testing purposes
01006         std::size_t ds = T12::dataSize;
01007         TS_ASSERT_EQUALS( ds, 2 );
01008 
01009         // test if all elements were set to zero
01010         // note that m_data is private
01011         for( std::size_t k = 0; k < 2; ++k )
01012         {
01013             TS_ASSERT_EQUALS( t12.m_data[ k ], 0.0 );
01014         }
01015 
01016         // do the same for some more tensors
01017         // symmetric tensors need less memory, 6 instead of 9 values in this case
01018         TS_ASSERT_THROWS_NOTHING( T23 t23() );
01019         T23 t23;
01020         ds = T23::dataSize;
01021         TS_ASSERT_EQUALS( ds, 6 );
01022         for( std::size_t k = 0; k < 6; ++k )
01023         {
01024             TS_ASSERT_EQUALS( t23.m_data[ k ], 0.0f );
01025         }
01026 
01027         TS_ASSERT_THROWS_NOTHING( T42 t42() );
01028         T42 t42;
01029         ds = T42::dataSize;
01030         TS_ASSERT_EQUALS( ds, 5 );
01031         for( std::size_t k = 0; k < 5; ++k )
01032         {
01033             TS_ASSERT_EQUALS( t42.m_data[ k ], 0 );
01034         }
01035 
01036         TS_ASSERT_THROWS_NOTHING( T63 t63() );
01037         T63 t63;
01038         ds = T63::dataSize;
01039         TS_ASSERT_EQUALS( ds, 28 );
01040         for( std::size_t k = 0; k < 28; ++k )
01041         {
01042             TS_ASSERT_EQUALS( t63.m_data[ k ], 0.0 );
01043         }
01044 
01045         TS_ASSERT_THROWS_NOTHING( T00 t00() );
01046         T00 t00;
01047         TS_ASSERT_EQUALS( t00.m_data, 0 );
01048     }
01049 
01050     /**
01051      * The copy constructor should copy all values.
01052      */
01053     void testWTensorBaseSymCopyConstructor()
01054     {
01055         typedef WTensorBaseSym< 2, 3, int > T23;
01056         typedef WTensorBaseSym< 5, 4, double > T54;
01057         typedef WTensorBaseSym< 3, 3, float > T33;
01058         typedef WTensorBaseSym< 0, 2, int > T02;
01059 
01060         {
01061             // create a tensor and fill in some values
01062             // use direct access to the m_data array as access operators aren't tested yet
01063             T23 t;
01064 
01065             t.m_data[ 2 ] = 3;
01066             t.m_data[ 3 ] = 2;
01067             t.m_data[ 4 ] = -1;
01068 
01069             // also test the first and last elements to avoid off-by-one error
01070             t.m_data[ 5 ] = -25;
01071             t.m_data[ 0 ] = 26;
01072 
01073             TS_ASSERT_THROWS_NOTHING( T23 m( t ) );
01074             T23 m( t );
01075 
01076             // the data arrays of t and m should be the same
01077             TS_ASSERT_SAME_DATA( &t.m_data[ 0 ], &m.m_data[ 0 ], 6 * sizeof( int ) );
01078 
01079             // copy from a const ref
01080             T23 const& w = t;
01081             T23 const r( w );
01082 
01083             // the data arrays of r and t should be the same
01084             TS_ASSERT_SAME_DATA( &r.m_data[ 0 ], &t.m_data[ 0 ], 6 * sizeof( int ) );
01085         }
01086 
01087         // now test some other tensors
01088         {
01089             T54 t;
01090 
01091             t.m_data[ 2 ] = 3.0;
01092             t.m_data[ 3 ] = 2.4;
01093             t.m_data[ 7 ] = -1.0;
01094             t.m_data[ 33 ] = 20.0;
01095             t.m_data[ 21 ] = -134.243;
01096             t.m_data[ 54 ] = 567.534;
01097             t.m_data[ 48 ] = -5.4276;
01098             t.m_data[ 34 ] = 1233.4;
01099             t.m_data[ 27 ] = -9878.765;
01100 
01101             t.m_data[ 55 ] = -265.63;
01102             t.m_data[ 0 ] = 2453.0;
01103 
01104             TS_ASSERT_THROWS_NOTHING( T54 m( t ) );
01105             T54 m( t );
01106 
01107             TS_ASSERT_SAME_DATA( &t.m_data[ 0 ], &m.m_data[ 0 ], 56 * sizeof( double ) );
01108         }
01109 
01110         {
01111             T33 t;
01112 
01113             t.m_data[ 2 ] = 3.0f;
01114             t.m_data[ 3 ] = 2.0f;
01115             t.m_data[ 7 ] = -1.0f;
01116             t.m_data[ 1 ] = -13.4243f;
01117             t.m_data[ 5 ] = 5675.34f;
01118             t.m_data[ 6 ] = -54276.0f;
01119             t.m_data[ 4 ] = 123.34f;
01120             t.m_data[ 8 ] = -98787.65f;
01121 
01122             t.m_data[ 9 ] = -26.563f;
01123             t.m_data[ 0 ] = 245.3f;
01124 
01125             TS_ASSERT_THROWS_NOTHING( T33 m( t ) );
01126             T33 m( t );
01127 
01128             TS_ASSERT_SAME_DATA( &t.m_data[ 0 ], &m.m_data[ 0 ], 10 * sizeof( float ) );
01129         }
01130 
01131         // test multiple assignments in one statement
01132         {
01133             T33 t, m, u, z;
01134 
01135             t.m_data[ 2 ] = 3.0f;
01136             t.m_data[ 3 ] = 2.0f;
01137             t.m_data[ 7 ] = -1.0f;
01138             t.m_data[ 1 ] = -13.4243f;
01139             t.m_data[ 5 ] = 5675.34f;
01140             t.m_data[ 6 ] = -54276.0f;
01141             t.m_data[ 4 ] = 123.34f;
01142             t.m_data[ 8 ] = -98787.65f;
01143 
01144             t.m_data[ 9 ] = -26.563f;
01145             t.m_data[ 0 ] = 245.3f;
01146 
01147             z = u = m = t;
01148 
01149             TS_ASSERT_SAME_DATA( &t.m_data[ 0 ], &m.m_data[ 0 ], 10 * sizeof( float ) );
01150             TS_ASSERT_SAME_DATA( &m.m_data[ 0 ], &u.m_data[ 0 ], 10 * sizeof( float ) );
01151             TS_ASSERT_SAME_DATA( &u.m_data[ 0 ], &z.m_data[ 0 ], 10 * sizeof( float ) );
01152         }
01153 
01154         {
01155             T02 t;
01156             t.m_data = -5;
01157 
01158             TS_ASSERT_THROWS_NOTHING( T02 m( t ) );
01159             T02 m( t );
01160 
01161             TS_ASSERT_EQUALS( m.m_data, t.m_data );
01162         }
01163     }
01164 
01165     /**
01166      * Test the copy operator.
01167      */
01168     void testWTensorBaseSymCopyOperatorSimple()
01169     {
01170         // this is essentially the same test as with the copy constructor,
01171         // only this time we use the copy operator
01172 
01173         typedef WTensorBaseSym< 2, 3, int > T23;
01174         typedef WTensorBaseSym< 5, 4, double > T54;
01175         typedef WTensorBaseSym< 3, 3, float > T33;
01176         typedef WTensorBaseSym< 0, 3, double > T03;
01177 
01178         {
01179             // create a tensor and fill in some values
01180             // use direct access to the m_data array as access operators aren't tested yet
01181             T23 t, m;
01182 
01183             t.m_data[ 2 ] = 3;
01184             t.m_data[ 3 ] = 2;
01185             t.m_data[ 1 ] = -1;
01186 
01187             // also test the first and last elements to avoid off-by-one error
01188             t.m_data[ 5 ] = -25;
01189             t.m_data[ 0 ] = 26;
01190 
01191             // force operator =
01192             TS_ASSERT_THROWS_NOTHING( m.operator = ( t ) );
01193             m.operator = ( t );
01194 
01195             // the data arrays of t and m should be the same
01196             TS_ASSERT_SAME_DATA( &t.m_data[ 0 ], &m.m_data[ 0 ], 6 * sizeof( int ) );
01197 
01198             // copy from a const ref
01199             T23 const& w = t;
01200             T23 r;
01201             r.operator = ( w );
01202 
01203             // the data arrays of r and t should be the same
01204             TS_ASSERT_SAME_DATA( &r.m_data[ 0 ], &t.m_data[ 0 ], 6 * sizeof( int ) );
01205         }
01206 
01207         // now test some other tensors
01208         {
01209             T54 t, m;
01210 
01211             t.m_data[ 2 ] = 3.0;
01212             t.m_data[ 3 ] = 2.4;
01213             t.m_data[ 7 ] = -1.0;
01214             t.m_data[ 33 ] = 20.0;
01215             t.m_data[ 21 ] = -134.243;
01216             t.m_data[ 54 ] = 567.534;
01217             t.m_data[ 48 ] = -5.4276;
01218             t.m_data[ 34 ] = 1233.4;
01219             t.m_data[ 27 ] = -9878.765;
01220 
01221             t.m_data[ 55 ] = -265.63;
01222             t.m_data[ 0 ] = 2453.0;
01223 
01224             TS_ASSERT_THROWS_NOTHING( m.operator = ( t ) );
01225             m.operator = ( t );
01226 
01227             TS_ASSERT_SAME_DATA( &t.m_data[ 0 ], &m.m_data[ 0 ], 56 * sizeof( double ) );
01228         }
01229 
01230         {
01231             T33 t, m;
01232 
01233             t.m_data[ 2 ] = 3.0f;
01234             t.m_data[ 3 ] = 2.0f;
01235             t.m_data[ 7 ] = -1.0f;
01236             t.m_data[ 1 ] = -13.4243f;
01237             t.m_data[ 5 ] = 5675.34f;
01238             t.m_data[ 6 ] = -54276.0f;
01239             t.m_data[ 4 ] = 123.34f;
01240             t.m_data[ 8 ] = -98787.65f;
01241 
01242             t.m_data[ 9 ] = -26.563f;
01243             t.m_data[ 0 ] = 245.3f;
01244 
01245             TS_ASSERT_THROWS_NOTHING( m.operator = ( t ) );
01246             m.operator = ( t );
01247 
01248             TS_ASSERT_SAME_DATA( &t.m_data[ 0 ], &m.m_data[ 0 ], 10 * sizeof( float ) );
01249         }
01250 
01251         {
01252             T03 t;
01253 
01254             t.m_data = -4;
01255 
01256             TS_ASSERT_THROWS_NOTHING( T03 m( t ) );
01257 
01258             T03 m( t );
01259 
01260             TS_ASSERT_EQUALS( m.m_data, t.m_data );
01261         }
01262     }
01263 
01264     /**
01265      * Test if the copy operator handles assignments of variables to themselves correctly.
01266      */
01267     void testWTensorBaseSymCopyOperatorSelfCopy()
01268     {
01269         typedef WTensorBaseSym< 3, 3, double > T33;
01270         typedef WTensorBaseSym< 0, 0, int > T00;
01271 
01272         {
01273             T33 t;
01274 
01275             // set some elements
01276             t.m_data[ 0 ] = 347.856;
01277             t.m_data[ 9 ] = -4.0;
01278             t.m_data[ 4 ] = -564.4;
01279 
01280             // create a copy of t for comparison
01281             T33 m( t );
01282 
01283             // now try copying t onto itself
01284             // this should not throw anything, as the WTensorSym documentation states that Data_T
01285             // ( in this case double ) shouldn't throw on assignment
01286             // this is also the reason that there is no test with a datatype whose operator = throws
01287             TS_ASSERT_THROWS_NOTHING( t.operator = ( t ) );
01288             t.operator = ( t );
01289 
01290             // t and m should still be equal
01291             TS_ASSERT_SAME_DATA( &t.m_data[ 0 ], &m.m_data[ 0 ], 10 * sizeof( double ) );
01292         }
01293 
01294         {
01295             T00 t;
01296 
01297             t.m_data = -57;
01298 
01299             T00 m( t );
01300 
01301             TS_ASSERT_THROWS_NOTHING( t.operator = ( t ) );
01302             t.operator = ( t );
01303 
01304             TS_ASSERT_EQUALS( m.m_data, t.m_data );
01305         }
01306     }
01307 
01308     /**
01309      * Test if the access operator correctly throws Exceptions only when the input indices are invalid.
01310      */
01311     void testWTensorBaseSymArrayAccessErrorConditions()
01312     {
01313         typedef WTensorBaseSym< 4, 4, double > T44;
01314         typedef WTensorBaseSym< 1, 4, int > T14;
01315         typedef WTensorBaseSym< 3, 2, float > T32;
01316         typedef WTensorBaseSym< 0, 654, int > T0;
01317 
01318         // first, we'll check some error conditions
01319         {
01320             // instantiate a tensor
01321             T44 t;
01322 
01323             // now create an index array
01324             int idx[] = { 0, 1, 2, 3 };
01325             // this should work
01326             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
01327 
01328             // try some invalid indices, indices of a tensor of dimension 4 may only be 0, 1, 2 or 3
01329             idx[ 3 ] = 4; // idx == [ 0, 1, 2, 4 ]
01330             TS_ASSERT_THROWS( t[ idx ], WException );
01331 
01332             // indices are cast to std::size_t (which should be unsigned)
01333             idx[ 3 ] = -1; // idx == [ 0, 1, 2, -1 ]
01334             TS_ASSERT_THROWS( t[ idx ], WException );
01335 
01336             idx[ 3 ] = 2;
01337             idx[ 0 ] = 4537; // idx == [ 4537, 1, 2, 2 ]
01338             TS_ASSERT_THROWS( t[ idx ], WException );
01339 
01340             idx[ 0 ] = -434; // idx == [ -434, 1, 2, 2 ]
01341             TS_ASSERT_THROWS( t[ idx ], WException );
01342 
01343             // some indices that should be valid
01344             idx[ 0 ] = 3;
01345             idx[ 1 ] = 3;
01346             idx[ 2 ] = 3;
01347             idx[ 3 ] = 3;
01348             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
01349 
01350             idx[ 0 ] = 0;
01351             idx[ 1 ] = 0;
01352             idx[ 2 ] = 0;
01353             idx[ 3 ] = 0;
01354             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
01355 
01356             idx[ 0 ] = 1;
01357             idx[ 1 ] = 3;
01358             idx[ 2 ] = 2;
01359             idx[ 3 ] = 1;
01360             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
01361 
01362             idx[ 0 ] = 0;
01363             idx[ 1 ] = 0;
01364             idx[ 2 ] = 2;
01365             idx[ 3 ] = 0;
01366             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
01367 
01368             // a larger array should also work, all unneeded values should be ignored
01369             std::size_t idx2[] = { 0, 1, 2, 3, 8, 54643 };
01370             TS_ASSERT_THROWS_NOTHING( t[ idx2 ] );
01371 
01372             // note that the length of the index array cannot be checked
01373         }
01374 
01375         // now do the same for another tensor
01376         {
01377             T14 t;
01378 
01379             int idx[] = { 0 };
01380             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
01381 
01382             idx[ 0 ] = 4;
01383             TS_ASSERT_THROWS( t[ idx ], WException );
01384 
01385             idx[ 0 ] = 4537;
01386             TS_ASSERT_THROWS( t[ idx ], WException );
01387 
01388             idx[ 0 ] = 1;
01389             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
01390 
01391             idx[ 0 ] = 2;
01392             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
01393 
01394             idx[ 0 ] = 3;
01395             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
01396 
01397             std::size_t idx2[] = { 0, 1, 2, 3, 8, 54643 };
01398             TS_ASSERT_THROWS_NOTHING( t[ idx2 ] );
01399         }
01400 
01401         // and another one
01402         {
01403             T32 t;
01404 
01405             // note that only values 0 and 1 are valid indices
01406             int idx[] = { 0, 1, 1 };
01407             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
01408 
01409             idx[ 2 ] = 3;
01410             TS_ASSERT_THROWS( t[ idx ], WException );
01411 
01412             idx[ 0 ] = -1;
01413             TS_ASSERT_THROWS( t[ idx ], WException );
01414 
01415             idx[ 2 ] = 2;
01416             idx[ 0 ] = 4537;
01417             TS_ASSERT_THROWS( t[ idx ], WException );
01418 
01419             idx[ 0 ] = 0;
01420             idx[ 1 ] = 1;
01421             idx[ 2 ] = 0;
01422             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
01423 
01424             idx[ 0 ] = 0;
01425             idx[ 1 ] = 0;
01426             idx[ 2 ] = 0;
01427             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
01428 
01429             idx[ 0 ] = 1;
01430             idx[ 1 ] = 0;
01431             idx[ 2 ] = 1;
01432             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
01433 
01434             idx[ 0 ] = 0;
01435             idx[ 1 ] = 0;
01436             idx[ 2 ] = 1;
01437             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
01438 
01439             std::size_t idx2[] = { 0, 1, 1, 3, 8, 54643 };
01440             TS_ASSERT_THROWS_NOTHING( t[ idx2 ] );
01441         }
01442 
01443         {
01444             T0 t;
01445 
01446             std::size_t idx[] = { 0, 1 };
01447             std::size_t* idx2 = NULL;
01448 
01449             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
01450             TS_ASSERT_THROWS_NOTHING( t[ idx2 ] );
01451         }
01452     }
01453 
01454     /**
01455      * Test if the array access operator returns the correct elements.
01456      */
01457     void testWTensorBaseSymArrayAccess()
01458     {
01459         typedef WTensorBaseSym< 2, 3, std::size_t > T23;
01460         typedef WTensorBaseSym< 3, 4, std::size_t > T34;
01461 
01462         // now test if operator [] returns the correct elements
01463         {
01464             // create a new tensor
01465             T23 t;
01466 
01467             // enumerate all elements
01468             for( std::size_t k = 0; k < T23::dataSize; ++k )
01469             {
01470                 t.m_data[ k ] = k;
01471             }
01472 
01473             // the order of elements should be
01474             // 0 1 2
01475             //   3 4
01476             //     5
01477             std::size_t idx[] = { 0, 0 };
01478             TS_ASSERT_EQUALS( t[ idx ], 0 );
01479             idx[ 1 ] = 1; // idx == [ 0, 1 ]
01480             TS_ASSERT_EQUALS( t[ idx ], 1 );
01481             idx[ 1 ] = 2; // idx == [ 0, 2 ]
01482             TS_ASSERT_EQUALS( t[ idx ], 2 );
01483             idx[ 0 ] = 1; // idx == [ 1, 2 ]
01484             TS_ASSERT_EQUALS( t[ idx ], 4 );
01485             idx[ 1 ] = 1; // idx == [ 1, 1 ]
01486             TS_ASSERT_EQUALS( t[ idx ], 3 );
01487             idx[ 1 ] = 0; // idx == [ 1, 0 ]
01488             TS_ASSERT_EQUALS( t[ idx ], 1 );
01489             idx[ 0 ] = 2; // idx == [ 2, 0 ]
01490             TS_ASSERT_EQUALS( t[ idx ], 2 );
01491             idx[ 1 ] = 1; // idx == [ 2, 1 ]
01492             TS_ASSERT_EQUALS( t[ idx ], 4 );
01493             idx[ 1 ] = 2; // idx == [ 2, 2 ]
01494             TS_ASSERT_EQUALS( t[ idx ], 5 );
01495 
01496             // const refs should also work
01497             T23 const& w = t;
01498             idx[ 0 ] = idx[ 1 ] = 0;
01499             TS_ASSERT_EQUALS( w[ idx ], 0 );
01500             idx[ 1 ] = 1; // idx == [ 0, 1 ]
01501             TS_ASSERT_EQUALS( w[ idx ], 1 );
01502             idx[ 1 ] = 2; // idx == [ 0, 2 ]
01503             TS_ASSERT_EQUALS( w[ idx ], 2 );
01504             idx[ 0 ] = 1; // idx == [ 1, 2 ]
01505             TS_ASSERT_EQUALS( w[ idx ], 4 );
01506             idx[ 1 ] = 1; // idx == [ 1, 1 ]
01507             TS_ASSERT_EQUALS( w[ idx ], 3 );
01508             idx[ 1 ] = 0; // idx == [ 1, 0 ]
01509             TS_ASSERT_EQUALS( w[ idx ], 1 );
01510             idx[ 0 ] = 2; // idx == [ 2, 0 ]
01511             TS_ASSERT_EQUALS( w[ idx ], 2 );
01512             idx[ 1 ] = 1; // idx == [ 2, 1 ]
01513             TS_ASSERT_EQUALS( w[ idx ], 4 );
01514             idx[ 1 ] = 2; // idx == [ 2, 2 ]
01515             TS_ASSERT_EQUALS( w[ idx ], 5 );
01516         }
01517         {
01518             // create a new tensor
01519             T34 t;
01520 
01521             // enumerate all elements
01522             for( std::size_t k = 0; k < T34::dataSize; ++k )
01523             {
01524                 t.m_data[ k ] = k;
01525             }
01526 
01527             // order should be
01528             //
01529             // idx[0] == 0  idx[0] == 1   idx[0] == 2   idx[0] == 3
01530             //
01531             // 0  1  2  3                                               idx[1] == 0
01532             //    4  5  6      10 11 12                                 idx[1] == 1
01533             //       7  8         13 14         16 17                   idx[1] == 2
01534             //          9            15            18            19     idx[1] == 3
01535 
01536             std::size_t idx[] = { 0, 0, 0 };
01537             TS_ASSERT_EQUALS( t[ idx ], 0 );
01538             idx[ 1 ] = 2; // idx == [ 0, 2, 0 ]
01539             TS_ASSERT_EQUALS( t[ idx ], 2 );
01540             idx[ 2 ] = 3; // idx == [ 0, 2, 3 ]
01541             TS_ASSERT_EQUALS( t[ idx ], 8 );
01542             idx[ 0 ] = 1; // idx == [ 1, 2, 3 ]
01543             TS_ASSERT_EQUALS( t[ idx ], 14 );
01544             idx[ 1 ] = 1; // idx == [ 1, 1, 3 ]
01545             TS_ASSERT_EQUALS( t[ idx ], 12 );
01546             idx[ 0 ] = 3; // idx == [ 3, 1, 3 ]
01547             TS_ASSERT_EQUALS( t[ idx ], 15 );
01548             idx[ 2 ] = 0; // idx == [ 3, 1, 0 ]
01549             TS_ASSERT_EQUALS( t[ idx ], 6 );
01550             idx[ 1 ] = 3; // idx == [ 3, 3, 0 ]
01551             TS_ASSERT_EQUALS( t[ idx ], 9 );
01552             idx[ 1 ] = 2; // idx == [ 3, 2, 0 ]
01553             TS_ASSERT_EQUALS( t[ idx ], 8 );
01554         }
01555     }
01556 
01557     /**
01558      * Test if operator [] correctly maps permutations of the same set of indices to
01559      * the same array positions.
01560      */
01561     void testWTensorBaseSymAccessOperatorPermutations()
01562     {
01563         typedef WTensorBaseSym< 3, 4, std::size_t > T34;
01564 
01565         T34 t;
01566 
01567         // enumerate all elements
01568         for( std::size_t k = 0; k < T34::dataSize; ++k )
01569         {
01570             t.m_data[ k ] = k;
01571         }
01572 
01573         // create some index set permutations
01574         std::size_t idx1[ 3 ][ 3 ] = { { 0, 0, 1 }, // NOLINT no extra lines for { or } in an array initialization
01575                                        { 0, 1, 0 }, // NOLINT
01576                                        { 1, 0, 0 } }; // NOLINT
01577 
01578         std::size_t idx2[ 6 ][ 3 ] = { { 0, 1, 2 }, // NOLINT
01579                                        { 0, 2, 1 }, // NOLINT
01580                                        { 1, 2, 0 }, // NOLINT
01581                                        { 2, 1, 0 }, // NOLINT
01582                                        { 1, 0, 2 }, // NOLINT
01583                                        { 2, 1, 0 } }; // NOLINT
01584 
01585         std::size_t idx3[ 3 ][ 3 ] = { { 0, 0, 3 }, // NOLINT
01586                                        { 0, 3, 0 }, // NOLINT
01587                                        { 3, 0, 0 } }; // NOLINT
01588 
01589         std::size_t idx4[ 6 ][ 3 ] = { { 0, 3, 2 }, // NOLINT
01590                                        { 0, 2, 3 }, // NOLINT
01591                                        { 3, 2, 0 }, // NOLINT
01592                                        { 2, 3, 0 }, // NOLINT
01593                                        { 3, 0, 2 }, // NOLINT
01594                                        { 2, 3, 0 } }; // NOLINT
01595 
01596         // operator [] should map any permutation of a set of indices onto the same array position
01597         TS_ASSERT_EQUALS( t[ idx1[ 0 ] ], t[ idx1[ 1 ] ] );
01598         TS_ASSERT_EQUALS( t[ idx1[ 1 ] ], t[ idx1[ 2 ] ] );
01599 
01600         TS_ASSERT_EQUALS( t[ idx2[ 0 ] ], t[ idx2[ 1 ] ] );
01601         TS_ASSERT_EQUALS( t[ idx2[ 1 ] ], t[ idx2[ 2 ] ] );
01602         TS_ASSERT_EQUALS( t[ idx2[ 2 ] ], t[ idx2[ 3 ] ] );
01603         TS_ASSERT_EQUALS( t[ idx2[ 3 ] ], t[ idx2[ 4 ] ] );
01604         TS_ASSERT_EQUALS( t[ idx2[ 4 ] ], t[ idx2[ 5 ] ] );
01605 
01606         TS_ASSERT_EQUALS( t[ idx3[ 0 ] ], t[ idx3[ 1 ] ] );
01607         TS_ASSERT_EQUALS( t[ idx3[ 1 ] ], t[ idx3[ 2 ] ] );
01608 
01609         TS_ASSERT_EQUALS( t[ idx4[ 0 ] ], t[ idx4[ 1 ] ] );
01610         TS_ASSERT_EQUALS( t[ idx4[ 1 ] ], t[ idx4[ 2 ] ] );
01611         TS_ASSERT_EQUALS( t[ idx4[ 2 ] ], t[ idx4[ 3 ] ] );
01612         TS_ASSERT_EQUALS( t[ idx4[ 3 ] ], t[ idx4[ 4 ] ] );
01613         TS_ASSERT_EQUALS( t[ idx4[ 4 ] ], t[ idx4[ 5 ] ] );
01614 
01615         // permutations of different index sets may never map onto the same position
01616         TS_ASSERT_DIFFERS( t[ idx1[ 0 ] ], t[ idx2[ 0 ] ] );
01617         TS_ASSERT_DIFFERS( t[ idx1[ 1 ] ], t[ idx2[ 5 ] ] );
01618         TS_ASSERT_DIFFERS( t[ idx2[ 0 ] ], t[ idx4[ 4 ] ] );
01619         TS_ASSERT_DIFFERS( t[ idx2[ 0 ] ], t[ idx3[ 2 ] ] );
01620         TS_ASSERT_DIFFERS( t[ idx2[ 3 ] ], t[ idx3[ 1 ] ] );
01621         TS_ASSERT_DIFFERS( t[ idx3[ 0 ] ], t[ idx2[ 0 ] ] );
01622         TS_ASSERT_DIFFERS( t[ idx3[ 1 ] ], t[ idx4[ 3 ] ] );
01623         TS_ASSERT_DIFFERS( t[ idx3[ 0 ] ], t[ idx1[ 2 ] ] );
01624         TS_ASSERT_DIFFERS( t[ idx4[ 2 ] ], t[ idx1[ 0 ] ] );
01625         TS_ASSERT_DIFFERS( t[ idx4[ 5 ] ], t[ idx3[ 2 ] ] );
01626     }
01627 
01628     /**
01629      * Test the std::vector version of operator [] for correct handling of
01630      * various input vector sizes.
01631      */
01632     void testWTensorBaseSymVectorAccess()
01633     {
01634         typedef WTensorBaseSym< 4, 4, double > T44;
01635         typedef WTensorBaseSym< 1, 4, double > T14;
01636         typedef WTensorBaseSym< 6, 2, double > T62;
01637 
01638         {
01639             T44 t;
01640 
01641             // test a vector of invalid size
01642             std::vector< int > idx;
01643 
01644             // this should throw a WException (using the WAssert macro)
01645             TS_ASSERT_THROWS( t[ idx ], WException );
01646 
01647             idx.push_back( 0 ); // idx == [ 0 ]
01648             TS_ASSERT_THROWS( t[ idx ], WException );
01649             idx.push_back( 1 ); // idx == [ 0, 1 ]
01650             TS_ASSERT_THROWS( t[ idx ], WException );
01651             idx.push_back( 2 ); // idx == [ 0, 1, 2 ]
01652             TS_ASSERT_THROWS( t[ idx ], WException );
01653 
01654             idx.push_back( 3 ); // idx == [ 0, 1, 2, 3 ]
01655             // now idx has the correct size and all valid indices
01656             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
01657 
01658             // a larger vector should also work
01659             idx.push_back( 456 ); // idx == [ 0, 0, 2, 0, 456 ]
01660 
01661             // this should simply ignore all values after the 4th
01662             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
01663 
01664             idx.push_back( -1 );
01665             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
01666 
01667             // bounds checking on the indices is done by the array version of operator [],
01668             // which is called by the vector version
01669             // I'll add some tests here though, in case this changes in the future
01670             idx[ 0 ] = -1;
01671             TS_ASSERT_THROWS( t[ idx ], WException );
01672 
01673             idx[ 0 ] = 4;
01674             TS_ASSERT_THROWS( t[ idx ], WException );
01675 
01676             idx[ 0 ] = 3;
01677             idx[ 3 ] = -1;
01678             TS_ASSERT_THROWS( t[ idx ], WException );
01679 
01680             idx[ 3 ] = 4;
01681             TS_ASSERT_THROWS( t[ idx ], WException );
01682 
01683             idx[ 3 ] = 2;
01684             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
01685         }
01686         {
01687             T14 t;
01688 
01689             std::vector< int > idx;
01690             TS_ASSERT_THROWS( t[ idx ], WException );
01691 
01692             idx.push_back( 0 ); // idx == [ 0 ]
01693             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
01694 
01695             idx.push_back( 3 ); // idx == [ 0, 3 ]
01696             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
01697 
01698             idx.push_back( 456 ); // idx == [ 0, 3, 456 ]
01699             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
01700 
01701             idx.push_back( -1 );
01702             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
01703         }
01704         {
01705             T62 t;
01706 
01707             std::vector< int > idx;
01708             TS_ASSERT_THROWS( t[ idx ], WException );
01709 
01710             idx.push_back( 0 ); // idx == [ 0 ]
01711             TS_ASSERT_THROWS( t[ idx ], WException );
01712             idx.push_back( 1 ); // idx == [ 0, 1 ]
01713             TS_ASSERT_THROWS( t[ idx ], WException );
01714             idx.push_back( 0 ); // idx == [ 0, 1, 0 ]
01715             TS_ASSERT_THROWS( t[ idx ], WException );
01716             idx.push_back( 1 );
01717             TS_ASSERT_THROWS( t[ idx ], WException );
01718             idx.push_back( 1 );
01719             TS_ASSERT_THROWS( t[ idx ], WException );
01720             idx.push_back( 0 );
01721             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
01722 
01723             idx.push_back( 456 );
01724             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
01725 
01726             idx.push_back( -1 );
01727             TS_ASSERT_THROWS_NOTHING( t[ idx ] );
01728 
01729             T62 const w;
01730             TS_ASSERT_THROWS_NOTHING( w[ idx ] );
01731         }
01732     }
01733 
01734     /**
01735      * Test if operator == works correctly.
01736      */
01737     void testWTensorBaseSymCompareOperator()
01738     {
01739         typedef WTensorBaseSym< 1, 7, double > T17;
01740         typedef WTensorBaseSym< 3, 2, int > T32;
01741         typedef WTensorBaseSym< 0, 0, float > T00;
01742 
01743         {
01744             T17 t, m;
01745 
01746             // two tensors of the same type should be initialized to the same values
01747             TS_ASSERT( t == m );
01748             TS_ASSERT( m == t );
01749 
01750             // a tensor should always be equal to itself
01751             TS_ASSERT( t == t );
01752             TS_ASSERT( m == m );
01753 
01754             // change some values
01755             std::size_t idx[] = { 4 };
01756             t[ idx ] = 5.0;
01757 
01758             TS_ASSERT( !( t == m ) );
01759             TS_ASSERT( !( m == t ) );
01760             TS_ASSERT( t == t );
01761             TS_ASSERT( m == m );
01762 
01763             m[ idx ] = 5.0;
01764 
01765             TS_ASSERT( t == m );
01766             TS_ASSERT( m == t );
01767             TS_ASSERT( t == t );
01768             TS_ASSERT( m == m );
01769 
01770             idx[ 0 ] = 2;
01771             m[ idx ] = 543543.0;
01772 
01773             TS_ASSERT( !( t == m ) );
01774             TS_ASSERT( !( m == t ) );
01775             TS_ASSERT( t == t );
01776             TS_ASSERT( m == m );
01777 
01778             // copying a tensor should lead to the respective tensors being equal
01779             t = m;
01780             TS_ASSERT( t == m );
01781             TS_ASSERT( m == t );
01782             TS_ASSERT( t == t );
01783             TS_ASSERT( m == m );
01784 
01785             // test const
01786             T17 const ct, cm;
01787             TS_ASSERT( ct == cm );
01788             TS_ASSERT( cm == ct );
01789             TS_ASSERT( ct == ct );
01790             TS_ASSERT( cm == cm );
01791         }
01792         {
01793             T32 t, m;
01794 
01795             std::size_t idx[] = { 0, 0, 0 };
01796 
01797             // two tensors of the same type should be initialized to the same values
01798             TS_ASSERT( t == m );
01799             TS_ASSERT( m == t );
01800 
01801             // a tensor should always be equal to itself
01802             TS_ASSERT( t == t );
01803             TS_ASSERT( m == m );
01804 
01805             idx[ 1 ] = 1;
01806 
01807             m[ idx ] = -5643;
01808 
01809             TS_ASSERT( !( t == m ) );
01810             TS_ASSERT( !( m == t ) );
01811             TS_ASSERT( t == t );
01812             TS_ASSERT( m == m );
01813 
01814             t = m;
01815 
01816             TS_ASSERT( t == m );
01817             TS_ASSERT( m == t );
01818             TS_ASSERT( t == t );
01819             TS_ASSERT( m == m );
01820 
01821             idx[ 1 ] = 0;
01822 
01823             t[ idx ] = 564;
01824 
01825             TS_ASSERT( !( t == m ) );
01826             TS_ASSERT( !( m == t ) );
01827             TS_ASSERT( t == t );
01828             TS_ASSERT( m == m );
01829 
01830             t.m_data[ 0 ] = 5;
01831             t.m_data[ 1 ] = -65464;
01832             t.m_data[ 2 ] = 89;
01833             t.m_data[ 3 ] = 3276;
01834 
01835             m.m_data[ 0 ] = -5;
01836             m.m_data[ 1 ] = 65464;
01837             m.m_data[ 2 ] = -89;
01838             m.m_data[ 3 ] = -3276;
01839 
01840             TS_ASSERT( !( t == m ) );
01841             TS_ASSERT( !( m == t ) );
01842             TS_ASSERT( t == t );
01843             TS_ASSERT( m == m );
01844         }
01845         {
01846             T00 t, m;
01847 
01848             // two tensors of the same type should be initialized to the same values
01849             TS_ASSERT( t == m );
01850             TS_ASSERT( m == t );
01851 
01852             // a tensor should always be equal to itself
01853             TS_ASSERT( t == t );
01854             TS_ASSERT( m == m );
01855 
01856             t.m_data = 2;
01857 
01858             TS_ASSERT( !( t == m ) );
01859             TS_ASSERT( !( m == t ) );
01860             TS_ASSERT( t == t );
01861             TS_ASSERT( m == m );
01862 
01863             m.m_data = 2;
01864 
01865             TS_ASSERT( t == m );
01866             TS_ASSERT( m == t );
01867             TS_ASSERT( t == t );
01868             TS_ASSERT( m == m );
01869         }
01870     }
01871 
01872     /**
01873      * Test if operator != works correctly.
01874      */
01875     void testWTensorBaseSymCompareOperator2()
01876     {
01877         typedef WTensorBaseSym< 3, 3, int > T33;
01878         typedef WTensorBaseSym< 0, 0, int > T00;
01879 
01880         {
01881             T33 t, m;
01882 
01883             // two new instances should never not be equal
01884             TS_ASSERT( !( t != m ) );
01885             TS_ASSERT( !( m != t ) );
01886 
01887             // a tensor should never not be equal to itself
01888             TS_ASSERT( !( t != t ) );
01889             TS_ASSERT( !( m != m ) );
01890 
01891             // change some elements
01892             t.m_data[ 4 ] = -23467;
01893 
01894             TS_ASSERT( t != m );
01895             TS_ASSERT( m != t );
01896             TS_ASSERT( !( t != t ) );
01897             TS_ASSERT( !( m != m ) );
01898 
01899             t = m;
01900             TS_ASSERT( !( t != m ) );
01901             TS_ASSERT( !( m != t ) );
01902 
01903             t.m_data[ 0 ] = 1;
01904             TS_ASSERT( t != m );
01905             TS_ASSERT( m != t );
01906             TS_ASSERT( !( t != t ) );
01907             TS_ASSERT( !( m != m ) );
01908 
01909             t = m;
01910             TS_ASSERT( !( t != m ) );
01911             TS_ASSERT( !( m != t ) );
01912             TS_ASSERT( !( t != t ) );
01913             TS_ASSERT( !( m != m ) );
01914 
01915             t.m_data[ 9 ] = -1;
01916             TS_ASSERT( t != m );
01917             TS_ASSERT( m != t );
01918             TS_ASSERT( !( t != t ) );
01919             TS_ASSERT( !( m != m ) );
01920 
01921             // test const
01922             T33 const ct, cm;
01923             TS_ASSERT( !( ct != cm ) );
01924             TS_ASSERT( !( cm != ct ) );
01925             TS_ASSERT( !( ct != ct ) );
01926             TS_ASSERT( !( cm != cm ) );
01927         }
01928 
01929         {
01930             T00 t, m;
01931 
01932             TS_ASSERT( !( t != m ) );
01933             TS_ASSERT( !( m != t ) );
01934             TS_ASSERT( !( t != t ) );
01935             TS_ASSERT( !( m != m ) );
01936 
01937             t.m_data = 2;
01938 
01939             TS_ASSERT( t != m );
01940             TS_ASSERT( m != t );
01941             TS_ASSERT( !( t != t ) );
01942             TS_ASSERT( !( m != m ) );
01943 
01944             m.m_data = 2;
01945 
01946             TS_ASSERT( !( t != m ) );
01947             TS_ASSERT( !( m != t ) );
01948             TS_ASSERT( !( t != t ) );
01949             TS_ASSERT( !( m != m ) );
01950         }
01951     }
01952 };
01953 
01954 /**
01955  * A class that tests the WTensorFunc template.
01956  */
01957 class WTensorFuncTest : public CxxTest::TestSuite
01958 {
01959 public:
01960     /**
01961      * Test operator () error conditions.
01962      */
01963     void testAccessOperatorErrors()
01964     {
01965         // first test with an asymmetric tensor base
01966         typedef WTensorFunc< WTensorBase, 3, 3, double > F33;
01967         typedef WTensorFunc< WTensorBase, 1, 5, int > F15;
01968 
01969         {
01970             F33 f;
01971 
01972             // try some valid indices
01973             TS_ASSERT_THROWS_NOTHING( f( 0, 0, 0 ) );
01974             TS_ASSERT_THROWS_NOTHING( f( 1, 0, 0 ) );
01975             TS_ASSERT_THROWS_NOTHING( f( 2, 2, 2 ) );
01976             TS_ASSERT_THROWS_NOTHING( f( 1, 1, 1 ) );
01977             TS_ASSERT_THROWS_NOTHING( f( 1, 0, 2 ) );
01978             TS_ASSERT_THROWS_NOTHING( f( 0, 2, 0 ) );
01979 
01980             // try some invalid indices
01981             // negative indices are not allowed as the parameters are of type std::size_t
01982             TS_ASSERT_THROWS( f( 0, 0, 3 ), WException );
01983             TS_ASSERT_THROWS( f( 0, 654465, 0 ), WException );
01984             TS_ASSERT_THROWS( f( 4, 0, 0 ), WException );
01985             TS_ASSERT_THROWS( f( 0, 0, 45 ), WException );
01986             TS_ASSERT_THROWS( f( 0, 64, 0 ), WException );
01987             TS_ASSERT_THROWS( f( 792, 981, 5645 ), WException );
01988         }
01989         {
01990             F15 f;
01991 
01992             TS_ASSERT_THROWS_NOTHING( f( 0 ) );
01993             TS_ASSERT_THROWS_NOTHING( f( 1 ) );
01994             TS_ASSERT_THROWS_NOTHING( f( 2 ) );
01995             TS_ASSERT_THROWS_NOTHING( f( 3 ) );
01996             TS_ASSERT_THROWS_NOTHING( f( 4 ) );
01997 
01998             TS_ASSERT_THROWS( f( 5 ), WException );
01999             TS_ASSERT_THROWS( f( 5436 ), WException );
02000         }
02001 
02002         // now try a symmetric tensor base
02003         typedef WTensorFunc< WTensorBaseSym, 2, 4, double > F24;
02004 
02005         {
02006             F24 f;
02007 
02008             TS_ASSERT_THROWS_NOTHING( f( 0, 0 ) );
02009             TS_ASSERT_THROWS_NOTHING( f( 3, 0 ) );
02010             TS_ASSERT_THROWS_NOTHING( f( 2, 3 ) );
02011             TS_ASSERT_THROWS_NOTHING( f( 3, 3 ) );
02012             TS_ASSERT_THROWS_NOTHING( f( 0, 1 ) );
02013 
02014             TS_ASSERT_THROWS( f( 4, 0 ), WException );
02015             TS_ASSERT_THROWS( f( 3, 457 ), WException );
02016         }
02017     }
02018 
02019     /**
02020      * Test if operator () returns the correct elements.
02021      */
02022     void testAccessOperator()
02023     {
02024         typedef WTensorFunc< WTensorBase, 6, 2, std::size_t > F62;
02025         typedef WTensorBase< 6, 2, std::size_t > Base62;
02026 
02027         F62 f;
02028         Base62& b = f;
02029 
02030         for( std::size_t k = 0; k < 64; ++k )
02031         {
02032             b.m_data[ k ] = k;
02033         }
02034 
02035         TS_ASSERT_EQUALS( f( 0, 0, 0, 0, 0, 0 ), 0 );
02036         TS_ASSERT_EQUALS( f( 0, 0, 0, 1, 0, 1 ), 5 );
02037         TS_ASSERT_EQUALS( f( 1, 1, 1, 0, 0, 0 ), 56 );
02038         TS_ASSERT_EQUALS( f( 0, 1, 0, 0, 0, 1 ), 17 );
02039         TS_ASSERT_EQUALS( f( 0, 0, 1, 0, 1, 0 ), 10 );
02040         TS_ASSERT_EQUALS( f( 1, 0, 1, 0, 0, 1 ), 41 );
02041         TS_ASSERT_EQUALS( f( 1, 1, 1, 1, 1, 1 ), 63 );
02042 
02043         F62 const& w = f;
02044         TS_ASSERT_EQUALS( w( 0, 0, 0, 0, 0, 0 ), 0 );
02045         TS_ASSERT_EQUALS( w( 0, 0, 0, 1, 0, 1 ), 5 );
02046         TS_ASSERT_EQUALS( w( 1, 1, 1, 0, 0, 0 ), 56 );
02047         TS_ASSERT_EQUALS( w( 0, 1, 0, 0, 0, 1 ), 17 );
02048         TS_ASSERT_EQUALS( w( 0, 0, 1, 0, 1, 0 ), 10 );
02049         TS_ASSERT_EQUALS( w( 1, 0, 1, 0, 0, 1 ), 41 );
02050         TS_ASSERT_EQUALS( w( 1, 1, 1, 1, 1, 1 ), 63 );
02051     }
02052 
02053     /**
02054      * Test if operator () keeps the symmetry of a WTensorBaseSym intact.
02055      */
02056     void testAccessOperatorSymmetry()
02057     {
02058         typedef WTensorFunc< WTensorBaseSym, 4, 5, std::size_t > F45;
02059         typedef WTensorBaseSym< 4, 5, std::size_t > Base45;
02060 
02061         F45 f;
02062         Base45& b = f;
02063 
02064         for( std::size_t k = 0; k < 70; ++k )
02065         {
02066             b.m_data[ k ] = k;
02067         }
02068 
02069         std::size_t idx[ 8 ][ 6 ] = { { 0, 1, 2, 4 }, // NOLINT no extra line per { or }
02070                                       { 3, 2, 4, 0 }, // NOLINT
02071                                       { 4, 4, 4, 0 }, // NOLINT
02072                                       { 0, 0, 0, 0 }, // NOLINT
02073                                       { 3, 4, 0, 1 }, // NOLINT
02074                                       { 2, 2, 2, 2 }, // NOLINT
02075                                       { 4, 4, 4, 4 }, // NOLINT
02076                                       { 2, 2, 0, 3 } };  // NOLINT
02077 
02078         TS_ASSERT( f( 0, 1, 2, 4 ) == f[ idx[ 0 ] ] );
02079         TS_ASSERT( f( 1, 0, 2, 4 ) == f[ idx[ 0 ] ] );
02080         TS_ASSERT( f( 4, 1, 0, 2 ) == f[ idx[ 0 ] ] );
02081         TS_ASSERT( f( 0, 3, 2, 4 ) == f[ idx[ 1 ] ] );
02082         TS_ASSERT( f( 0, 4, 4, 4 ) == f[ idx[ 2 ] ] );
02083         TS_ASSERT( f( 4, 0, 4, 4 ) == f[ idx[ 2 ] ] );
02084         TS_ASSERT( f( 0, 0, 0, 0 ) == f[ idx[ 3 ] ] );
02085         TS_ASSERT( f( 0, 1, 3, 4 ) == f[ idx[ 4 ] ] );
02086         TS_ASSERT( f( 2, 2, 2, 2 ) == f[ idx[ 5 ] ] );
02087         TS_ASSERT( f( 4, 4, 4, 4 ) == f[ idx[ 6 ] ] );
02088         TS_ASSERT( f( 2, 2, 3, 0 ) == f[ idx[ 7 ] ] );
02089         TS_ASSERT( f( 2, 3, 0, 2 ) == f[ idx[ 7 ] ] );
02090 
02091         F45 const& w = f;
02092         TS_ASSERT( w( 0, 1, 2, 4 ) == w[ idx[ 0 ] ] );
02093         TS_ASSERT( w( 1, 0, 2, 4 ) == w[ idx[ 0 ] ] );
02094         TS_ASSERT( w( 4, 1, 0, 2 ) == w[ idx[ 0 ] ] );
02095         TS_ASSERT( w( 0, 3, 2, 4 ) == w[ idx[ 1 ] ] );
02096         TS_ASSERT( w( 0, 4, 4, 4 ) == w[ idx[ 2 ] ] );
02097         TS_ASSERT( w( 4, 0, 4, 4 ) == w[ idx[ 2 ] ] );
02098         TS_ASSERT( w( 0, 0, 0, 0 ) == w[ idx[ 3 ] ] );
02099         TS_ASSERT( w( 0, 1, 3, 4 ) == w[ idx[ 4 ] ] );
02100         TS_ASSERT( w( 2, 2, 2, 2 ) == w[ idx[ 5 ] ] );
02101         TS_ASSERT( w( 4, 4, 4, 4 ) == w[ idx[ 6 ] ] );
02102         TS_ASSERT( w( 2, 2, 3, 0 ) == w[ idx[ 7 ] ] );
02103         TS_ASSERT( w( 2, 3, 0, 2 ) == w[ idx[ 7 ] ] );
02104     }
02105 };
02106 
02107 /**
02108  * Test all typecasts and copy operators that copy from another type.
02109  */
02110 class WTensorTypesTest : public CxxTest::TestSuite
02111 {
02112 public:
02113     /**
02114      * Test constructing a WTensorBase from a WTensorBaseSym.
02115      */
02116     void testCopyContructorBaseFromBaseSym()
02117     {
02118         typedef WTensorBaseSym< 2, 4, double > S24;
02119         typedef WTensorBase< 2, 4, double > T24;
02120         typedef WTensorBaseSym< 1, 4, double > S14;
02121         typedef WTensorBase< 1, 4, double > T14;
02122         typedef WTensorBaseSym< 0, 4, double > S04;
02123         typedef WTensorBase< 0, 4, double > T04;
02124 
02125         // construct a symmetric tensor and initialize an asymmetric tensor from it
02126         {
02127             S24 s;
02128 
02129             std::size_t idx[ 2 ] = { 0, 3 };
02130 
02131             s[ idx ] = -2.0;
02132 
02133             idx[ 0 ] = 3;
02134             idx[ 1 ] = 2;
02135 
02136             s[ idx ] = 3.0;
02137 
02138             TS_ASSERT_THROWS_NOTHING( T24 t = T24( s );
02139                                       t.getOrder() );
02140             T24 t = T24( s );
02141 
02142             TS_ASSERT_EQUALS( t[ idx ], 3.0 );
02143 
02144             idx[ 0 ] = 3;
02145             idx[ 1 ] = 0;
02146 
02147             TS_ASSERT_EQUALS( t[ idx ], -2.0 );
02148 
02149             idx[ 0 ] = 1;
02150 
02151             TS_ASSERT_EQUALS( t[ idx ], 0.0 );
02152         }
02153         // order = 1 is kind of a special case, as there is only one "permutation" of a single index
02154         {
02155             S14 s;
02156 
02157             std::size_t idx[ 1 ] = { 0 };
02158 
02159             s[ idx ] = -2.0;
02160 
02161             idx[ 0 ] = 3;
02162 
02163             s[ idx ] = 3.0;
02164 
02165             TS_ASSERT_THROWS_NOTHING( T14 t = T14( s );
02166                                       t.getOrder() );
02167             T14 t = T14( s );
02168 
02169             TS_ASSERT_EQUALS( t[ idx ], 3.0 );
02170             idx[ 0 ] = 0;
02171             TS_ASSERT_EQUALS( t[ idx ], -2.0 );
02172             idx[ 0 ] = 1;
02173             TS_ASSERT_EQUALS( t[ idx ], 0.0 );
02174             idx[ 0 ] = 2;
02175             TS_ASSERT_EQUALS( t[ idx ], 0.0 );
02176         }
02177         // now test the order = 0 version
02178         {
02179             S04 s;
02180 
02181             std::size_t* idx = NULL;
02182             s[ idx ] = 5.0;
02183 
02184             TS_ASSERT_THROWS_NOTHING( T04 t = T04( s );
02185                                       t.getOrder() );
02186             T04 t = T04( s );
02187 
02188             TS_ASSERT_EQUALS( t[ idx ], 5.0 );
02189         }
02190     }
02191 
02192     /**
02193      * Test assignment of a WTensorBaseSym to a WTensorBase.
02194      */
02195     void testCopyOperatorBaseFromSym()
02196     {
02197         // same test as the last one, only this time we use the copy operator
02198         typedef WTensorBaseSym< 2, 4, double > S24;
02199         typedef WTensorBase< 2, 4, double > T24;
02200         typedef WTensorBaseSym< 1, 4, double > S14;
02201         typedef WTensorBase< 1, 4, double > T14;
02202         typedef WTensorBaseSym< 0, 4, double > S04;
02203         typedef WTensorBase< 0, 4, double > T04;
02204 
02205         {
02206             S24 s;
02207             T24 t;
02208 
02209             std::size_t idx[ 2 ] = { 0, 3 };
02210 
02211             s[ idx ] = -2.0;
02212 
02213             idx[ 0 ] = 3;
02214             idx[ 1 ] = 2;
02215 
02216             s[ idx ] = 3.0;
02217 
02218             TS_ASSERT_THROWS_NOTHING( t = s );
02219             t = s;
02220 
02221             TS_ASSERT_EQUALS( t[ idx ], 3.0 );
02222 
02223             idx[ 0 ] = 3;
02224             idx[ 1 ] = 0;
02225 
02226             TS_ASSERT_EQUALS( t[ idx ], -2.0 );
02227 
02228             idx[ 0 ] = 1;
02229 
02230             TS_ASSERT_EQUALS( t[ idx ], 0.0 );
02231         }
02232         // order = 1 is kind of a special case, as there is only one "permutation" of a single index
02233         {
02234             S14 s;
02235             T14 t;
02236 
02237             std::size_t idx[ 1 ] = { 0 };
02238 
02239             s[ idx ] = -2.0;
02240 
02241             idx[ 0 ] = 3;
02242 
02243             s[ idx ] = 3.0;
02244 
02245             TS_ASSERT_THROWS_NOTHING( t = s );
02246             t = s;
02247 
02248             TS_ASSERT_EQUALS( t[ idx ], 3.0 );
02249             idx[ 0 ] = 0;
02250             TS_ASSERT_EQUALS( t[ idx ], -2.0 );
02251             idx[ 0 ] = 1;
02252             TS_ASSERT_EQUALS( t[ idx ], 0.0 );
02253             idx[ 0 ] = 2;
02254             TS_ASSERT_EQUALS( t[ idx ], 0.0 );
02255         }
02256         // now test the order = 0 version
02257         {
02258             S04 s;
02259             T04 t;
02260 
02261             std::size_t* idx = NULL;
02262             s[ idx ] = 5.0;
02263 
02264             TS_ASSERT_THROWS_NOTHING( t = s );
02265             t = s;
02266 
02267             TS_ASSERT_EQUALS( t[ idx ], 5.0 );
02268         }
02269     }
02270 
02271     /**
02272      * Test casts from any tensorbase of order 0 to a value.
02273      */
02274     void testCastTensorToValue()
02275     {
02276         // create some "scalar tensors" and cast them to their respective Data_T
02277         {
02278             // types
02279             WTensorFunc< WTensorBase, 0, 1, double > td;
02280             WTensorFunc< WTensorBase, 0, 0, float > tf;
02281             WTensorFunc< WTensorBase, 0, 456, int > ti;
02282 
02283             // implicitly cast to Data_T
02284             td() = 3.0;
02285             double d = td;
02286             TS_ASSERT_EQUALS( d, 3.0 );
02287 
02288             tf() = 3.0f;
02289             float f = tf;
02290             TS_ASSERT_EQUALS( f, 3.0f );
02291 
02292             ti() = 3;
02293             int i = ti;
02294             TS_ASSERT_EQUALS( i, 3 );
02295         }
02296         // do the same test with symmetric tensors
02297         {
02298             WTensorFunc< WTensorBase, 0, 1, double > td;
02299             WTensorFunc< WTensorBase, 0, 0, float > tf;
02300             WTensorFunc< WTensorBase, 0, 456, int > ti;
02301 
02302             td() = 3.0;
02303             double d = td;
02304             TS_ASSERT_EQUALS( d, 3.0 );
02305 
02306             tf() = 3.0f;
02307             float f = tf;
02308             TS_ASSERT_EQUALS( f, 3.0f );
02309 
02310             ti() = 3;
02311             int i = ti;
02312             TS_ASSERT_EQUALS( i, 3 );
02313         }
02314     }
02315 
02316     /**
02317      * Test casts from any tensorbase of order 1 to a WValue.
02318      */
02319     void testCastTensorToVector()
02320     {
02321         {
02322             WTensorFunc< WTensorBase, 1, 5, double > t;
02323             t( 0 ) = -9.765;
02324             t( 1 ) = 154.06;
02325             t( 4 ) = -57.0;
02326 
02327             WValue< double > v = t;
02328 
02329             TS_ASSERT_EQUALS( v.size(), 5 );
02330 
02331             TS_ASSERT_EQUALS( v[ 0 ], -9.765 );
02332             TS_ASSERT_EQUALS( v[ 1 ], 154.06 );
02333             TS_ASSERT_EQUALS( v[ 2 ], 0.0 );
02334             TS_ASSERT_EQUALS( v[ 3 ], 0.0 );
02335             TS_ASSERT_EQUALS( v[ 4 ], -57.0 );
02336         }
02337         {
02338             WTensorFunc< WTensorBaseSym, 1, 5, double > t;
02339             t( 0 ) = -9.765;
02340             t( 1 ) = 154.06;
02341             t( 4 ) = -57.0;
02342 
02343             WValue< double > v = t;
02344 
02345             TS_ASSERT_EQUALS( v.size(), 5 );
02346 
02347             TS_ASSERT_EQUALS( v[ 0 ], -9.765 );
02348             TS_ASSERT_EQUALS( v[ 1 ], 154.06 );
02349             TS_ASSERT_EQUALS( v[ 2 ], 0.0 );
02350             TS_ASSERT_EQUALS( v[ 3 ], 0.0 );
02351             TS_ASSERT_EQUALS( v[ 4 ], -57.0 );
02352         }
02353     }
02354 
02355     /**
02356      * Test casts from any tensorbase of order 2 to a WMatrix.
02357      */
02358     void testCastTensorToMatrix()
02359     {
02360         {
02361             WTensorFunc< WTensorBase, 2, 3, double > t;
02362             t( 0, 0 ) = -9.765;
02363             t( 1, 0 ) = 154.06;
02364             t( 2, 2 ) = -57.0;
02365 
02366             WMatrix< double > m = t;
02367 
02368             TS_ASSERT_EQUALS( m.getNbCols(), 3 );
02369             TS_ASSERT_EQUALS( m.getNbRows(), 3 );
02370 
02371             for( std::size_t i = 0; i < 3; ++i )
02372             {
02373                 for( std::size_t j = 0; j < 3; ++j )
02374                 {
02375                     TS_ASSERT_EQUALS( m( i, j ), t( i, j ) );
02376                 }
02377             }
02378         }
02379         {
02380             WTensorFunc< WTensorBaseSym, 2, 3, double > t;
02381             t( 0, 0 ) = -9.765;
02382             t( 1, 0 ) = 154.06;
02383             t( 2, 2 ) = -57.0;
02384 
02385             WMatrix< double > m = t;
02386 
02387             TS_ASSERT_EQUALS( m.getNbCols(), 3 );
02388             TS_ASSERT_EQUALS( m.getNbRows(), 3 );
02389 
02390             for( std::size_t i = 0; i < 3; ++i )
02391             {
02392                 for( std::size_t j = 0; j < 3; ++j )
02393                 {
02394                     TS_ASSERT_EQUALS( m( i, j ), t( i, j ) );
02395                 }
02396             }
02397         }
02398     }
02399 };
02400 
02401 /**
02402  * Test some utility functions.
02403  */
02404 class WTensorUtilityTest : public CxxTest::TestSuite
02405 {
02406 public:
02407     // the functions testet here are needed for the initialization of the
02408     // index permutation to array position mapping
02409     // note that these functions do not check for errors and are meant for internal use
02410     /**
02411      * Test iteration of indices.
02412      */
02413     void testIndexIteration()
02414     {
02415         boost::array< std::size_t, 3 > is;
02416         is.assign( 0 );   // is == ( 0, 0, 0 )
02417         std::vector< std::size_t > shouldBe( 3, 0 );
02418         shouldBe[ 2 ] = 1; // shouldBe == ( 0, 0, 1 )
02419 
02420         positionIterateOneStep< 3, 3 >( is );
02421         TS_ASSERT_SAME_DATA( &is[ 0 ], &shouldBe[ 0 ], 3 * sizeof( std::size_t ) );
02422 
02423         positionIterateOneStep< 3, 3 >( is );
02424         positionIterateOneStep< 3, 3 >( is );
02425         shouldBe[ 1 ] = 1;
02426         shouldBe[ 2 ] = 0; // shouldBe == ( 0, 1, 0 )
02427 
02428         TS_ASSERT_SAME_DATA( &is[ 0 ], &shouldBe[ 0 ], 3 * sizeof( std::size_t ) );
02429 
02430         // the dim = 2 case is more interesting
02431         positionIterateOneStep< 3, 2 >( is );
02432         positionIterateOneStep< 3, 2 >( is );
02433         shouldBe[ 0 ] = 1;
02434         shouldBe[ 1 ] = 0; // shouldBe == ( 1, 0, 0 )
02435 
02436         TS_ASSERT_SAME_DATA( &is[ 0 ], &shouldBe[ 0 ], 3 * sizeof( std::size_t ) );
02437 
02438         positionIterateOneStep< 3, 2 >( is );
02439         shouldBe[ 2 ] = 1;
02440 
02441         TS_ASSERT_SAME_DATA( &is[ 0 ], &shouldBe[ 0 ], 3 * sizeof( std::size_t ) );
02442     }
02443 
02444     /**
02445      * Test sorted iteration of indices.
02446      */
02447     void testIndexIterationSorted()
02448     {
02449         boost::array< std::size_t, 3 > v;
02450         v.assign( 0 );
02451 
02452         std::size_t numIter = WBinom< 5, 3 >::value - 1;
02453 
02454         // the indices should always be sorted
02455         for( std::size_t k = 0; k < numIter; ++k )
02456         {
02457             positionIterateSortedOneStep< 3, 3 >( v );
02458             TS_ASSERT( v[ 0 ] <= v[ 1 ] );
02459             TS_ASSERT( v[ 1 ] <= v[ 2 ] );
02460         }
02461 
02462         //after iterating numIter times, v should be ( 2, 2, 2 )
02463         TS_ASSERT_EQUALS( v[ 0 ], 2 );
02464         TS_ASSERT_EQUALS( v[ 1 ], 2 );
02465         TS_ASSERT_EQUALS( v[ 2 ], 2 );
02466 
02467         // now test the dim = 2 case
02468         v[ 0 ] = v[ 1 ] = v[ 2 ] = 0;
02469         numIter = WBinom< 4, 3 >::value - 1;
02470 
02471         // the indices should always be sorted
02472         for( std::size_t k = 0; k < numIter; ++k )
02473         {
02474             positionIterateSortedOneStep< 3, 2 >( v );
02475             TS_ASSERT( v[ 0 ] <= v[ 1 ] );
02476             TS_ASSERT( v[ 1 ] <= v[ 2 ] );
02477         }
02478 
02479         //after iterating numIter times, v should be ( 1, 1, 1 )
02480         TS_ASSERT_EQUALS( v[ 0 ], 1 );
02481         TS_ASSERT_EQUALS( v[ 1 ], 1 );
02482         TS_ASSERT_EQUALS( v[ 2 ], 1 );
02483     }
02484 };
02485 
02486 // restore WASSERT_AS_CASSERT flag
02487 #ifdef WASSERT_FLAG_CHANGED
02488 #define WASSERT_AS_CASSERT
02489 #undefine WASSERT_FLAG_CHANGED
02490 #endif
02491 
02492 #endif  // WTENSORBASE_TEST_H