OpenWalnut 1.2.5
|
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 00034 #include "../WAssert.h" 00035 #include "WCompileTimeFunctions.h" 00036 #include "WMatrix.h" 00037 #include "WValue.h" 00038 00039 // TODO(reichenbach): Remove vectors (because of the enum dataSize). 00040 00041 // forward declaration of the test classes 00042 class WTensorFuncTest; 00043 class WTensorBaseTest; 00044 class WTensorBaseSymTest; 00045 00046 // forward declaration 00047 template< std::size_t order, std::size_t dim, typename Data_T > 00048 class WTensorBaseSym; 00049 00050 // ############################ utility functions #################################### 00051 00052 /** 00053 * Iterate a position in a multidimensional grid. 00054 * 00055 * This essentially creates a linear order on all positions in a tensor, where a position 00056 * is any valid allocation of indices. 00057 * 00058 * Example: for a tensor of order 2 and dimension 3, all possible positions are: 00059 * 00060 * ( 0, 0 ), ( 0, 1 ), ( 0, 2 ), ( 1, 0 ), ( 1, 1 ), ( 1, 2 ), ( 2, 0 ), ( 2, 1 ), ( 2, 2 ) 00061 * 00062 * \param pos The position to be iterated. 00063 */ 00064 template< std::size_t order, std::size_t dim > 00065 inline void positionIterateOneStep( std::vector< std::size_t >& pos ) // NOLINT, need a reference here 00066 { 00067 WAssert( pos.size() >= order, "" ); 00068 00069 for( std::size_t k = order - 1; k > 0; --k ) 00070 { 00071 if( pos[ k ] == dim - 1) 00072 { 00073 pos[ k ] = 0; 00074 } 00075 else 00076 { 00077 ++( pos[ k ] ); 00078 return; 00079 } 00080 } 00081 ++( pos[ 0 ] ); 00082 } 00083 00084 /** 00085 * Iterate a sorted position in a multidimensional grid. 00086 * 00087 * This essentially creates a linear order on all sorted positions in a tensor, where a sorted position 00088 * is any valid allocation of indices where those indices are in ascending order. 00089 * 00090 * Example: for a tensor of order 2 and dimension 3, all possible sorted positions are: 00091 * 00092 * ( 0, 0 ), ( 0, 1 ), ( 0, 2 ), ( 1, 1 ), ( 1, 2 ), ( 2, 2 ) 00093 * 00094 * The number of sorted positions of a tensor matches the number of elements that need to be stored 00095 * by the symmetric tensor of the same order and dimension. 00096 * 00097 * \param pos The sorted(!) position to be iterated. 00098 */ 00099 template< std::size_t order, std::size_t dim > 00100 inline void positionIterateSortedOneStep( std::vector< std::size_t >& pos ) // NOLINT, need a reference here 00101 { 00102 WAssert( pos.size() >= order, "" ); 00103 00104 for( int k = order - 1; k > -1; --k ) 00105 { 00106 if( pos[ k ] != dim - 1 ) 00107 { 00108 ++( pos[ k ] ); 00109 for( std::size_t i = k + 1; i < order; ++i ) 00110 { 00111 pos[ i ] = pos[ k ]; 00112 } 00113 return; 00114 } 00115 } 00116 } 00117 00118 /** 00119 * Same as the version above, using no template arguments. 00120 * 00121 * \param order The order of the tensor. 00122 * \param dim The dimension of the tensor. 00123 * \param pos The sorted(!) position to be iterated. 00124 */ 00125 inline void positionIterateSortedOneStep( std::size_t order, std::size_t dim, std::vector< std::size_t >& pos ) // NOLINT, need a reference here 00126 { 00127 WAssert( pos.size() >= order, "" ); 00128 00129 for( int k = order - 1; k > -1; --k ) 00130 { 00131 if( pos[ k ] != dim - 1 ) 00132 { 00133 ++( pos[ k ] ); 00134 for( std::size_t i = k + 1; i < order; ++i ) 00135 { 00136 pos[ i ] = pos[ k ]; 00137 } 00138 return; 00139 } 00140 } 00141 } 00142 00143 // ############################# class WTensorBase<> ################################# 00144 /** 00145 * Normal tensor base class. 00146 * 00147 * \tparam order The order of the tensor. 00148 * \tparam dim The dimension of the tensor, i.e. the number of components 00149 * in each direction. 00150 * \tparam Data_T The datatype of the components, double by default. 00151 * 00152 * \note The type Data_T may not throw exceptions on construction, destruction or 00153 * during any assignment operator. 00154 * \note The dimension may not be 0. 00155 * 00156 * \see WTensor 00157 */ 00158 template< std::size_t order, std::size_t dim, typename Data_T > 00159 class WTensorBase 00160 { 00161 /** 00162 * For dim == 0, create an artificial compiler error. 00163 */ 00164 BOOST_STATIC_ASSERT( dim != 0 ); 00165 00166 // Make the appropriate tensor of order + 1 a friend, so it has access to the getPos() member. 00167 friend class WTensorBase< order + 1, dim, Data_T >; 00168 00169 // make the test class a friend 00170 friend class ::WTensorBaseTest; 00171 00172 // make the func test class a friend 00173 friend class ::WTensorFuncTest; 00174 00175 public: 00176 /** 00177 * Standard constructor. 00178 * 00179 * All elements are set to Data_T(). 00180 */ 00181 WTensorBase(); 00182 00183 /** 00184 * Copy constructor. 00185 * 00186 * \param t The tensor to copy from. 00187 */ 00188 WTensorBase( WTensorBase const& t ); // NOLINT 00189 00190 /** 00191 * Copy construct a WTensorBase from a WTensorBaseSym. 00192 * 00193 * \param t The symmetric tensor to copy from. 00194 */ 00195 explicit WTensorBase( WTensorBaseSym< order, dim, Data_T > const& t ); 00196 00197 /** 00198 * Copy operator. 00199 * 00200 * \param t The tensor to copy from. 00201 * 00202 * \return *this. 00203 */ 00204 WTensorBase const& operator = ( WTensorBase const& t ); 00205 00206 /** 00207 * Copy operator. 00208 * 00209 * \param t The symmetric tensor to copy from. 00210 * 00211 * \return *this. 00212 */ 00213 WTensorBase const& operator = ( WTensorBaseSym< order, dim, Data_T > const& t ); 00214 00215 /** 00216 * Get the dimension of this tensor. 00217 * 00218 * \return The dimension of this tensor. 00219 */ 00220 std::size_t getDimension() const; 00221 00222 /** 00223 * Get the order of this tensor. 00224 * 00225 * \return The order of this tensor. 00226 */ 00227 std::size_t getOrder() const; 00228 00229 /** 00230 * Get the element at a specific position. 00231 * 00232 * \param indices A std::vector of indices that has a size of at least order. 00233 * 00234 * \return A reference to the element. 00235 */ 00236 template< typename Index_T > 00237 Data_T& operator[] ( std::vector< Index_T > const& indices ); 00238 00239 /** 00240 * Get the element at a specific position. 00241 * 00242 * \param indices A std::vector of indices that has a size of at least order. 00243 * 00244 * \return A reference to the element. 00245 */ 00246 template< typename Index_T > 00247 Data_T const& operator[] ( std::vector< Index_T > const& indices ) const; 00248 00249 /** 00250 * Get the element at a specific position. 00251 * 00252 * \param indices An array of indices that has a size of at least order. 00253 * 00254 * \return A reference to the element. 00255 * 00256 * \note The array must have a length of at least order. 00257 */ 00258 template< typename Index_T > 00259 Data_T& operator[] ( Index_T indices[] ); 00260 00261 /** 00262 * Get the element at a specific position. 00263 * 00264 * \param indices An array of indices that has a size of at least order. 00265 * 00266 * \return A reference to the element. 00267 * 00268 * \note The array must have a length of at least order. 00269 */ 00270 template< typename Index_T > 00271 Data_T const& operator[] ( Index_T indices[] ) const; 00272 00273 /** 00274 * Compare this WTensorBase to another one. 00275 * 00276 * \param other The WBensorBase to compare to. 00277 * 00278 * \return True, iff this tensors' elements are equal to another tensors' elements. 00279 */ 00280 bool operator == ( WTensorBase const& other ) const; 00281 00282 /** 00283 * Compare this WTensorBase to another one. 00284 * 00285 * \param other The WBensorBase to compare to. 00286 * 00287 * \return True, iff this tensors' elements are not equal to another tensors' elements. 00288 */ 00289 bool operator != ( WTensorBase const& other ) const; 00290 00291 private: 00292 /** 00293 * Calculate the position of the element in the data vector. The function 00294 * is build recursively at compile-time. 00295 * 00296 * \param pos An array of indices. 00297 * 00298 * \return The position of the element. 00299 */ 00300 template< typename Index_T > 00301 static inline std::size_t getPos( Index_T pos[] ); 00302 00303 /** 00304 * Stores all elements. 00305 */ 00306 std::vector< Data_T > m_data; 00307 00308 /** 00309 * Declare a compile-time constant as enum and not as static constant. 00310 */ 00311 enum 00312 { 00313 /** 00314 * The number of elements to store. 00315 */ 00316 dataSize = WPower< dim, order >::value 00317 }; 00318 }; 00319 00320 template< std::size_t order, std::size_t dim, typename Data_T > 00321 WTensorBase< order, dim, Data_T >::WTensorBase() 00322 : m_data( dataSize, Data_T() ) 00323 { 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 : m_data( dataSize ) 00335 { 00336 *this = t; 00337 } 00338 00339 template< std::size_t order, std::size_t dim, typename Data_T > 00340 WTensorBase< order, dim, Data_T > const& WTensorBase< order, dim, Data_T >::operator = ( WTensorBase const& t ) 00341 { 00342 m_data = t.m_data; 00343 return *this; 00344 } 00345 00346 template< std::size_t order, std::size_t dim, typename Data_T > 00347 WTensorBase< order, dim, Data_T > const& WTensorBase< order, dim, Data_T >::operator = ( WTensorBaseSym< order, dim, Data_T > const& t ) 00348 { 00349 std::vector< std::size_t > pos( order, 0 ); 00350 00351 for( std::size_t k = 0; k < dataSize; ++k ) 00352 { 00353 ( *this )[ pos ] = t[ pos ]; 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.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.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 * Standard constructor. 00657 * 00658 * All elements are set to Data_T(). 00659 */ 00660 WTensorBaseSym(); 00661 00662 /** 00663 * Constructs the symmetrical tensor and initialize with the given data. 00664 * 00665 * \param data The components of the symmetrical tensor: Take care of the 00666 * ordering of the components to match the ordering in \see m_data. 00667 */ 00668 explicit WTensorBaseSym( const WValue< Data_T >& data ); 00669 00670 /** 00671 * Copy constructor. 00672 * 00673 * \param t The tensor to copy from. 00674 */ 00675 WTensorBaseSym( WTensorBaseSym const& t ); // NOLINT 00676 00677 /** 00678 * Copy operator. 00679 * 00680 * \param t The tensor to copy from. 00681 * 00682 * \return *this. 00683 */ 00684 WTensorBaseSym const& operator = ( WTensorBaseSym const& t ); 00685 00686 /** 00687 * Get the dimension of this tensor. 00688 * 00689 * \return The dimension of this tensor. 00690 */ 00691 std::size_t getDimension() const; 00692 00693 /** 00694 * Get the order of this tensor. 00695 * 00696 * \return The order of this tensor. 00697 */ 00698 std::size_t getOrder() const; 00699 00700 /** 00701 * Get the element at a specific position. 00702 * 00703 * \param indices A std::vector of indices that has a size of at least order. 00704 * 00705 * \return A reference to the element. 00706 */ 00707 template< typename Index_T > 00708 Data_T& operator[] ( std::vector< Index_T > const& indices ); 00709 00710 /** 00711 * Get the element at a specific position. 00712 * 00713 * \param indices A std::vector of indices that has a size of at least order. 00714 * 00715 * \return A reference to the element. 00716 */ 00717 template< typename Index_T > 00718 Data_T const& operator[] ( std::vector< Index_T > const& indices ) const; 00719 00720 /** 00721 * Get the element at a specific position. 00722 * 00723 * \param indices An array of indices that has a size of at least order. 00724 * 00725 * \return A reference to the element. 00726 * 00727 * \note No bounds checking is performed. 00728 */ 00729 template< typename Index_T > 00730 Data_T& operator[] ( Index_T indices[] ); 00731 00732 /** 00733 * Get the element at a specific position. 00734 * 00735 * \param indices An array of indices that has a size of at least order. 00736 * 00737 * \return A reference to the element. 00738 * 00739 * \note No bounds checking is performed. 00740 */ 00741 template< typename Index_T > 00742 Data_T const& operator[] ( Index_T indices[] ) const; 00743 00744 /** 00745 * Compare this WTensorBaseSym to another one. 00746 * 00747 * \param other The WTensorBaseSym to compare to. 00748 * 00749 * \return True, iff this tensors' elements are equal to another tensors' elements. 00750 */ 00751 bool operator == ( WTensorBaseSym const& other ) const; 00752 00753 /** 00754 * Compare this WTensorBaseSym to another one. 00755 * 00756 * \param other The WTensorBaseSym to compare to. 00757 * 00758 * \return True, iff this tensors' elements are not equal to another tensors' elements. 00759 */ 00760 bool operator != ( WTensorBaseSym const& other ) const; 00761 00762 private: 00763 /** 00764 * Stores the elements of this tensor lexicographical ordered on their 00765 * indices, where for each set of permutations the lexicographical lowest 00766 * index is used. 00767 */ 00768 std::vector< Data_T > m_data; 00769 00770 /** 00771 * Declare a compile-time constant as enum and not as static constant. 00772 */ 00773 enum 00774 { 00775 /** 00776 * The number of elements to store. 00777 */ 00778 dataSize = WBinom< order + dim - 1, order >::value 00779 }; 00780 00781 /** 00782 * A class that maps symmetric tensor indices to vector positions. 00783 */ 00784 class PositionIndexer 00785 { 00786 public: 00787 /** 00788 * Standard constructor. The mapping is calculated here. 00789 */ 00790 PositionIndexer(); 00791 00792 /** 00793 * Get the mapped position. 00794 * 00795 * \param pos An array of indices. 00796 * 00797 * \return The position that corresponds to the indices. 00798 */ 00799 template< typename Index_T > 00800 inline std::size_t operator[] ( Index_T pos[] ) const; 00801 00802 /** 00803 * Declare a compile-time constant as enum and not as static constant. 00804 */ 00805 enum 00806 { 00807 /** 00808 * The number of data elements. 00809 */ 00810 dataSize = WBinom< order + dim - 1, order >::value 00811 }; 00812 00813 private: 00814 /** 00815 * Maps the indices to a vector element position. 00816 */ 00817 WTensorBase< order, dim, std::size_t > m_positions; 00818 }; 00819 00820 /** 00821 * A static PositionIndexer that maps tensor indices to vector positions. 00822 */ 00823 static PositionIndexer const m_indexer; 00824 }; 00825 00826 // initialize the indexer object as a static object 00827 template< std::size_t order, std::size_t dim, typename Data_T > 00828 typename WTensorBaseSym< order, dim, Data_T >::PositionIndexer const WTensorBaseSym< order, dim, Data_T >::m_indexer; 00829 00830 // ######################## impl of WTensorBaseSym::PositionIndexer ##################################### 00831 00832 template< std::size_t order, std::size_t dim, typename Data_T > 00833 WTensorBaseSym< order, dim, Data_T >::PositionIndexer::PositionIndexer() 00834 { 00835 // the map uses lexical ordering of vectors 00836 std::map< std::vector< std::size_t >, std::size_t > m; 00837 00838 // fill the map with all possible combinations of indices, where 00839 // every combination of indices appears in ascending order of indices 00840 std::vector< std::size_t > pos( order, 0 ); 00841 for( std::size_t k = 0; k < dataSize; ++k ) 00842 { 00843 // enumerate the position 00844 m[ pos ] = k; 00845 00846 // get the next sorted combination 00847 positionIterateSortedOneStep< order, dim >( pos ); 00848 } 00849 00850 // now iterate all possible sets of indices 00851 pos = std::vector< std::size_t >( order, 0 ); 00852 std::vector< std::size_t > _p( order, 0 ); 00853 for( std::size_t k = 0; k < WPower< dim, order >::value; ++k ) 00854 { 00855 _p = pos; 00856 00857 // sort the indices in _p 00858 std::sort( _p.begin(), _p.end() ); 00859 00860 // now map the arbitrary ordered indices to the position of the ordered set in m (and thus in m_data) 00861 m_positions[ pos ] = m[ _p ]; 00862 00863 // the map should already know the sorted position, 00864 // it should never be added by std::map::operator [] at this point 00865 WAssert( m.size() == dataSize, "" ); 00866 00867 // get the next position 00868 positionIterateOneStep< order, dim >( pos ); 00869 } 00870 } 00871 00872 template< std::size_t order, std::size_t dim, typename Data_T > 00873 template< typename Index_T > 00874 std::size_t WTensorBaseSym< order, dim, Data_T >::PositionIndexer::operator[] ( Index_T pos[] ) const 00875 { 00876 return m_positions[ pos ]; 00877 } 00878 00879 // ######################## impl of WTensorBaseSym ##################################### 00880 00881 template< std::size_t order, std::size_t dim, typename Data_T > 00882 WTensorBaseSym< order, dim, Data_T >::WTensorBaseSym() 00883 : m_data( dataSize, Data_T() ) 00884 { 00885 } 00886 00887 template< std::size_t order, std::size_t dim, typename Data_T > 00888 WTensorBaseSym< order, dim, Data_T >::WTensorBaseSym( const WValue< Data_T >& data ) 00889 : m_data( &data[0], &data[0] + data.size() ) 00890 { 00891 WAssert( dataSize == m_data.size(), "Number of given components does not match the order and dimension of this symmetric tensor" ); 00892 } 00893 00894 template< std::size_t order, std::size_t dim, typename Data_T > 00895 WTensorBaseSym< order, dim, Data_T >::WTensorBaseSym( WTensorBaseSym const& t ) 00896 : m_data( t.m_data ) 00897 { 00898 } 00899 00900 template< std::size_t order, std::size_t dim, typename Data_T > 00901 WTensorBaseSym< order, dim, Data_T > const& WTensorBaseSym< order, dim, Data_T >::operator = ( WTensorBaseSym const& t ) 00902 { 00903 m_data = t.m_data; 00904 return *this; 00905 } 00906 00907 template< std::size_t order, std::size_t dim, typename Data_T > 00908 std::size_t WTensorBaseSym< order, dim, Data_T >::getDimension() const 00909 { 00910 return dim; 00911 } 00912 00913 template< std::size_t order, std::size_t dim, typename Data_T > 00914 std::size_t WTensorBaseSym< order, dim, Data_T >::getOrder() const 00915 { 00916 return order; 00917 } 00918 00919 template< std::size_t order, std::size_t dim, typename Data_T > 00920 template< typename Index_T > 00921 Data_T& WTensorBaseSym< order, dim, Data_T >::operator[] ( std::vector< Index_T > const& indices ) 00922 { 00923 return const_cast< Data_T& >( static_cast< WTensorBaseSym const& >( *this ).operator[] ( indices ) ); 00924 } 00925 00926 template< std::size_t order, std::size_t dim, typename Data_T > 00927 template< typename Index_T > 00928 Data_T const& WTensorBaseSym< order, dim, Data_T >::operator[] ( std::vector< Index_T > const& indices ) const 00929 { 00930 WAssert( indices.size() >= order, "" ); 00931 return operator[] ( &indices[ 0 ] ); 00932 } 00933 00934 template< std::size_t order, std::size_t dim, typename Data_T > 00935 template< typename Index_T > 00936 Data_T& WTensorBaseSym< order, dim, Data_T >::operator[] ( Index_T indices[] ) 00937 { 00938 return const_cast< Data_T& >( static_cast< WTensorBaseSym const& >( *this ).operator[] ( indices ) ); 00939 } 00940 00941 template< std::size_t order, std::size_t dim, typename Data_T > 00942 template< typename Index_T > 00943 Data_T const& WTensorBaseSym< order, dim, Data_T >::operator[] ( Index_T indices[] ) const 00944 { 00945 std::size_t p = m_indexer[ indices ]; 00946 WAssert( p < m_data.size(), "" ); 00947 return m_data[ p ]; 00948 } 00949 00950 template< std::size_t order, std::size_t dim, typename Data_T > 00951 bool WTensorBaseSym< order, dim, Data_T >::operator == ( WTensorBaseSym const& other ) const 00952 { 00953 return m_data == other.m_data; 00954 } 00955 00956 template< std::size_t order, std::size_t dim, typename Data_T > 00957 bool WTensorBaseSym< order, dim, Data_T >::operator != ( WTensorBaseSym const& other ) const 00958 { 00959 return m_data != other.m_data; 00960 } 00961 00962 // ######################### WTensorBaseSym for order == 0 ########################## 00963 00964 /** 00965 * \tparam dim The dimension of the tensor, i.e. the number of components 00966 * in each direction. 00967 * \tparam Data_T The datatype of the components, double by default. 00968 00969 * Specialization for order = 0. This essentially encapsulates a scalar. The purpose of 00970 * this specialization is compatibility for generic tensor functions. 00971 */ 00972 template< std::size_t dim, typename Data_T > 00973 class WTensorBaseSym< 0, dim, Data_T > 00974 { 00975 friend class ::WTensorBaseSymTest; 00976 friend class ::WTensorFuncTest; 00977 00978 public: 00979 // implementations are inline as they are trivial 00980 /** 00981 * Standard constructor. 00982 * 00983 * All elements are set to Data_T(). 00984 */ 00985 WTensorBaseSym() 00986 : m_data( Data_T() ) 00987 { 00988 } 00989 00990 /** 00991 * Copy constructor. 00992 * 00993 * \param t The tensor to copy from. 00994 */ 00995 WTensorBaseSym( WTensorBaseSym const& t ) // NOLINT 00996 : m_data( t.m_data ) 00997 { 00998 } 00999 01000 /** 01001 * Copy operator. 01002 * 01003 * \param t The tensor to copy from. 01004 * 01005 * \return *this. 01006 */ 01007 WTensorBaseSym const& operator = ( WTensorBaseSym const& t ) 01008 { 01009 m_data = t.m_data; 01010 return *this; 01011 } 01012 01013 /** 01014 * Get the dimension of this tensor. 01015 * 01016 * \return The dimension of this tensor. 01017 */ 01018 std::size_t getDimension() const 01019 { 01020 return dim; 01021 } 01022 01023 /** 01024 * Get the order of this tensor. 01025 * 01026 * \return The order of this tensor. 01027 */ 01028 std::size_t getOrder() const 01029 { 01030 return 0; 01031 } 01032 01033 /** 01034 * Get the value of this scalar. 01035 * 01036 * \return A reference to the element. 01037 */ 01038 template< typename Index_T > 01039 Data_T& operator[] ( std::vector< Index_T > const& /* indices */ ) 01040 { 01041 return m_data; 01042 } 01043 01044 /** 01045 * Get the value of this scalar. 01046 * 01047 * \return A reference to the element. 01048 */ 01049 template< typename Index_T > 01050 Data_T const& operator[] ( std::vector< Index_T > const& /* indices */ ) const 01051 { 01052 return m_data; 01053 } 01054 01055 /** 01056 * Get the value of this scalar. 01057 * 01058 * \return A reference to the element. 01059 */ 01060 template< typename Index_T > 01061 Data_T& operator[] ( Index_T[] /* indices */ ) 01062 { 01063 return m_data; 01064 } 01065 01066 /** 01067 * Get the value of this scalar. 01068 * 01069 * \return A reference to the element. 01070 */ 01071 template< typename Index_T > 01072 Data_T const& operator[] ( Index_T[] /* indices */ ) const 01073 { 01074 return m_data; 01075 } 01076 01077 /** 01078 * Compare this WTensorBase to another one. 01079 * 01080 * \param other The WBensorBase to compare to. 01081 * 01082 * \return True, iff this tensors' elements are equal to another tensors' elements. 01083 */ 01084 bool operator == ( WTensorBaseSym const& other ) const 01085 { 01086 return m_data == other.m_data; 01087 } 01088 01089 /** 01090 * Compare this WTensorBase to another one. 01091 * 01092 * \param other The WBensorBase to compare to. 01093 * 01094 * \return True, iff this tensors' elements are not equal to another tensors' elements. 01095 */ 01096 bool operator != ( WTensorBaseSym const& other ) const 01097 { 01098 return m_data != other.m_data; 01099 } 01100 01101 private: 01102 /** 01103 * Stores the value. 01104 */ 01105 Data_T m_data; 01106 01107 /** 01108 * Declare a compile-time constant as enum and not as static constant. 01109 */ 01110 enum 01111 { 01112 /** 01113 * The number of elements to store. 01114 */ 01115 dataSize = 1 01116 }; 01117 }; 01118 01119 // ################################### class WTensorFunc<> ###################################### 01120 01121 /** 01122 * Implements functions that should only be defined for certain values of order. 01123 * 01124 * \tparam TensorBase_T Either WTensorBase<> or WTensorBaseSym<> 01125 * \tparam order The order of the tensor. 01126 * \tparam dim The dimension of the tensor, i.e. the number of components 01127 * in each direction. 01128 * \tparam Data_T The datatype of the components, double by default. 01129 */ 01130 //next line is nolint because brainlint cannot find the declaration of TensorBase_T 01131 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t order, std::size_t dim, typename Data_T > //NOLINT 01132 class WTensorFunc : public TensorBase_T< order, dim, Data_T > 01133 { 01134 }; 01135 01136 /** 01137 * Implements the operator () for an order of 6. 01138 * 01139 * \tparam TensorBase_T Either WTensorBase<> or WTensorBaseSym<> 01140 * \tparam dim The dimension of the tensor, i.e. the number of components 01141 * in each direction. 01142 * \tparam Data_T The datatype of the components, double by default. 01143 */ 01144 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01145 class WTensorFunc< TensorBase_T, 6, dim, Data_T > : public TensorBase_T< 6, dim, Data_T > 01146 { 01147 public: 01148 /** 01149 * Access operator. 01150 * 01151 * \param i0 An index. 01152 * \param i1 An index. 01153 * \param i2 An index. 01154 * \param i3 An index. 01155 * \param i4 An index. 01156 * \param i5 An index. 01157 * 01158 * \return A reference to the element. 01159 */ 01160 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 ); 01161 01162 /** 01163 * Access operator. 01164 * 01165 * \param i0 An index. 01166 * \param i1 An index. 01167 * \param i2 An index. 01168 * \param i3 An index. 01169 * \param i4 An index. 01170 * \param i5 An index. 01171 * 01172 * \return A reference to the element. 01173 */ 01174 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; 01175 }; 01176 01177 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01178 Data_T& WTensorFunc< TensorBase_T, 6, dim, Data_T >::operator() ( std::size_t i0, std::size_t i1, std::size_t i2, 01179 std::size_t i3, std::size_t i4, std::size_t i5 ) 01180 { 01181 return const_cast< Data_T& >( static_cast< WTensorFunc const& >( *this ).operator() ( i0, i1, i2, i3, i4, i5 ) ); 01182 } 01183 01184 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01185 Data_T const& WTensorFunc< TensorBase_T, 6, dim, Data_T >::operator() ( std::size_t i0, std::size_t i1, std::size_t i2, 01186 std::size_t i3, std::size_t i4, std::size_t i5 ) const 01187 { 01188 std::size_t p[] = { i0, i1, i2, i3, i4, i5 }; 01189 return TensorBase_T< 6, dim, Data_T >::operator[] ( p ); 01190 } 01191 01192 01193 01194 01195 /** 01196 * Implements the operator () for an order of 5. 01197 * 01198 * \tparam TensorBase_T Either WTensorBase<> or WTensorBaseSym<> 01199 * \tparam dim The dimension of the tensor, i.e. the number of components 01200 * in each direction. 01201 * \tparam Data_T The datatype of the components, double by default. 01202 */ 01203 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01204 class WTensorFunc< TensorBase_T, 5, dim, Data_T > : public TensorBase_T< 5, dim, Data_T > 01205 { 01206 public: 01207 /** 01208 * Access operator. 01209 * 01210 * \param i0 An index. 01211 * \param i1 An index. 01212 * \param i2 An index. 01213 * \param i3 An index. 01214 * \param i4 An index. 01215 * 01216 * \return A reference to the element. 01217 */ 01218 Data_T& operator() ( std::size_t i0, std::size_t i1, std::size_t i2, std::size_t i3, std::size_t i4 ); 01219 01220 /** 01221 * Access operator. 01222 * 01223 * \param i0 An index. 01224 * \param i1 An index. 01225 * \param i2 An index. 01226 * \param i3 An index. 01227 * \param i4 An index. 01228 * 01229 * \return A reference to the element. 01230 */ 01231 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; 01232 }; 01233 01234 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01235 Data_T& WTensorFunc< TensorBase_T, 5, dim, Data_T >::operator() ( std::size_t i0, std::size_t i1, std::size_t i2, 01236 std::size_t i3, std::size_t i4 ) 01237 { 01238 return const_cast< Data_T& >( static_cast< WTensorFunc const& >( *this ).operator() ( i0, i1, i2, i3, i4 ) ); 01239 } 01240 01241 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01242 Data_T const& WTensorFunc< TensorBase_T, 5, dim, Data_T >::operator() ( std::size_t i0, std::size_t i1, std::size_t i2, 01243 std::size_t i3, std::size_t i4 ) const 01244 { 01245 std::size_t p[] = { i0, i1, i2, i3, i4 }; 01246 return TensorBase_T< 5, dim, Data_T >::operator[] ( p ); 01247 } 01248 01249 01250 01251 01252 /** 01253 * Implements the operator () for an order of 4. 01254 * 01255 * \tparam TensorBase_T Either WTensorBase<> or WTensorBaseSym<> 01256 * \tparam dim The dimension of the tensor, i.e. the number of components 01257 * in each direction. 01258 * \tparam Data_T The datatype of the components, double by default. 01259 */ 01260 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01261 class WTensorFunc< TensorBase_T, 4, dim, Data_T > : public TensorBase_T< 4, dim, Data_T > 01262 { 01263 public: 01264 /** 01265 * Access operator. 01266 * 01267 * \param i0 An index. 01268 * \param i1 An index. 01269 * \param i2 An index. 01270 * \param i3 An index. 01271 * 01272 * \return A reference to the element. 01273 */ 01274 Data_T& operator() ( std::size_t i0, std::size_t i1, std::size_t i2, std::size_t i3 ); 01275 01276 /** 01277 * Access operator. 01278 * 01279 * \param i0 An index. 01280 * \param i1 An index. 01281 * \param i2 An index. 01282 * \param i3 An index. 01283 * 01284 * \return A reference to the element. 01285 */ 01286 Data_T const& operator() ( std::size_t i0, std::size_t i1, std::size_t i2, std::size_t i3 ) const; 01287 }; 01288 01289 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01290 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 ) 01291 { 01292 return const_cast< Data_T& >( static_cast< WTensorFunc const& >( *this ).operator() ( i0, i1, i2, i3 ) ); 01293 } 01294 01295 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01296 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 01297 { 01298 std::size_t p[] = { i0, i1, i2, i3 }; 01299 return TensorBase_T< 4, dim, Data_T >::operator[] ( p ); 01300 } 01301 01302 01303 01304 /** 01305 * Implements the operator () for an order of 3. 01306 * 01307 * \tparam TensorBase_T Either WTensorBase<> or WTensorBaseSym<> 01308 * \tparam dim The dimension of the tensor, i.e. the number of components 01309 * in each direction. 01310 * \tparam Data_T The datatype of the components, double by default. 01311 */ 01312 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01313 class WTensorFunc< TensorBase_T, 3, dim, Data_T > : public TensorBase_T< 3, dim, Data_T > 01314 { 01315 public: 01316 /** 01317 * Access operator. 01318 * 01319 * \param i0 An index. 01320 * \param i1 An index. 01321 * \param i2 An index. 01322 * 01323 * \return A reference to the element. 01324 */ 01325 Data_T& operator() ( std::size_t i0, std::size_t i1, std::size_t i2 ); 01326 01327 /** 01328 * Access operator. 01329 * 01330 * \param i0 An index. 01331 * \param i1 An index. 01332 * \param i2 An index. 01333 * 01334 * \return A reference to the element. 01335 */ 01336 Data_T const& operator() ( std::size_t i0, std::size_t i1, std::size_t i2 ) const; 01337 }; 01338 01339 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01340 Data_T& WTensorFunc< TensorBase_T, 3, dim, Data_T >::operator() ( std::size_t i0, std::size_t i1, std::size_t i2 ) 01341 { 01342 return const_cast< Data_T& >( static_cast< WTensorFunc const& >( *this ).operator() ( i0, i1, i2 ) ); 01343 } 01344 01345 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01346 Data_T const& WTensorFunc< TensorBase_T, 3, dim, Data_T >::operator() ( std::size_t i0, std::size_t i1, std::size_t i2 ) const 01347 { 01348 std::size_t p[] = { i0, i1, i2 }; 01349 return TensorBase_T< 3, dim, Data_T >::operator[] ( p ); 01350 } 01351 01352 /** 01353 * Implements the operator () for an order of 2 as well as casts to WMatrix. 01354 * 01355 * \tparam TensorBase_T Either WTensorBase<> or WTensorBaseSym<> 01356 * \tparam dim The dimension of the tensor, i.e. the number of components 01357 * in each direction. 01358 * \tparam Data_T The datatype of the components, double by default. 01359 */ 01360 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01361 class WTensorFunc< TensorBase_T, 2, dim, Data_T > : public TensorBase_T< 2, dim, Data_T > 01362 { 01363 public: 01364 /** 01365 * Default constructor. 01366 */ 01367 WTensorFunc(); 01368 01369 /** 01370 * Initializes the tensor with the given data. 01371 * 01372 * \param data Components in same ordering as the components of the TensorBase class. 01373 */ 01374 explicit WTensorFunc( const WValue< Data_T >& data ); 01375 01376 /** 01377 * Access operator. 01378 * 01379 * \param i0 An index. 01380 * \param i1 An index. 01381 * 01382 * \return A reference to the element. 01383 */ 01384 Data_T& operator() ( std::size_t i0, std::size_t i1 ); 01385 01386 /** 01387 * Access operator. 01388 * 01389 * \param i0 An index. 01390 * \param i1 An index. 01391 * 01392 * \return A reference to the element. 01393 */ 01394 Data_T const& operator() ( std::size_t i0, std::size_t i1 ) const; 01395 01396 /** 01397 * Cast this 2nd-order tensor into a WMatrix. 01398 */ 01399 operator WMatrix< Data_T >() const; 01400 }; 01401 01402 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > 01403 WTensorFunc< TensorBase_T, 2, dim, Data_T >::WTensorFunc() 01404 : TensorBase_T< 2, dim, Data_T >() 01405 { 01406 } 01407 01408 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > 01409 WTensorFunc< TensorBase_T, 2, dim, Data_T >::WTensorFunc( const WValue< Data_T >& data ) 01410 : TensorBase_T< 2, dim, Data_T >( data ) 01411 { 01412 } 01413 01414 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01415 Data_T& WTensorFunc< TensorBase_T, 2, dim, Data_T >::operator() ( std::size_t i0, std::size_t i1 ) 01416 { 01417 return const_cast< Data_T& >( static_cast< WTensorFunc const& >( *this ).operator() ( i0, i1 ) ); 01418 } 01419 01420 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01421 Data_T const& WTensorFunc< TensorBase_T, 2, dim, Data_T >::operator() ( std::size_t i0, std::size_t i1 ) const 01422 { 01423 std::size_t p[] = { i0, i1 }; 01424 return TensorBase_T< 2, dim, Data_T >::operator[] ( p ); 01425 } 01426 01427 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01428 WTensorFunc< TensorBase_T, 2, dim, Data_T >::operator WMatrix< Data_T > () const 01429 { 01430 WMatrix< Data_T > m( dim, dim ); 01431 for( std::size_t i = 0; i < dim; ++i ) 01432 { 01433 for( std::size_t j = 0; j < dim; ++j ) 01434 { 01435 m( i, j ) = this->operator() ( i, j ); 01436 } 01437 } 01438 return m; 01439 } 01440 01441 /** 01442 * Implements the operator () for an order of 1 as well as a cast to WValue. 01443 * 01444 * \tparam TensorBase_T Either WTensorBase<> or WTensorBaseSym<> 01445 * \tparam dim The dimension of the tensor, i.e. the number of components 01446 * in each direction. 01447 * \tparam Data_T The datatype of the components, double by default. 01448 */ 01449 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01450 class WTensorFunc< TensorBase_T, 1, dim, Data_T > : public TensorBase_T< 1, dim, Data_T > 01451 { 01452 public: 01453 /** 01454 * Access operator. 01455 * 01456 * \param i0 An index. 01457 * 01458 * \return A reference to the element. 01459 */ 01460 Data_T& operator() ( std::size_t i0 ); 01461 01462 /** 01463 * Access operator. 01464 * 01465 * \param i0 An index. 01466 * 01467 * \return A reference to the element. 01468 */ 01469 Data_T const& operator() ( std::size_t i0 ) const; 01470 01471 /** 01472 * Cast this tensor to a WValue. 01473 */ 01474 operator WValue< Data_T > () const; 01475 }; 01476 01477 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01478 Data_T& WTensorFunc< TensorBase_T, 1, dim, Data_T >::operator() ( std::size_t i0 ) 01479 { 01480 return const_cast< Data_T& >( static_cast< WTensorFunc const& >( *this ).operator() ( i0 ) ); 01481 } 01482 01483 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01484 Data_T const& WTensorFunc< TensorBase_T, 1, dim, Data_T >::operator() ( std::size_t i0 ) const 01485 { 01486 std::size_t p[] = { i0 }; 01487 return TensorBase_T< 1, dim, Data_T >::operator[] ( p ); 01488 } 01489 01490 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01491 WTensorFunc< TensorBase_T, 1, dim, Data_T >::operator WValue< Data_T > () const 01492 { 01493 WValue< Data_T > v( dim ); 01494 01495 for( std::size_t k = 0; k < dim; ++k ) 01496 { 01497 v[ k ] = this->operator() ( k ); 01498 } 01499 01500 return v; 01501 } 01502 01503 /** 01504 * Implements the operator () for an order of 0 and a cast to Data_T. 01505 * 01506 * \tparam TensorBase_T Either WTensorBase<> or WTensorBaseSym<> 01507 * \tparam dim The dimension of the tensor, i.e. the number of components 01508 * in each direction. 01509 * \tparam Data_T The datatype of the components, double by default. 01510 */ 01511 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01512 class WTensorFunc< TensorBase_T, 0, dim, Data_T > : public TensorBase_T< 0, dim, Data_T > 01513 { 01514 public: 01515 /** 01516 * Access operator. 01517 * 01518 * \return A reference to the element. 01519 */ 01520 Data_T& operator() (); 01521 01522 /** 01523 * Access operator. 01524 * 01525 * \return A reference to the element. 01526 */ 01527 Data_T const& operator() () const; 01528 01529 /** 01530 * Cast this tensor to a Data_T. 01531 */ 01532 operator Data_T() const; 01533 }; 01534 01535 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01536 Data_T& WTensorFunc< TensorBase_T, 0, dim, Data_T >::operator() () 01537 { 01538 return const_cast< Data_T& >( static_cast< WTensorFunc const& >( *this ).operator() () ); 01539 } 01540 01541 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01542 Data_T const& WTensorFunc< TensorBase_T, 0, dim, Data_T >::operator() () const 01543 { 01544 #ifdef _MSC_VER 01545 return TensorBase_T< 0, dim, Data_T >::operator[]< std::size_t >( NULL ); 01546 #else 01547 return TensorBase_T< 0, dim, Data_T >::template operator[]< std::size_t >( NULL ); 01548 #endif 01549 } 01550 01551 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT 01552 WTensorFunc< TensorBase_T, 0, dim, Data_T >::operator Data_T() const 01553 { 01554 #ifdef _MSC_VER 01555 return TensorBase_T< 0, dim, Data_T >::operator[]< std::size_t >( NULL ); 01556 #else 01557 return TensorBase_T< 0, dim, Data_T >::template operator[]< std::size_t >( NULL ); 01558 #endif 01559 } 01560 01561 #endif // WTENSORBASE_H