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