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_H 00026 #define WTENSORBASE_H 00027 00028 #include <algorithm> 00029 #include <map> 00030 #include <vector> 00031 00032 #include <boost/static_assert.hpp> 00033 #include <boost/array.hpp> 00034 00035 #include "../WAssert.h" 00036 #include "WCompileTimeFunctions.h" 00037 #include "WMatrix.h" 00038 #include "WValue.h" 00039 00040 // TODO(reichenbach): Remove vectors (because of the enum dataSize). 00041 00042 // forward declaration of the test classes 00043 class WTensorFuncTest; 00044 class WTensorBaseTest; 00045 class WTensorBaseSymTest; 00046 00047 // forward declaration 00048 template< std::size_t order, std::size_t dim, typename Data_T > 00049 class WTensorBaseSym; 00050 00051 // ############################ utility functions #################################### 00052 00053 /** 00054 * Iterate a position in a multidimensional grid. 00055 * 00056 * This essentially creates a linear order on all positions in a tensor, where a position 00057 * is any valid allocation of indices. 00058 * 00059 * Example: for a tensor of order 2 and dimension 3, all possible positions are: 00060 * 00061 * ( 0, 0 ), ( 0, 1 ), ( 0, 2 ), ( 1, 0 ), ( 1, 1 ), ( 1, 2 ), ( 2, 0 ), ( 2, 1 ), ( 2, 2 ) 00062 * 00063 * \param pos The position to be iterated. 00064 */ 00065 template< std::size_t order, std::size_t dim > 00066 inline void positionIterateOneStep( boost::array< std::size_t, order >& pos ) // NOLINT, need a reference here 00067 { 00068 WAssert( pos.size() >= order, "" ); 00069 00070 for( std::size_t k = order - 1; k > 0; --k ) 00071 { 00072 if( pos[ k ] == dim - 1) 00073 { 00074 pos[ k ] = 0; 00075 } 00076 else 00077 { 00078 ++( pos[ k ] ); 00079 return; 00080 } 00081 } 00082 ++( pos[ 0 ] ); 00083 } 00084 00085 /** 00086 * Iterate a sorted position in a multidimensional grid. 00087 * 00088 * This essentially creates a linear order on all sorted positions in a tensor, where a sorted position 00089 * is any valid allocation of indices where those indices are in ascending order. 00090 * 00091 * Example: for a tensor of order 2 and dimension 3, all possible sorted positions are: 00092 * 00093 * ( 0, 0 ), ( 0, 1 ), ( 0, 2 ), ( 1, 1 ), ( 1, 2 ), ( 2, 2 ) 00094 * 00095 * The number of sorted positions of a tensor matches the number of elements that need to be stored 00096 * by the symmetric tensor of the same order and dimension. 00097 * 00098 * \param pos The sorted(!) position to be iterated. 00099 */ 00100 template< std::size_t order, std::size_t dim > 00101 inline void positionIterateSortedOneStep( boost::array< std::size_t, order >& pos ) // NOLINT, need a reference here 00102 { 00103 WAssert( pos.size() >= order, "" ); 00104 00105 for( int k = order - 1; k > -1; --k ) 00106 { 00107 if( pos[ k ] != dim - 1 ) 00108 { 00109 ++( pos[ k ] ); 00110 for( std::size_t i = k + 1; i < order; ++i ) 00111 { 00112 pos[ i ] = pos[ k ]; 00113 } 00114 return; 00115 } 00116 } 00117 } 00118 00119 /** 00120 * Same as the version above, using no template arguments. 00121 * 00122 * \param order The order of the tensor. 00123 * \param dim The dimension of the tensor. 00124 * \param pos The sorted(!) position to be iterated. 00125 */ 00126 inline void positionIterateSortedOneStep( std::size_t order, std::size_t dim, std::vector< std::size_t >& pos ) // NOLINT, need a reference here 00127 { 00128 WAssert( pos.size() >= order, "" ); 00129 00130 for( int k = order - 1; k > -1; --k ) 00131 { 00132 if( pos[ k ] != dim - 1 ) 00133 { 00134 ++( pos[ k ] ); 00135 for( std::size_t i = k + 1; i < order; ++i ) 00136 { 00137 pos[ i ] = pos[ k ]; 00138 } 00139 return; 00140 } 00141 } 00142 } 00143 00144 // ############################# class WTensorBase<> ################################# 00145 /** 00146 * Normal tensor base class. 00147 * 00148 * \tparam order The order of the tensor. 00149 * \tparam dim The dimension of the tensor, i.e. the number of components 00150 * in each direction. 00151 * \tparam Data_T The datatype of the components, double by default. 00152 * 00153 * \note The type Data_T may not throw exceptions on construction, destruction or 00154 * during any assignment operator. 00155 * \note The dimension may not be 0. 00156 * 00157 * \see WTensor 00158 */ 00159 template< std::size_t order, std::size_t dim, typename Data_T > 00160 class WTensorBase 00161 { 00162 /** 00163 * For dim == 0, create an artificial compiler error. 00164 */ 00165 BOOST_STATIC_ASSERT( dim != 0 ); 00166 00167 // Make the appropriate tensor of order + 1 a friend, so it has access to the getPos() member. 00168 friend class WTensorBase< order + 1, dim, Data_T >; 00169 00170 // make the test class a friend 00171 friend class ::WTensorBaseTest; 00172 00173 // make the func test class a friend 00174 friend class ::WTensorFuncTest; 00175 00176 public: 00177 /** 00178 * Standard constructor. 00179 * 00180 * All elements are set to Data_T(). 00181 */ 00182 WTensorBase(); 00183 00184 /** 00185 * Copy constructor. 00186 * 00187 * \param t The tensor to copy from. 00188 */ 00189 WTensorBase( WTensorBase const& t ); // NOLINT 00190 00191 /** 00192 * Copy construct a WTensorBase from a WTensorBaseSym. 00193 * 00194 * \param t The symmetric tensor to copy from. 00195 */ 00196 explicit WTensorBase( WTensorBaseSym< order, dim, Data_T > const& t ); 00197 00198 /** 00199 * Copy operator. 00200 * 00201 * \param t The tensor to copy from. 00202 * 00203 * \return *this. 00204 */ 00205 WTensorBase const& operator = ( WTensorBase const& t ); 00206 00207 /** 00208 * Copy operator. 00209 * 00210 * \param t The symmetric tensor to copy from. 00211 * 00212 * \return *this. 00213 */ 00214 WTensorBase const& operator = ( WTensorBaseSym< order, dim, Data_T > const& t ); 00215 00216 /** 00217 * Get the dimension of this tensor. 00218 * 00219 * \return The dimension of this tensor. 00220 */ 00221 std::size_t getDimension() const; 00222 00223 /** 00224 * Get the order of this tensor. 00225 * 00226 * \return The order of this tensor. 00227 */ 00228 std::size_t getOrder() const; 00229 00230 /** 00231 * Get the element at a specific position. 00232 * 00233 * \param indices A std::vector of indices that has a size of at least order. 00234 * 00235 * \return A reference to the element. 00236 */ 00237 template< typename Index_T > 00238 Data_T& operator[] ( std::vector< Index_T > const& indices ); 00239 00240 /** 00241 * Get the element at a specific position. 00242 * 00243 * \param indices A std::vector of indices that has a size of at least order. 00244 * 00245 * \return A reference to the element. 00246 */ 00247 template< typename Index_T > 00248 Data_T const& operator[] ( std::vector< Index_T > const& indices ) const; 00249 00250 /** 00251 * Get the element at a specific position. 00252 * 00253 * \param indices An array of indices that has a size of at least order. 00254 * 00255 * \return A reference to the element. 00256 * 00257 * \note The array must have a length of at least order. 00258 */ 00259 template< typename Index_T > 00260 Data_T& operator[] ( Index_T indices[] ); 00261 00262 /** 00263 * Get the element at a specific position. 00264 * 00265 * \param indices An array of indices that has a size of at least order. 00266 * 00267 * \return A reference to the element. 00268 * 00269 * \note The array must have a length of at least order. 00270 */ 00271 template< typename Index_T > 00272 Data_T const& operator[] ( Index_T indices[] ) const; 00273 00274 /** 00275 * Compare this WTensorBase to another one. 00276 * 00277 * \param other The WBensorBase to compare to. 00278 * 00279 * \return True, iff this tensors' elements are equal to another tensors' elements. 00280 */ 00281 bool operator == ( WTensorBase const& other ) const; 00282 00283 /** 00284 * Compare this WTensorBase to another one. 00285 * 00286 * \param other The WBensorBase to compare to. 00287 * 00288 * \return True, iff this tensors' elements are not equal to another tensors' elements. 00289 */ 00290 bool operator != ( WTensorBase const& other ) const; 00291 00292 /** 00293 * Declare a compile-time constant as enum and not as static constant. 00294 */ 00295 enum 00296 { 00297 /** 00298 * The number of elements to store. 00299 */ 00300 dataSize = WPower< dim, order >::value 00301 }; 00302 00303 private: 00304 /** 00305 * Calculate the position of the element in the data vector. The function 00306 * is build recursively at compile-time. 00307 * 00308 * \param pos An array of indices. 00309 * 00310 * \return The position of the element. 00311 */ 00312 template< typename Index_T > 00313 static inline std::size_t getPos( Index_T pos[] ); 00314 00315 //! Stores all elements. 00316 //std::vector< Data_T > m_data; 00317 boost::array< Data_T, dataSize > m_data; 00318 }; 00319 00320 template< std::size_t order, std::size_t dim, typename Data_T > 00321 WTensorBase< order, dim, Data_T >::WTensorBase() 00322 { 00323 m_data.assign( Data_T() ); 00324 } 00325 00326 template< std::size_t order, std::size_t dim, typename Data_T > 00327 WTensorBase< order, dim, Data_T >::WTensorBase( WTensorBase const& t ) 00328 : m_data( t.m_data ) 00329 { 00330 } 00331 00332 template< std::size_t order, std::size_t dim, typename Data_T > 00333 WTensorBase< order, dim, Data_T >::WTensorBase( WTensorBaseSym< order, dim, Data_T > const& t ) 00334 { 00335 *this = t; 00336 } 00337 00338 template< std::size_t order, std::size_t dim, typename Data_T > 00339 WTensorBase< order, dim, Data_T > const& WTensorBase< order, dim, Data_T >::operator = ( WTensorBase const& t ) 00340 { 00341 m_data = t.m_data; 00342 return *this; 00343 } 00344 00345 template< std::size_t order, std::size_t dim, typename Data_T > 00346 WTensorBase< order, dim, Data_T > const& WTensorBase< order, dim, Data_T >::operator = ( WTensorBaseSym< order, dim, Data_T > const& t ) 00347 { 00348 boost::array< std::size_t, order > pos; 00349 pos.assign( 0 ); 00350 00351 for( std::size_t k = 0; k < dataSize; ++k ) 00352 { 00353 ( *this )[ &pos[ 0 ] ] = t[ &pos[ 0 ] ]; 00354 positionIterateOneStep< order, dim >( pos ); 00355 } 00356 00357 return *this; 00358 } 00359 00360 template< std::size_t order, std::size_t dim, typename Data_T > 00361 std::size_t WTensorBase< order, dim, Data_T >::getDimension() const 00362 { 00363 return dim; 00364 } 00365 00366 template< std::size_t order, std::size_t dim, typename Data_T > 00367 std::size_t WTensorBase< order, dim, Data_T >::getOrder() const 00368 { 00369 return order; 00370 } 00371 00372 template< std::size_t order, std::size_t dim, typename Data_T > 00373 template< typename Index_T > 00374 std::size_t WTensorBase< order, dim, Data_T >::getPos( Index_T pos[] ) 00375 { 00376 return WTensorBase< order - 1, dim, Data_T >::getPos( pos ) * dim + static_cast< std::size_t >( pos[ order - 1 ] ); 00377 } 00378 00379 template< std::size_t order, std::size_t dim, typename Data_T > 00380 template< typename Index_T > 00381 Data_T& WTensorBase< order, dim, Data_T >::operator[] ( std::vector< Index_T > const& indices ) 00382 { 00383 return const_cast< Data_T& >( static_cast< WTensorBase const& >( *this ).operator[] ( indices ) ); 00384 } 00385 00386 template< std::size_t order, std::size_t dim, typename Data_T > 00387 template< typename Index_T > 00388 Data_T const& WTensorBase< order, dim, Data_T >::operator[] ( std::vector< Index_T > const& indices ) const 00389 { 00390 WAssert( indices.size() >= order, "" ); 00391 return operator[] ( &indices[ 0 ] ); 00392 } 00393 00394 template< std::size_t order, std::size_t dim, typename Data_T > 00395 template< typename Index_T > 00396 Data_T& WTensorBase< order, dim, Data_T >::operator[] ( Index_T indices[] ) 00397 { 00398 return const_cast< Data_T& >( static_cast< WTensorBase const& >( *this ).operator[] ( indices ) ); 00399 } 00400 00401 template< std::size_t order, std::size_t dim, typename Data_T > 00402 template< typename Index_T > 00403 Data_T const& WTensorBase< order, dim, Data_T >::operator[] ( Index_T indices[] ) const 00404 { 00405 for( std::size_t k = 0; k < order; ++k ) 00406 { 00407 WAssert( static_cast< std::size_t >( indices[ k ] ) < dim, "" ); 00408 } 00409 std::size_t p = getPos( indices ); 00410 return m_data[ p ]; 00411 } 00412 00413 template< std::size_t order, std::size_t dim, typename Data_T > 00414 bool WTensorBase< order, dim, Data_T >::operator == ( WTensorBase const& other ) const 00415 { 00416 return m_data == other.m_data; 00417 } 00418 00419 template< std::size_t order, std::size_t dim, typename Data_T > 00420 bool WTensorBase< order, dim, Data_T >::operator != ( WTensorBase const& other ) const 00421 { 00422 return m_data != other.m_data; 00423 } 00424 00425 // ######################### WTensorBase for order == 0 ########################## 00426 00427 /** 00428 * \tparam dim The dimension of the tensor, i.e. the number of components 00429 * in each direction. 00430 * \tparam Data_T The datatype of the components, double by default. 00431 00432 * Specialization for order = 0. This essentially encapsulates a scalar. The purpose of 00433 * this specialization is compatibility for generic tensor functions. 00434 */ 00435 template< std::size_t dim, typename Data_T > 00436 class WTensorBase< 0, dim, Data_T > 00437 { 00438 // Make the appropriate tensor of order + 1 a friend, so it has access to the getPos() member. 00439 friend class WTensorBase< 1, dim, Data_T >; 00440 00441 // make the test class a friend 00442 friend class ::WTensorBaseTest; 00443 00444 // make the func test class a friend 00445 friend class ::WTensorFuncTest; 00446 00447 public: 00448 // implementations are inline as they are trivial 00449 /** 00450 * Standard constructor. 00451 * 00452 * All elements are set to Data_T(). 00453 */ 00454 WTensorBase() 00455 : m_data( Data_T() ) 00456 { 00457 } 00458 00459 /** 00460 * Copy constructor. 00461 * 00462 * \param t The tensor to copy from. 00463 */ 00464 WTensorBase( WTensorBase const& t ) // NOLINT 00465 : m_data( t.m_data ) 00466 { 00467 } 00468 00469 /** 00470 * Copy construct a WTensorBase from a WTensorBaseSym. 00471 * 00472 * \param t The symmetric tensor to copy from. 00473 */ 00474 explicit WTensorBase( WTensorBaseSym< 0, dim, Data_T > const& t ) 00475 : m_data() 00476 { 00477 m_data = t.template operator[]< std::size_t >( NULL ); 00478 } 00479 00480 /** 00481 * Copy operator. 00482 * 00483 * \param t The tensor to copy from. 00484 * 00485 * \return *this. 00486 */ 00487 WTensorBase const& operator = ( WTensorBase const& t ) 00488 { 00489 m_data = t.m_data; 00490 return *this; 00491 } 00492 00493 /** 00494 * Copy operator. 00495 * 00496 * \param t The symmetric tensor to copy from. 00497 * 00498 * \return *this. 00499 */ 00500 WTensorBase const& operator = ( WTensorBaseSym< 0, dim, Data_T > const& t ) 00501 { 00502 m_data = t.template operator[]< std::size_t >( NULL ); 00503 return *this; 00504 } 00505 00506 /** 00507 * Get the dimension of this tensor. 00508 * 00509 * \return The dimension of this tensor. 00510 */ 00511 std::size_t getDimension() const 00512 { 00513 return dim; 00514 } 00515 00516 /** 00517 * Get the order of this tensor. 00518 * 00519 * \return The order of this tensor. 00520 */ 00521 std::size_t getOrder() const 00522 { 00523 return 0; 00524 } 00525 00526 /** 00527 * Get the value of this scalar. 00528 * 00529 * \return A reference to the element. 00530 */ 00531 template< typename Index_T > 00532 Data_T& operator[] ( std::vector< Index_T > const& /* indices */ ) 00533 { 00534 return m_data; 00535 } 00536 00537 /** 00538 * Get the value of this scalar. 00539 * 00540 * \return A reference to the element. 00541 */ 00542 template< typename Index_T > 00543 Data_T const& operator[] ( std::vector< Index_T > const& /* indices */ ) const 00544 { 00545 return m_data; 00546 } 00547 00548 /** 00549 * Get the value of this scalar. 00550 * 00551 * \return A reference to the element. 00552 */ 00553 template< typename Index_T > 00554 Data_T& operator[] ( Index_T[] /* indices */ ) 00555 { 00556 return m_data; 00557 } 00558 00559 /** 00560 * Get the value of this scalar. 00561 * 00562 * \return A reference to the element. 00563 */ 00564 template< typename Index_T > 00565 Data_T const& operator[] ( Index_T[] /* indices */ ) const 00566 { 00567 return m_data; 00568 } 00569 00570 /** 00571 * Compare this WTensorBase to another one. 00572 * 00573 * \param other The WBensorBase to compare to. 00574 * 00575 * \return True, iff this tensors' elements are equal to another tensors' elements. 00576 */ 00577 bool operator == ( WTensorBase const& other ) const 00578 { 00579 return m_data == other.m_data; 00580 } 00581 00582 /** 00583 * Compare this WTensorBase to another one. 00584 * 00585 * \param other The WBensorBase to compare to. 00586 * 00587 * \return True, iff this tensors' elements are not equal to another tensors' elements. 00588 */ 00589 bool operator != ( WTensorBase const& other ) const 00590 { 00591 return m_data != other.m_data; 00592 } 00593 00594 private: 00595 /** 00596 * Calculate the position of the element in the data vector. This 00597 * is essentially the standard case of the recursion. 00598 * 00599 * \return 0. 00600 */ 00601 template< typename Index_T > 00602 static inline std::size_t getPos( Index_T[] /* pos */ ) 00603 { 00604 return 0; 00605 } 00606 00607 /** 00608 * Stores the value. 00609 */ 00610 Data_T m_data; 00611 00612 /** 00613 * Declare a compile-time constant as enum and not as static constant. 00614 */ 00615 enum 00616 { 00617 /** 00618 * The number of elements to store. 00619 */ 00620 dataSize = 1 00621 }; 00622 }; 00623 00624 // ################################# class WTensorBaseSym<> ##################################### 00625 00626 /** 00627 * Symmetric tensor base class. 00628 * 00629 * \tparam order The order of the tensor. 00630 * \tparam dim The dimension of the tensor, i.e. the number of components 00631 * in each direction. 00632 * \tparam Data_T The datatype of the components, double by default. 00633 * 00634 * \note The type Data_T may not throw exceptions on construction, destruction or 00635 * during any assignment operator. 00636 * \note The dimension may not be 0. 00637 * 00638 * \see WTensorSym 00639 */ 00640 template< std::size_t order, std::size_t dim, typename Data_T > 00641 class WTensorBaseSym 00642 { 00643 /** 00644 * For dim == 0, create an artificial compiler error. 00645 */ 00646 BOOST_STATIC_ASSERT( dim != 0 ); 00647 00648 // make the test class a friend 00649 friend class ::WTensorBaseSymTest; 00650 00651 // make the func test class a friend 00652 friend class ::WTensorFuncTest; 00653 00654 public: 00655 /** 00656 * Declare a compile-time constant as enum and not as static constant. 00657 */ 00658 enum 00659 { 00660 /** 00661 * The number of elements to store. 00662 */ 00663 dataSize = WBinom< order + dim - 1, order >::value 00664 }; 00665 00666 /** 00667 * Standard constructor. 00668 * 00669 * All elements are set to Data_T(). 00670 */ 00671 WTensorBaseSym(); 00672 00673 /** 00674 * Constructs the symmetrical tensor and initialize with the given data. 00675 * 00676 * \param data The components of the symmetrical tensor: Take care of the 00677 * ordering of the components to match the ordering in \see m_data. 00678 */ 00679 explicit WTensorBaseSym( const WValue< Data_T >& data ); 00680 00681 /** 00682 * Constructs the symmetrical tensor and initialize with the given data. 00683 * 00684 * \param data The components of the symmetrical tensor: Take care of the 00685 * ordering of the components to match the ordering in \see m_data. 00686 */ 00687 explicit WTensorBaseSym( const boost::array< Data_T, dataSize >& data ); 00688 00689 /** 00690 * Copy constructor. 00691 * 00692 * \param t The tensor to copy from. 00693 */ 00694 WTensorBaseSym( WTensorBaseSym const& t ); // NOLINT 00695 00696 /** 00697 * Copy operator. 00698 * 00699 * \param t The tensor to copy from. 00700 * 00701 * \return *this. 00702 */ 00703 WTensorBaseSym const& operator = ( WTensorBaseSym const& t ); 00704 00705 /** 00706 * Get the dimension of this tensor. 00707 * 00708 * \return The dimension of this tensor. 00709 */ 00710 std::size_t getDimension() const; 00711 00712 /** 00713 * Get the order of this tensor. 00714 * 00715 * \return The order of this tensor. 00716 */ 00717 std::size_t getOrder() const; 00718 00719 /** 00720 * Set internal data from a WValue. 00721 * 00722 * \param values The input values. 00723 */ 00724 void setValues( WValue< Data_T > const& values ); 00725 00726 /** 00727 * Set internal data from a boost array. 00728 * 00729 * \param values The input values. 00730 */ 00731 void setValues( boost::array< Data_T, dataSize > const& values ); 00732 00733 /** 00734 * Get the element at a specific position. 00735 * 00736 * \param indices A std::vector of indices that has a size of at least order. 00737 * 00738 * \return A reference to the element. 00739 */ 00740 template< typename Index_T > 00741 Data_T& operator[] ( std::vector< Index_T > const& indices ); 00742 00743 /** 00744 * Get the element at a specific position. 00745 * 00746 * \param indices A std::vector of indices that has a size of at least order. 00747 * 00748 * \return A reference to the element. 00749 */ 00750 template< typename Index_T > 00751 Data_T const& operator[] ( std::vector< Index_T > const& indices ) const; 00752 00753 /** 00754 * Get the element at a specific position. 00755 * 00756 * \param indices An array of indices that has a size of at least order. 00757 * 00758 * \return A reference to the element. 00759 * 00760 * \note No bounds checking is performed. 00761 */ 00762 template< typename Index_T > 00763 Data_T& operator[] ( Index_T indices[] ); 00764 00765 /** 00766 * Get the element at a specific position. 00767 * 00768 * \param indices An array of indices that has a size of at least order. 00769 * 00770 * \return A reference to the element. 00771 * 00772 * \note No bounds checking is performed. 00773 */ 00774 template< typename Index_T > 00775 Data_T const& operator[] ( Index_T indices[] ) const; 00776 00777 /** 00778 * Compare this WTensorBaseSym to another one. 00779 * 00780 * \param other The WTensorBaseSym to compare to. 00781 * 00782 * \return True, iff this tensors' elements are equal to another tensors' elements. 00783 */ 00784 bool operator == ( WTensorBaseSym const& other ) const; 00785 00786 /** 00787 * Compare this WTensorBaseSym to another one. 00788 * 00789 * \param other The WTensorBaseSym to compare to. 00790 * 00791 * \return True, iff this tensors' elements are not equal to another tensors' elements. 00792 */ 00793 bool operator != ( WTensorBaseSym const& other ) const; 00794 00795 protected: 00796 /** 00797 * Stores the elements of this tensor lexicographical ordered on their 00798 * indices, where for each set of permutations the lexicographical lowest 00799 * index is used. 00800 */ 00801 // std::vector< Data_T > m_data; 00802 boost::array< Data_T, dataSize > m_data; 00803 00804 private: 00805 /** 00806 * A class that maps symmetric tensor indices to vector positions. 00807 */ 00808 class PositionIndexer 00809 { 00810 public: 00811 /** 00812 * Standard constructor. The mapping is calculated here. 00813 */ 00814 PositionIndexer(); 00815 00816 /** 00817 * Get the mapped position. 00818 * 00819 * \param pos An array of indices. 00820 * 00821 * \return The position that corresponds to the indices. 00822 */ 00823 template< typename Index_T > 00824 inline std::size_t operator[] ( Index_T pos[] ) const; 00825 00826 /** 00827 * Declare a compile-time constant as enum and not as static constant. 00828 */ 00829 enum 00830 { 00831 /** 00832 * The number of data elements. 00833 */ 00834 dataSize = WBinom< order + dim - 1, order >::value 00835 }; 00836 00837 private: 00838 /** 00839 * Maps the indices to a vector element position. 00840 */ 00841 WTensorBase< order, dim, std::size_t > m_positions; 00842 }; 00843 00844 /** 00845 * A static PositionIndexer that maps tensor indices to vector positions. 00846 */ 00847 static PositionIndexer const m_indexer; 00848 }; 00849 00850 // initialize the indexer object as a static object 00851 template< std::size_t order, std::size_t dim, typename Data_T > 00852 typename WTensorBaseSym< order, dim, Data_T >::PositionIndexer const WTensorBaseSym< order, dim, Data_T >::m_indexer; 00853 00854 // ######################## impl of WTensorBaseSym::PositionIndexer ##################################### 00855 00856 template< std::size_t order, std::size_t dim, typename Data_T > 00857 WTensorBaseSym< order, dim, Data_T >::PositionIndexer::PositionIndexer() 00858 { 00859 // the map uses lexical ordering of vectors 00860 std::map< boost::array< std::size_t, order >, std::size_t > m; 00861 00862 // fill the map with all possible combinations of indices, where 00863 // every combination of indices appears in ascending order of indices 00864 boost::array< std::size_t, order > pos; 00865 pos.assign( 0 ); 00866 00867 for( std::size_t k = 0; k < dataSize; ++k ) 00868 { 00869 // enumerate the position 00870 // m[ pos ] = k; 00871 m.insert( std::make_pair( pos, k ) ); 00872 00873 // get the next sorted combination 00874 positionIterateSortedOneStep< order, dim >( pos ); 00875 } 00876 00877 // now iterate all possible sets of indices 00878 pos.assign( 0 ); 00879 00880 boost::array< std::size_t, order > _p; 00881 _p.assign( 0 ); 00882 00883 for( std::size_t k = 0; k < WPower< dim, order >::value; ++k ) 00884 { 00885 _p = pos; 00886 00887 // sort the indices in _p 00888 std::sort( _p.begin(), _p.end() ); 00889 00890 // now map the arbitrary ordered indices to the position of the ordered set in m (and thus in m_data) 00891 m_positions[ &pos[ 0 ] ] = m[ _p ]; 00892 00893 // the map should already knows the sorted position, 00894 // it should never be added by std::map::operator [] at this point 00895 WAssert( m.size() == dataSize, "" ); 00896 00897 // get the next position 00898 positionIterateOneStep< order, dim >( pos ); 00899 } 00900 } 00901 00902 template< std::size_t order, std::size_t dim, typename Data_T > 00903 template< typename Index_T > 00904 std::size_t WTensorBaseSym< order, dim, Data_T >::PositionIndexer::operator[] ( Index_T pos[] ) const 00905 { 00906 return m_positions[ pos ]; 00907 } 00908 00909 // ######################## impl of WTensorBaseSym ##################################### 00910 00911 template< std::size_t order, std::size_t dim, typename Data_T > 00912 WTensorBaseSym< order, dim, Data_T >::WTensorBaseSym() 00913 { 00914 m_data.assign( Data_T() ); 00915 } 00916 00917 template< std::size_t order, std::size_t dim, typename Data_T > 00918 WTensorBaseSym< order, dim, Data_T >::WTensorBaseSym( const WValue< Data_T >& data ) 00919 { 00920 WAssert( dataSize == m_data.size(), "Number of given components does not match the order and dimension of this symmetric tensor" ); 00921 std::copy( &data[ 0 ], &data[ 0 ] + data.size(), &m_data[ 0 ] ); 00922 } 00923 00924 template< std::size_t order, std::size_t dim, typename Data_T > 00925 WTensorBaseSym< order, dim, Data_T >::WTensorBaseSym( const boost::array< Data_T, dataSize >& data ) 00926 { 00927 std::copy( &data[ 0 ], &data[ 0 ] + dataSize, &m_data[ 0 ] ); 00928 } 00929 00930 template< std::size_t order, std::size_t dim, typename Data_T > 00931 WTensorBaseSym< order, dim, Data_T >::WTensorBaseSym( WTensorBaseSym const& t ) 00932 : m_data( t.m_data ) 00933 { 00934 } 00935 00936 template< std::size_t order, std::size_t dim, typename Data_T > 00937 WTensorBaseSym< order, dim, Data_T > const& WTensorBaseSym< order, dim, Data_T >::operator = ( WTensorBaseSym const& t ) 00938 { 00939 m_data = t.m_data; 00940 return *this; 00941 } 00942 00943 template< std::size_t order, std::size_t dim, typename Data_T > 00944 std::size_t WTensorBaseSym< order, dim, Data_T >::getDimension() const 00945 { 00946 return dim; 00947 } 00948 00949 template< std::size_t order, std::size_t dim, typename Data_T > 00950 std::size_t WTensorBaseSym< order, dim, Data_T >::getOrder() const 00951 { 00952 return order; 00953 } 00954 00955 template< std::size_t order, std::size_t dim, typename Data_T > 00956 void WTensorBaseSym< order, dim, Data_T >::setValues( WValue< Data_T > const& values ) 00957 { 00958 WAssert( m_data.size() == values.size(), "Number of given components does not match the order and dimension of this symmetric tensor" ); 00959 std::copy( &values[ 0 ], &values[ 0 ] + values.size(), &m_data[ 0 ] ); 00960 } 00961 00962 template< std::size_t order, std::size_t dim, typename Data_T > 00963 void WTensorBaseSym< order, dim, Data_T >::setValues( boost::array< Data_T, dataSize > const& values ) 00964 { 00965 std::copy( &values[ 0 ], &values[ 0 ] + dataSize, &m_data[ 0 ] ); 00966 } 00967 00968 template< std::size_t order, std::size_t dim, typename Data_T > 00969 template< typename Index_T > 00970 Data_T& WTensorBaseSym< order, dim, Data_T >::operator[] ( std::vector< Index_T > const& indices ) 00971 { 00972 return const_cast< Data_T& >( static_cast< WTensorBaseSym const& >( *this ).operator[] ( indices ) ); 00973 } 00974 00975 template< std::size_t order, std::size_t dim, typename Data_T > 00976 template< typename Index_T > 00977 Data_T const& WTensorBaseSym< order, dim, Data_T >::operator[] ( std::vector< Index_T > const& indices ) const 00978 { 00979 WAssert( indices.size() >= order, "" ); 00980 return operator[] ( &indices[ 0 ] ); 00981 } 00982 00983 template< std::size_t order, std::size_t dim, typename Data_T > 00984 template< typename Index_T > 00985 Data_T& WTensorBaseSym< order, dim, Data_T >::operator[] ( Index_T indices[] ) 00986 { 00987 return const_cast< Data_T& >( static_cast< WTensorBaseSym const& >( *this ).operator[] ( indices ) ); 00988 } 00989 00990 template< std::size_t order, std::size_t dim, typename Data_T > 00991 template< typename Index_T > 00992 Data_T const& WTensorBaseSym< order, dim, Data_T >::operator[] ( Index_T indices[] ) const 00993 { 00994 std::size_t p = m_indexer[ indices ]; 00995 WAssert( p < m_data.size(), "" ); 00996 return m_data[ p ]; 00997 } 00998 00999 template< std::size_t order, std::size_t dim, typename Data_T > 01000 bool WTensorBaseSym< order, dim, Data_T >::operator == ( WTensorBaseSym const& other ) const 01001 { 01002 return m_data == other.m_data; 01003 } 01004 01005 template< std::size_t order, std::size_t dim, typename Data_T > 01006 bool WTensorBaseSym< order, dim, Data_T >::operator != ( WTensorBaseSym const& other ) const 01007 { 01008 return m_data != other.m_data; 01009 } 01010 01011 // ######################### WTensorBaseSym for order == 0 ########################## 01012 01013 /** 01014 * \tparam dim The dimension of the tensor, i.e. the number of components 01015 * in each direction. 01016 * \tparam Data_T The datatype of the components, double by default. 01017 01018 * Specialization for order = 0. This essentially encapsulates a scalar. The purpose of 01019 * this specialization is compatibility for generic tensor functions. 01020 */ 01021 template< std::size_t dim, typename Data_T > 01022 class WTensorBaseSym< 0, dim, Data_T > 01023 { 01024 friend class ::WTensorBaseSymTest; 01025 friend class ::WTensorFuncTest; 01026 01027 public: 01028 // implementations are inline as they are trivial 01029 /** 01030 * Standard constructor. 01031 * 01032 * All elements are set to Data_T(). 01033 */ 01034 WTensorBaseSym() 01035 : m_data( Data_T() ) 01036 { 01037 } 01038 01039 /** 01040 * Copy constructor. 01041 * 01042 * \param t The tensor to copy from. 01043 */ 01044 WTensorBaseSym( WTensorBaseSym const& t ) // NOLINT 01045 : m_data( t.m_data ) 01046 { 01047 } 01048 01049 /** 01050 * Copy operator. 01051 * 01052 * \param t The tensor to copy from. 01053 * 01054 * \return *this. 01055 */ 01056 WTensorBaseSym const& operator = ( WTensorBaseSym const& t ) 01057 { 01058 m_data = t.m_data; 01059 return *this; 01060 } 01061 01062 /** 01063 * Get the dimension of this tensor. 01064 * 01065 * \return The dimension of this tensor. 01066 */ 01067 std::size_t getDimension() const 01068 { 01069 return dim; 01070 } 01071 01072 /** 01073 * Get the order of this tensor. 01074 * 01075 * \return The order of this tensor. 01076 */ 01077 std::size_t getOrder() const 01078 { 01079 return 0; 01080 } 01081 01082 /** 01083 * Get the value of this scalar. 01084 * 01085 * \return A reference to the element. 01086 */ 01087 template< typename Index_T > 01088 Data_T& operator[] ( std::vector< Index_T > const& /* indices */ ) 01089 { 01090 return m_data; 01091 } 01092 01093 /** 01094 * Get the value of this scalar. 01095 * 01096 * \return A reference to the element. 01097 */ 01098 template< typename Index_T > 01099 Data_T const& operator[] ( std::vector< Index_T > const& /* indices */ ) const 01100 { 01101 return m_data; 01102 } 01103 01104 /** 01105 * Get the value of this scalar. 01106 * 01107 * \return A reference to the element. 01108 */ 01109 template< typename Index_T > 01110 Data_T& operator[] ( Index_T[] /* indices */ ) 01111 { 01112 return m_data; 01113 } 01114 01115 /** 01116 * Get the value of this scalar. 01117 * 01118 * \return A reference to the element. 01119 */ 01120 template< typename Index_T > 01121 Data_T const& operator[] ( Index_T[] /* indices */ ) const 01122 { 01123 return m_data; 01124 } 01125 01126 /** 01127 * Compare this WTensorBase to another one. 01128 * 01129 * \param other The WBensorBase to compare to. 01130 * 01131 * \return True, iff this tensors' elements are equal to another tensors' elements. 01132 */ 01133 bool operator == ( WTensorBaseSym const& other ) const 01134 { 01135 return m_data == other.m_data; 01136 } 01137 01138 /** 01139 * Compare this WTensorBase to another one. 01140 * 01141 * \param other The WBensorBase to compare to. 01142 * 01143 * \return True, iff this tensors' elements are not equal to another tensors' elements. 01144 */ 01145 bool operator != ( WTensorBaseSym const& other ) const 01146 { 01147 return m_data != other.m_data; 01148 } 01149 01150 /** 01151 * Declare a compile-time constant as enum and not as static constant. 01152 */ 01153 enum 01154 { 01155 /** 01156 * The number of elements to store. 01157 */ 01158 dataSize = 1 01159 }; 01160 01161 protected: 01162 /** 01163 * Stores the value. 01164 */ 01165 Data_T m_data; 01166 01167 private: 01168 }; 01169 01170 // ################################### class WTensorFunc<> ###################################### 01171 01172 /** 01173 * Implements functions that should only be defined for certain values of order. 01174 * 01175 * \tparam TensorBase_T Either WTensorBase<> or WTensorBaseSym<> 01176 * \tparam order The order of the tensor. 01177 * \tparam dim The dimension of the tensor, i.e. the number of components 01178 * in each direction. 01179 * \tparam Data_T The datatype of the components, double by default. 01180 */ 01181 //next line is nolint because brainlint cannot find the declaration of TensorBase_T 01182 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t order, std::size_t dim, typename Data_T > //NOLINT 01183 class WTensorFunc : public TensorBase_T< order, dim, Data_T > 01184 { 01185 public: 01186 /** 01187 * Default constructor. 01188 */ 01189 WTensorFunc(); 01190 01191 /** 01192 * Initializes the tensor with the given data. 01193 * 01194 * \param data Components in same ordering as the components of the TensorBase class. 01195 */ 01196 explicit WTensorFunc( const WValue< Data_T >& data ); 01197 01198 /** 01199 * Initializes the tensor with the given data. 01200 * 01201 * \param data Components in same ordering as the components of the TensorBase class. 01202 */ 01203 explicit WTensorFunc( const boost::array< Data_T, TensorBase_T< order, dim, Data_T >::dataSize >& data ); 01204 }; 01205 01206 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t order, std::size_t dim, typename Data_T > 01207 WTensorFunc< TensorBase_T, order, dim, Data_T >::WTensorFunc() 01208 : TensorBase_T< order, dim, Data_T >() 01209 { 01210 } 01211 01212 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t order, std::size_t dim, typename Data_T > 01213 WTensorFunc< TensorBase_T, order, dim, Data_T >::WTensorFunc( const WValue< Data_T >& data ) 01214 : TensorBase_T< order, dim, Data_T >( data ) 01215 { 01216 } 01217 01218 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t order, std::size_t dim, typename Data_T > 01219 WTensorFunc< TensorBase_T, order, dim, Data_T >::WTensorFunc( const boost::array< Data_T, TensorBase_T< order, dim, Data_T >::dataSize >& data ) 01220 : TensorBase_T< order, dim, Data_T >( data ) 01221 { 01222 } 01223 01224 01225 /** 01226 * Implements the operator () for an order of 6. 01227 * 01228 * \tparam TensorBase_T Either WTensorBase<> or WTensorBaseSym<> 01229 * \tparam dim The dimension of the tensor, i.e. the number of components 01230 * in each direction. 01231 * \tparam Data_T The datatype of the components, double by default. 01232 */ 01233 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01234 class WTensorFunc< TensorBase_T, 6, dim, Data_T > : public TensorBase_T< 6, dim, Data_T > 01235 { 01236 public: 01237 /** 01238 * Default constructor. 01239 */ 01240 WTensorFunc(); 01241 01242 /** 01243 * Initializes the tensor with the given data. 01244 * 01245 * \param data Components in same ordering as the components of the TensorBase class. 01246 */ 01247 explicit WTensorFunc( const WValue< Data_T >& data ); 01248 01249 /** 01250 * Initializes the tensor with the given data. 01251 * 01252 * \param data Components in same ordering as the components of the TensorBase class. 01253 */ 01254 explicit WTensorFunc( const boost::array< Data_T, TensorBase_T< 6, dim, Data_T >::dataSize >& data ); 01255 01256 /** 01257 * Access operator. 01258 * 01259 * \param i0 An index. 01260 * \param i1 An index. 01261 * \param i2 An index. 01262 * \param i3 An index. 01263 * \param i4 An index. 01264 * \param i5 An index. 01265 * 01266 * \return A reference to the element. 01267 */ 01268 Data_T& operator() ( std::size_t i0, std::size_t i1, std::size_t i2, std::size_t i3, std::size_t i4, std::size_t i5 ); 01269 01270 /** 01271 * Access operator. 01272 * 01273 * \param i0 An index. 01274 * \param i1 An index. 01275 * \param i2 An index. 01276 * \param i3 An index. 01277 * \param i4 An index. 01278 * \param i5 An index. 01279 * 01280 * \return A reference to the element. 01281 */ 01282 Data_T const& operator() ( std::size_t i0, std::size_t i1, std::size_t i2, std::size_t i3, std::size_t i4, std::size_t i5 ) const; 01283 }; 01284 01285 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > 01286 WTensorFunc< TensorBase_T, 6, dim, Data_T >::WTensorFunc() 01287 : TensorBase_T< 6, dim, Data_T >() 01288 { 01289 } 01290 01291 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > 01292 WTensorFunc< TensorBase_T, 6, dim, Data_T >::WTensorFunc( const WValue< Data_T >& data ) 01293 : TensorBase_T< 6, dim, Data_T >( data ) 01294 { 01295 } 01296 01297 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > 01298 WTensorFunc< TensorBase_T, 6, dim, Data_T >::WTensorFunc( const boost::array< Data_T, TensorBase_T< 6, dim, Data_T >::dataSize >& data ) 01299 : TensorBase_T< 6, dim, Data_T >( data ) 01300 { 01301 } 01302 01303 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01304 Data_T& WTensorFunc< TensorBase_T, 6, dim, Data_T >::operator() ( std::size_t i0, std::size_t i1, std::size_t i2, 01305 std::size_t i3, std::size_t i4, std::size_t i5 ) 01306 { 01307 return const_cast< Data_T& >( static_cast< WTensorFunc const& >( *this ).operator() ( i0, i1, i2, i3, i4, i5 ) ); 01308 } 01309 01310 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01311 Data_T const& WTensorFunc< TensorBase_T, 6, dim, Data_T >::operator() ( std::size_t i0, std::size_t i1, std::size_t i2, 01312 std::size_t i3, std::size_t i4, std::size_t i5 ) const 01313 { 01314 std::size_t p[] = { i0, i1, i2, i3, i4, i5 }; 01315 return TensorBase_T< 6, dim, Data_T >::operator[] ( p ); 01316 } 01317 01318 01319 01320 01321 /** 01322 * Implements the operator () for an order of 5. 01323 * 01324 * \tparam TensorBase_T Either WTensorBase<> or WTensorBaseSym<> 01325 * \tparam dim The dimension of the tensor, i.e. the number of components 01326 * in each direction. 01327 * \tparam Data_T The datatype of the components, double by default. 01328 */ 01329 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01330 class WTensorFunc< TensorBase_T, 5, dim, Data_T > : public TensorBase_T< 5, dim, Data_T > 01331 { 01332 public: 01333 /** 01334 * Access operator. 01335 * 01336 * \param i0 An index. 01337 * \param i1 An index. 01338 * \param i2 An index. 01339 * \param i3 An index. 01340 * \param i4 An index. 01341 * 01342 * \return A reference to the element. 01343 */ 01344 Data_T& operator() ( std::size_t i0, std::size_t i1, std::size_t i2, std::size_t i3, std::size_t i4 ); 01345 01346 /** 01347 * Access operator. 01348 * 01349 * \param i0 An index. 01350 * \param i1 An index. 01351 * \param i2 An index. 01352 * \param i3 An index. 01353 * \param i4 An index. 01354 * 01355 * \return A reference to the element. 01356 */ 01357 Data_T const& operator() ( std::size_t i0, std::size_t i1, std::size_t i2, std::size_t i3, std::size_t i4 ) const; 01358 }; 01359 01360 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01361 Data_T& WTensorFunc< TensorBase_T, 5, dim, Data_T >::operator() ( std::size_t i0, std::size_t i1, std::size_t i2, 01362 std::size_t i3, std::size_t i4 ) 01363 { 01364 return const_cast< Data_T& >( static_cast< WTensorFunc const& >( *this ).operator() ( i0, i1, i2, i3, i4 ) ); 01365 } 01366 01367 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01368 Data_T const& WTensorFunc< TensorBase_T, 5, dim, Data_T >::operator() ( std::size_t i0, std::size_t i1, std::size_t i2, 01369 std::size_t i3, std::size_t i4 ) const 01370 { 01371 std::size_t p[] = { i0, i1, i2, i3, i4 }; 01372 return TensorBase_T< 5, dim, Data_T >::operator[] ( p ); 01373 } 01374 01375 01376 01377 01378 /** 01379 * Implements the operator () for an order of 4. 01380 * 01381 * \tparam TensorBase_T Either WTensorBase<> or WTensorBaseSym<> 01382 * \tparam dim The dimension of the tensor, i.e. the number of components 01383 * in each direction. 01384 * \tparam Data_T The datatype of the components, double by default. 01385 */ 01386 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01387 class WTensorFunc< TensorBase_T, 4, dim, Data_T > : public TensorBase_T< 4, dim, Data_T > 01388 { 01389 public: 01390 /** 01391 * Default constructor. 01392 */ 01393 WTensorFunc(); 01394 01395 /** 01396 * Initializes the tensor with the given data. 01397 * 01398 * \param data Components in same ordering as the components of the TensorBase class. 01399 */ 01400 explicit WTensorFunc( const WValue< Data_T >& data ); 01401 01402 /** 01403 * Initializes the tensor with the given data. 01404 * 01405 * \param data Components in same ordering as the components of the TensorBase class. 01406 */ 01407 explicit WTensorFunc( const boost::array< Data_T, TensorBase_T< 4, dim, Data_T >::dataSize >& data ); 01408 01409 /** 01410 * Access operator. 01411 * 01412 * \param i0 An index. 01413 * \param i1 An index. 01414 * \param i2 An index. 01415 * \param i3 An index. 01416 * 01417 * \return A reference to the element. 01418 */ 01419 Data_T& operator() ( std::size_t i0, std::size_t i1, std::size_t i2, std::size_t i3 ); 01420 01421 /** 01422 * Access operator. 01423 * 01424 * \param i0 An index. 01425 * \param i1 An index. 01426 * \param i2 An index. 01427 * \param i3 An index. 01428 * 01429 * \return A reference to the element. 01430 */ 01431 Data_T const& operator() ( std::size_t i0, std::size_t i1, std::size_t i2, std::size_t i3 ) const; 01432 }; 01433 01434 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > 01435 WTensorFunc< TensorBase_T, 4, dim, Data_T >::WTensorFunc() 01436 : TensorBase_T< 4, dim, Data_T >() 01437 { 01438 } 01439 01440 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > 01441 WTensorFunc< TensorBase_T, 4, dim, Data_T >::WTensorFunc( const WValue< Data_T >& data ) 01442 : TensorBase_T< 4, dim, Data_T >( data ) 01443 { 01444 } 01445 01446 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > 01447 WTensorFunc< TensorBase_T, 4, dim, Data_T >::WTensorFunc( const boost::array< Data_T, TensorBase_T< 4, dim, Data_T >::dataSize >& data ) 01448 : TensorBase_T< 4, dim, Data_T >( data ) 01449 { 01450 } 01451 01452 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01453 Data_T& WTensorFunc< TensorBase_T, 4, dim, Data_T >::operator() ( std::size_t i0, std::size_t i1, std::size_t i2, std::size_t i3 ) 01454 { 01455 return const_cast< Data_T& >( static_cast< WTensorFunc const& >( *this ).operator() ( i0, i1, i2, i3 ) ); 01456 } 01457 01458 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01459 Data_T const& WTensorFunc< TensorBase_T, 4, dim, Data_T >::operator() ( std::size_t i0, std::size_t i1, std::size_t i2, std::size_t i3 ) const 01460 { 01461 std::size_t p[] = { i0, i1, i2, i3 }; 01462 return TensorBase_T< 4, dim, Data_T >::operator[] ( p ); 01463 } 01464 01465 01466 01467 /** 01468 * Implements the operator () for an order of 3. 01469 * 01470 * \tparam TensorBase_T Either WTensorBase<> or WTensorBaseSym<> 01471 * \tparam dim The dimension of the tensor, i.e. the number of components 01472 * in each direction. 01473 * \tparam Data_T The datatype of the components, double by default. 01474 */ 01475 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01476 class WTensorFunc< TensorBase_T, 3, dim, Data_T > : public TensorBase_T< 3, dim, Data_T > 01477 { 01478 public: 01479 /** 01480 * Access operator. 01481 * 01482 * \param i0 An index. 01483 * \param i1 An index. 01484 * \param i2 An index. 01485 * 01486 * \return A reference to the element. 01487 */ 01488 Data_T& operator() ( std::size_t i0, std::size_t i1, std::size_t i2 ); 01489 01490 /** 01491 * Access operator. 01492 * 01493 * \param i0 An index. 01494 * \param i1 An index. 01495 * \param i2 An index. 01496 * 01497 * \return A reference to the element. 01498 */ 01499 Data_T const& operator() ( std::size_t i0, std::size_t i1, std::size_t i2 ) const; 01500 }; 01501 01502 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01503 Data_T& WTensorFunc< TensorBase_T, 3, dim, Data_T >::operator() ( std::size_t i0, std::size_t i1, std::size_t i2 ) 01504 { 01505 return const_cast< Data_T& >( static_cast< WTensorFunc const& >( *this ).operator() ( i0, i1, i2 ) ); 01506 } 01507 01508 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01509 Data_T const& WTensorFunc< TensorBase_T, 3, dim, Data_T >::operator() ( std::size_t i0, std::size_t i1, std::size_t i2 ) const 01510 { 01511 std::size_t p[] = { i0, i1, i2 }; 01512 return TensorBase_T< 3, dim, Data_T >::operator[] ( p ); 01513 } 01514 01515 /** 01516 * Implements the operator () for an order of 2 as well as casts to WMatrix. 01517 * 01518 * \tparam TensorBase_T Either WTensorBase<> or WTensorBaseSym<> 01519 * \tparam dim The dimension of the tensor, i.e. the number of components 01520 * in each direction. 01521 * \tparam Data_T The datatype of the components, double by default. 01522 */ 01523 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01524 class WTensorFunc< TensorBase_T, 2, dim, Data_T > : public TensorBase_T< 2, dim, Data_T > 01525 { 01526 public: 01527 /** 01528 * Default constructor. 01529 */ 01530 WTensorFunc(); 01531 01532 /** 01533 * Initializes the tensor with the given data. 01534 * 01535 * \param data Components in same ordering as the components of the TensorBase class. 01536 */ 01537 explicit WTensorFunc( const WValue< Data_T >& data ); 01538 01539 /** 01540 * Initializes the tensor with the given data. 01541 * 01542 * \param data Components in same ordering as the components of the TensorBase class. 01543 */ 01544 explicit WTensorFunc( const boost::array< Data_T, TensorBase_T< 2, dim, Data_T >::dataSize >& data ); 01545 01546 /** 01547 * Access operator. 01548 * 01549 * \param i0 An index. 01550 * \param i1 An index. 01551 * 01552 * \return A reference to the element. 01553 */ 01554 Data_T& operator() ( std::size_t i0, std::size_t i1 ); 01555 01556 /** 01557 * Access operator. 01558 * 01559 * \param i0 An index. 01560 * \param i1 An index. 01561 * 01562 * \return A reference to the element. 01563 */ 01564 Data_T const& operator() ( std::size_t i0, std::size_t i1 ) const; 01565 01566 /** 01567 * Cast this 2nd-order tensor into a WMatrix. 01568 */ 01569 operator WMatrix< Data_T >() const; 01570 }; 01571 01572 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > 01573 WTensorFunc< TensorBase_T, 2, dim, Data_T >::WTensorFunc() 01574 : TensorBase_T< 2, dim, Data_T >() 01575 { 01576 } 01577 01578 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > 01579 WTensorFunc< TensorBase_T, 2, dim, Data_T >::WTensorFunc( const WValue< Data_T >& data ) 01580 : TensorBase_T< 2, dim, Data_T >( data ) 01581 { 01582 } 01583 01584 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > 01585 WTensorFunc< TensorBase_T, 2, dim, Data_T >::WTensorFunc( const boost::array< Data_T, TensorBase_T< 2, dim, Data_T >::dataSize >& data ) 01586 : TensorBase_T< 2, dim, Data_T >( data ) 01587 { 01588 } 01589 01590 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01591 Data_T& WTensorFunc< TensorBase_T, 2, dim, Data_T >::operator() ( std::size_t i0, std::size_t i1 ) 01592 { 01593 return const_cast< Data_T& >( static_cast< WTensorFunc const& >( *this ).operator() ( i0, i1 ) ); 01594 } 01595 01596 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01597 Data_T const& WTensorFunc< TensorBase_T, 2, dim, Data_T >::operator() ( std::size_t i0, std::size_t i1 ) const 01598 { 01599 std::size_t p[] = { i0, i1 }; 01600 return TensorBase_T< 2, dim, Data_T >::operator[] ( p ); 01601 } 01602 01603 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01604 WTensorFunc< TensorBase_T, 2, dim, Data_T >::operator WMatrix< Data_T > () const 01605 { 01606 WMatrix< Data_T > m( dim, dim ); 01607 for( std::size_t i = 0; i < dim; ++i ) 01608 { 01609 for( std::size_t j = 0; j < dim; ++j ) 01610 { 01611 m( i, j ) = this->operator() ( i, j ); 01612 } 01613 } 01614 return m; 01615 } 01616 01617 /** 01618 * Implements the operator () for an order of 1 as well as a cast to WValue. 01619 * 01620 * \tparam TensorBase_T Either WTensorBase<> or WTensorBaseSym<> 01621 * \tparam dim The dimension of the tensor, i.e. the number of components 01622 * in each direction. 01623 * \tparam Data_T The datatype of the components, double by default. 01624 */ 01625 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01626 class WTensorFunc< TensorBase_T, 1, dim, Data_T > : public TensorBase_T< 1, dim, Data_T > 01627 { 01628 public: 01629 /** 01630 * Access operator. 01631 * 01632 * \param i0 An index. 01633 * 01634 * \return A reference to the element. 01635 */ 01636 Data_T& operator() ( std::size_t i0 ); 01637 01638 /** 01639 * Access operator. 01640 * 01641 * \param i0 An index. 01642 * 01643 * \return A reference to the element. 01644 */ 01645 Data_T const& operator() ( std::size_t i0 ) const; 01646 01647 /** 01648 * Cast this tensor to a WValue. 01649 */ 01650 operator WValue< Data_T > () const; 01651 }; 01652 01653 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01654 Data_T& WTensorFunc< TensorBase_T, 1, dim, Data_T >::operator() ( std::size_t i0 ) 01655 { 01656 return const_cast< Data_T& >( static_cast< WTensorFunc const& >( *this ).operator() ( i0 ) ); 01657 } 01658 01659 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01660 Data_T const& WTensorFunc< TensorBase_T, 1, dim, Data_T >::operator() ( std::size_t i0 ) const 01661 { 01662 std::size_t p[] = { i0 }; 01663 return TensorBase_T< 1, dim, Data_T >::operator[] ( p ); 01664 } 01665 01666 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01667 WTensorFunc< TensorBase_T, 1, dim, Data_T >::operator WValue< Data_T > () const 01668 { 01669 WValue< Data_T > v( dim ); 01670 01671 for( std::size_t k = 0; k < dim; ++k ) 01672 { 01673 v[ k ] = this->operator() ( k ); 01674 } 01675 01676 return v; 01677 } 01678 01679 /** 01680 * Implements the operator () for an order of 0 and a cast to Data_T. 01681 * 01682 * \tparam TensorBase_T Either WTensorBase<> or WTensorBaseSym<> 01683 * \tparam dim The dimension of the tensor, i.e. the number of components 01684 * in each direction. 01685 * \tparam Data_T The datatype of the components, double by default. 01686 */ 01687 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01688 class WTensorFunc< TensorBase_T, 0, dim, Data_T > : public TensorBase_T< 0, dim, Data_T > 01689 { 01690 public: 01691 /** 01692 * Access operator. 01693 * 01694 * \return A reference to the element. 01695 */ 01696 Data_T& operator() (); 01697 01698 /** 01699 * Access operator. 01700 * 01701 * \return A reference to the element. 01702 */ 01703 Data_T const& operator() () const; 01704 01705 /** 01706 * Cast this tensor to a Data_T. 01707 */ 01708 operator Data_T() const; 01709 }; 01710 01711 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01712 Data_T& WTensorFunc< TensorBase_T, 0, dim, Data_T >::operator() () 01713 { 01714 return const_cast< Data_T& >( static_cast< WTensorFunc const& >( *this ).operator() () ); 01715 } 01716 01717 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01718 Data_T const& WTensorFunc< TensorBase_T, 0, dim, Data_T >::operator() () const 01719 { 01720 return TensorBase_T< 0, dim, Data_T >::template operator[]< std::size_t >( NULL ); 01721 } 01722 01723 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01724 WTensorFunc< TensorBase_T, 0, dim, Data_T >::operator Data_T() const 01725 { 01726 return TensorBase_T< 0, dim, Data_T >::template operator[]< std::size_t >( NULL ); 01727 } 01728 01729 #endif // WTENSORBASE_H