OpenWalnut
1.4.0
|
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