OpenWalnut 1.2.5
WTensorBase.h
00001 //---------------------------------------------------------------------------
00002 //
00003 // Project: OpenWalnut ( http://www.openwalnut.org )
00004 //
00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
00006 // For more information see http://www.openwalnut.org/copying
00007 //
00008 // This file is part of OpenWalnut.
00009 //
00010 // OpenWalnut is free software: you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as published by
00012 // the Free Software Foundation, either version 3 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // OpenWalnut is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public License
00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
00022 //
00023 //---------------------------------------------------------------------------
00024 
00025 #ifndef WTENSORBASE_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
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends