OpenWalnut  1.3.1
WTensorBase.h
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #ifndef WTENSORBASE_H
26 #define WTENSORBASE_H
27 
28 #include <algorithm>
29 #include <map>
30 #include <vector>
31 
32 #include <boost/static_assert.hpp>
33 #include <boost/array.hpp>
34 
35 #include "../WAssert.h"
36 #include "WCompileTimeFunctions.h"
37 #include "WMatrix.h"
38 #include "WValue.h"
39 
40 // TODO(reichenbach): Remove vectors (because of the enum dataSize).
41 
42 // forward declaration of the test classes
43 class WTensorFuncTest;
44 class WTensorBaseTest;
45 class WTensorBaseSymTest;
46 
47 // forward declaration
48 template< std::size_t order, std::size_t dim, typename Data_T >
50 
51 // ############################ utility functions ####################################
52 
53 /**
54  * Iterate a position in a multidimensional grid.
55  *
56  * This essentially creates a linear order on all positions in a tensor, where a position
57  * is any valid allocation of indices.
58  *
59  * Example: for a tensor of order 2 and dimension 3, all possible positions are:
60  *
61  * ( 0, 0 ), ( 0, 1 ), ( 0, 2 ), ( 1, 0 ), ( 1, 1 ), ( 1, 2 ), ( 2, 0 ), ( 2, 1 ), ( 2, 2 )
62  *
63  * \param pos The position to be iterated.
64  */
65 template< std::size_t order, std::size_t dim >
66 inline void positionIterateOneStep( boost::array< std::size_t, order >& pos ) // NOLINT, need a reference here
67 {
68  WAssert( pos.size() >= order, "" );
69 
70  for( std::size_t k = order - 1; k > 0; --k )
71  {
72  if( pos[ k ] == dim - 1)
73  {
74  pos[ k ] = 0;
75  }
76  else
77  {
78  ++( pos[ k ] );
79  return;
80  }
81  }
82  ++( pos[ 0 ] );
83 }
84 
85 /**
86  * Iterate a sorted position in a multidimensional grid.
87  *
88  * This essentially creates a linear order on all sorted positions in a tensor, where a sorted position
89  * is any valid allocation of indices where those indices are in ascending order.
90  *
91  * Example: for a tensor of order 2 and dimension 3, all possible sorted positions are:
92  *
93  * ( 0, 0 ), ( 0, 1 ), ( 0, 2 ), ( 1, 1 ), ( 1, 2 ), ( 2, 2 )
94  *
95  * The number of sorted positions of a tensor matches the number of elements that need to be stored
96  * by the symmetric tensor of the same order and dimension.
97  *
98  * \param pos The sorted(!) position to be iterated.
99  */
100 template< std::size_t order, std::size_t dim >
101 inline void positionIterateSortedOneStep( boost::array< std::size_t, order >& pos ) // NOLINT, need a reference here
102 {
103  WAssert( pos.size() >= order, "" );
104 
105  for( int k = order - 1; k > -1; --k )
106  {
107  if( pos[ k ] != dim - 1 )
108  {
109  ++( pos[ k ] );
110  for( std::size_t i = k + 1; i < order; ++i )
111  {
112  pos[ i ] = pos[ k ];
113  }
114  return;
115  }
116  }
117 }
118 
119 /**
120  * Same as the version above, using no template arguments.
121  *
122  * \param order The order of the tensor.
123  * \param dim The dimension of the tensor.
124  * \param pos The sorted(!) position to be iterated.
125  */
126 inline void positionIterateSortedOneStep( std::size_t order, std::size_t dim, std::vector< std::size_t >& pos ) // NOLINT, need a reference here
127 {
128  WAssert( pos.size() >= order, "" );
129 
130  for( int k = order - 1; k > -1; --k )
131  {
132  if( pos[ k ] != dim - 1 )
133  {
134  ++( pos[ k ] );
135  for( std::size_t i = k + 1; i < order; ++i )
136  {
137  pos[ i ] = pos[ k ];
138  }
139  return;
140  }
141  }
142 }
143 
144 // ############################# class WTensorBase<> #################################
145 /**
146  * Normal tensor base class.
147  *
148  * \tparam order The order of the tensor.
149  * \tparam dim The dimension of the tensor, i.e. the number of components
150  * in each direction.
151  * \tparam Data_T The datatype of the components, double by default.
152  *
153  * \note The type Data_T may not throw exceptions on construction, destruction or
154  * during any assignment operator.
155  * \note The dimension may not be 0.
156  *
157  * \see WTensor
158  */
159 template< std::size_t order, std::size_t dim, typename Data_T >
161 {
162  /**
163  * For dim == 0, create an artificial compiler error.
164  */
165  BOOST_STATIC_ASSERT( dim != 0 );
166 
167  // Make the appropriate tensor of order + 1 a friend, so it has access to the getPos() member.
168  friend class WTensorBase< order + 1, dim, Data_T >;
169 
170  // make the test class a friend
171  friend class ::WTensorBaseTest;
172 
173  // make the func test class a friend
174  friend class ::WTensorFuncTest;
175 
176 public:
177  /**
178  * Standard constructor.
179  *
180  * All elements are set to Data_T().
181  */
182  WTensorBase();
183 
184  /**
185  * Copy constructor.
186  *
187  * \param t The tensor to copy from.
188  */
189  WTensorBase( WTensorBase const& t ); // NOLINT
190 
191  /**
192  * Copy construct a WTensorBase from a WTensorBaseSym.
193  *
194  * \param t The symmetric tensor to copy from.
195  */
197 
198  /**
199  * Copy operator.
200  *
201  * \param t The tensor to copy from.
202  *
203  * \return *this.
204  */
205  WTensorBase const& operator = ( WTensorBase const& t );
206 
207  /**
208  * Copy operator.
209  *
210  * \param t The symmetric tensor to copy from.
211  *
212  * \return *this.
213  */
215 
216  /**
217  * Get the dimension of this tensor.
218  *
219  * \return The dimension of this tensor.
220  */
221  std::size_t getDimension() const;
222 
223  /**
224  * Get the order of this tensor.
225  *
226  * \return The order of this tensor.
227  */
228  std::size_t getOrder() const;
229 
230  /**
231  * Get the element at a specific position.
232  *
233  * \param indices A std::vector of indices that has a size of at least order.
234  *
235  * \return A reference to the element.
236  */
237  template< typename Index_T >
238  Data_T& operator[] ( std::vector< Index_T > const& indices );
239 
240  /**
241  * Get the element at a specific position.
242  *
243  * \param indices A std::vector of indices that has a size of at least order.
244  *
245  * \return A reference to the element.
246  */
247  template< typename Index_T >
248  Data_T const& operator[] ( std::vector< Index_T > const& indices ) const;
249 
250  /**
251  * Get the element at a specific position.
252  *
253  * \param indices An array of indices that has a size of at least order.
254  *
255  * \return A reference to the element.
256  *
257  * \note The array must have a length of at least order.
258  */
259  template< typename Index_T >
260  Data_T& operator[] ( Index_T indices[] );
261 
262  /**
263  * Get the element at a specific position.
264  *
265  * \param indices An array of indices that has a size of at least order.
266  *
267  * \return A reference to the element.
268  *
269  * \note The array must have a length of at least order.
270  */
271  template< typename Index_T >
272  Data_T const& operator[] ( Index_T indices[] ) const;
273 
274  /**
275  * Compare this WTensorBase to another one.
276  *
277  * \param other The WBensorBase to compare to.
278  *
279  * \return True, iff this tensors' elements are equal to another tensors' elements.
280  */
281  bool operator == ( WTensorBase const& other ) const;
282 
283  /**
284  * Compare this WTensorBase to another one.
285  *
286  * \param other The WBensorBase to compare to.
287  *
288  * \return True, iff this tensors' elements are not equal to another tensors' elements.
289  */
290  bool operator != ( WTensorBase const& other ) const;
291 
292  /**
293  * Declare a compile-time constant as enum and not as static constant.
294  */
295  enum
296  {
297  /**
298  * The number of elements to store.
299  */
301  };
302 
303 private:
304  /**
305  * Calculate the position of the element in the data vector. The function
306  * is build recursively at compile-time.
307  *
308  * \param pos An array of indices.
309  *
310  * \return The position of the element.
311  */
312  template< typename Index_T >
313  static inline std::size_t getPos( Index_T pos[] );
314 
315  //! Stores all elements.
316  //std::vector< Data_T > m_data;
317  boost::array< Data_T, dataSize > m_data;
318 };
319 
320 template< std::size_t order, std::size_t dim, typename Data_T >
322 {
323  m_data.assign( Data_T() );
324 }
325 
326 template< std::size_t order, std::size_t dim, typename Data_T >
328  : m_data( t.m_data )
329 {
330 }
331 
332 template< std::size_t order, std::size_t dim, typename Data_T >
334 {
335  *this = t;
336 }
337 
338 template< std::size_t order, std::size_t dim, typename Data_T >
340 {
341  m_data = t.m_data;
342  return *this;
343 }
344 
345 template< std::size_t order, std::size_t dim, typename Data_T >
347 {
348  boost::array< std::size_t, order > pos;
349  pos.assign( 0 );
350 
351  for( std::size_t k = 0; k < dataSize; ++k )
352  {
353  ( *this )[ &pos[ 0 ] ] = t[ &pos[ 0 ] ];
354  positionIterateOneStep< order, dim >( pos );
355  }
356 
357  return *this;
358 }
359 
360 template< std::size_t order, std::size_t dim, typename Data_T >
362 {
363  return dim;
364 }
365 
366 template< std::size_t order, std::size_t dim, typename Data_T >
368 {
369  return order;
370 }
371 
372 template< std::size_t order, std::size_t dim, typename Data_T >
373 template< typename Index_T >
374 std::size_t WTensorBase< order, dim, Data_T >::getPos( Index_T pos[] )
375 {
376  return WTensorBase< order - 1, dim, Data_T >::getPos( pos ) * dim + static_cast< std::size_t >( pos[ order - 1 ] );
377 }
378 
379 template< std::size_t order, std::size_t dim, typename Data_T >
380 template< typename Index_T >
381 Data_T& WTensorBase< order, dim, Data_T >::operator[] ( std::vector< Index_T > const& indices )
382 {
383  return const_cast< Data_T& >( static_cast< WTensorBase const& >( *this ).operator[] ( indices ) );
384 }
385 
386 template< std::size_t order, std::size_t dim, typename Data_T >
387 template< typename Index_T >
388 Data_T const& WTensorBase< order, dim, Data_T >::operator[] ( std::vector< Index_T > const& indices ) const
389 {
390  WAssert( indices.size() >= order, "" );
391  return operator[] ( &indices[ 0 ] );
392 }
393 
394 template< std::size_t order, std::size_t dim, typename Data_T >
395 template< typename Index_T >
397 {
398  return const_cast< Data_T& >( static_cast< WTensorBase const& >( *this ).operator[] ( indices ) );
399 }
400 
401 template< std::size_t order, std::size_t dim, typename Data_T >
402 template< typename Index_T >
403 Data_T const& WTensorBase< order, dim, Data_T >::operator[] ( Index_T indices[] ) const
404 {
405  for( std::size_t k = 0; k < order; ++k )
406  {
407  WAssert( static_cast< std::size_t >( indices[ k ] ) < dim, "" );
408  }
409  std::size_t p = getPos( indices );
410  return m_data[ p ];
411 }
412 
413 template< std::size_t order, std::size_t dim, typename Data_T >
415 {
416  return m_data == other.m_data;
417 }
418 
419 template< std::size_t order, std::size_t dim, typename Data_T >
421 {
422  return m_data != other.m_data;
423 }
424 
425 // ######################### WTensorBase for order == 0 ##########################
426 
427 /**
428  * \tparam dim The dimension of the tensor, i.e. the number of components
429  * in each direction.
430  * \tparam Data_T The datatype of the components, double by default.
431 
432  * Specialization for order = 0. This essentially encapsulates a scalar. The purpose of
433  * this specialization is compatibility for generic tensor functions.
434  */
435 template< std::size_t dim, typename Data_T >
436 class WTensorBase< 0, dim, Data_T >
437 {
438  // Make the appropriate tensor of order + 1 a friend, so it has access to the getPos() member.
439  friend class WTensorBase< 1, dim, Data_T >;
440 
441  // make the test class a friend
442  friend class ::WTensorBaseTest;
443 
444  // make the func test class a friend
445  friend class ::WTensorFuncTest;
446 
447 public:
448  // implementations are inline as they are trivial
449  /**
450  * Standard constructor.
451  *
452  * All elements are set to Data_T().
453  */
455  : m_data( Data_T() )
456  {
457  }
458 
459  /**
460  * Copy constructor.
461  *
462  * \param t The tensor to copy from.
463  */
464  WTensorBase( WTensorBase const& t ) // NOLINT
465  : m_data( t.m_data )
466  {
467  }
468 
469  /**
470  * Copy construct a WTensorBase from a WTensorBaseSym.
471  *
472  * \param t The symmetric tensor to copy from.
473  */
475  : m_data()
476  {
477  m_data = t.template operator[]< std::size_t >( NULL );
478  }
479 
480  /**
481  * Copy operator.
482  *
483  * \param t The tensor to copy from.
484  *
485  * \return *this.
486  */
488  {
489  m_data = t.m_data;
490  return *this;
491  }
492 
493  /**
494  * Copy operator.
495  *
496  * \param t The symmetric tensor to copy from.
497  *
498  * \return *this.
499  */
501  {
502  m_data = t.template operator[]< std::size_t >( NULL );
503  return *this;
504  }
505 
506  /**
507  * Get the dimension of this tensor.
508  *
509  * \return The dimension of this tensor.
510  */
511  std::size_t getDimension() const
512  {
513  return dim;
514  }
515 
516  /**
517  * Get the order of this tensor.
518  *
519  * \return The order of this tensor.
520  */
521  std::size_t getOrder() const
522  {
523  return 0;
524  }
525 
526  /**
527  * Get the value of this scalar.
528  *
529  * \return A reference to the element.
530  */
531  template< typename Index_T >
532  Data_T& operator[] ( std::vector< Index_T > const& /* indices */ )
533  {
534  return m_data;
535  }
536 
537  /**
538  * Get the value of this scalar.
539  *
540  * \return A reference to the element.
541  */
542  template< typename Index_T >
543  Data_T const& operator[] ( std::vector< Index_T > const& /* indices */ ) const
544  {
545  return m_data;
546  }
547 
548  /**
549  * Get the value of this scalar.
550  *
551  * \return A reference to the element.
552  */
553  template< typename Index_T >
554  Data_T& operator[] ( Index_T[] /* indices */ )
555  {
556  return m_data;
557  }
558 
559  /**
560  * Get the value of this scalar.
561  *
562  * \return A reference to the element.
563  */
564  template< typename Index_T >
565  Data_T const& operator[] ( Index_T[] /* indices */ ) const
566  {
567  return m_data;
568  }
569 
570  /**
571  * Compare this WTensorBase to another one.
572  *
573  * \param other The WBensorBase to compare to.
574  *
575  * \return True, iff this tensors' elements are equal to another tensors' elements.
576  */
577  bool operator == ( WTensorBase const& other ) const
578  {
579  return m_data == other.m_data;
580  }
581 
582  /**
583  * Compare this WTensorBase to another one.
584  *
585  * \param other The WBensorBase to compare to.
586  *
587  * \return True, iff this tensors' elements are not equal to another tensors' elements.
588  */
589  bool operator != ( WTensorBase const& other ) const
590  {
591  return m_data != other.m_data;
592  }
593 
594 private:
595  /**
596  * Calculate the position of the element in the data vector. This
597  * is essentially the standard case of the recursion.
598  *
599  * \return 0.
600  */
601  template< typename Index_T >
602  static inline std::size_t getPos( Index_T[] /* pos */ )
603  {
604  return 0;
605  }
606 
607  /**
608  * Stores the value.
609  */
610  Data_T m_data;
611 
612  /**
613  * Declare a compile-time constant as enum and not as static constant.
614  */
615  enum
616  {
617  /**
618  * The number of elements to store.
619  */
621  };
622 };
623 
624 // ################################# class WTensorBaseSym<> #####################################
625 
626 /**
627  * Symmetric tensor base class.
628  *
629  * \tparam order The order of the tensor.
630  * \tparam dim The dimension of the tensor, i.e. the number of components
631  * in each direction.
632  * \tparam Data_T The datatype of the components, double by default.
633  *
634  * \note The type Data_T may not throw exceptions on construction, destruction or
635  * during any assignment operator.
636  * \note The dimension may not be 0.
637  *
638  * \see WTensorSym
639  */
640 template< std::size_t order, std::size_t dim, typename Data_T >
641 class WTensorBaseSym
642 {
643  /**
644  * For dim == 0, create an artificial compiler error.
645  */
646  BOOST_STATIC_ASSERT( dim != 0 );
647 
648  // make the test class a friend
649  friend class ::WTensorBaseSymTest;
650 
651  // make the func test class a friend
652  friend class ::WTensorFuncTest;
653 
654 public:
655  /**
656  * Declare a compile-time constant as enum and not as static constant.
657  */
658  enum
659  {
660  /**
661  * The number of elements to store.
662  */
663  dataSize = WBinom< order + dim - 1, order >::value
664  };
665 
666  /**
667  * Standard constructor.
668  *
669  * All elements are set to Data_T().
670  */
671  WTensorBaseSym();
672 
673  /**
674  * Constructs the symmetrical tensor and initialize with the given data.
675  *
676  * \param data The components of the symmetrical tensor: Take care of the
677  * ordering of the components to match the ordering in \see m_data.
678  */
679  explicit WTensorBaseSym( const WValue< Data_T >& data );
680 
681  /**
682  * Constructs the symmetrical tensor and initialize with the given data.
683  *
684  * \param data The components of the symmetrical tensor: Take care of the
685  * ordering of the components to match the ordering in \see m_data.
686  */
687  explicit WTensorBaseSym( const boost::array< Data_T, dataSize >& data );
688 
689  /**
690  * Copy constructor.
691  *
692  * \param t The tensor to copy from.
693  */
694  WTensorBaseSym( WTensorBaseSym const& t ); // NOLINT
695 
696  /**
697  * Copy operator.
698  *
699  * \param t The tensor to copy from.
700  *
701  * \return *this.
702  */
703  WTensorBaseSym const& operator = ( WTensorBaseSym const& t );
704 
705  /**
706  * Get the dimension of this tensor.
707  *
708  * \return The dimension of this tensor.
709  */
710  std::size_t getDimension() const;
711 
712  /**
713  * Get the order of this tensor.
714  *
715  * \return The order of this tensor.
716  */
717  std::size_t getOrder() const;
718 
719  /**
720  * Set internal data from a WValue.
721  *
722  * \param values The input values.
723  */
724  void setValues( WValue< Data_T > const& values );
725 
726  /**
727  * Set internal data from a boost array.
728  *
729  * \param values The input values.
730  */
731  void setValues( boost::array< Data_T, dataSize > const& values );
732 
733  /**
734  * Get the element at a specific position.
735  *
736  * \param indices A std::vector of indices that has a size of at least order.
737  *
738  * \return A reference to the element.
739  */
740  template< typename Index_T >
741  Data_T& operator[] ( std::vector< Index_T > const& indices );
742 
743  /**
744  * Get the element at a specific position.
745  *
746  * \param indices A std::vector of indices that has a size of at least order.
747  *
748  * \return A reference to the element.
749  */
750  template< typename Index_T >
751  Data_T const& operator[] ( std::vector< Index_T > const& indices ) const;
752 
753  /**
754  * Get the element at a specific position.
755  *
756  * \param indices An array of indices that has a size of at least order.
757  *
758  * \return A reference to the element.
759  *
760  * \note No bounds checking is performed.
761  */
762  template< typename Index_T >
763  Data_T& operator[] ( Index_T indices[] );
764 
765  /**
766  * Get the element at a specific position.
767  *
768  * \param indices An array of indices that has a size of at least order.
769  *
770  * \return A reference to the element.
771  *
772  * \note No bounds checking is performed.
773  */
774  template< typename Index_T >
775  Data_T const& operator[] ( Index_T indices[] ) const;
776 
777  /**
778  * Compare this WTensorBaseSym to another one.
779  *
780  * \param other The WTensorBaseSym to compare to.
781  *
782  * \return True, iff this tensors' elements are equal to another tensors' elements.
783  */
784  bool operator == ( WTensorBaseSym const& other ) const;
785 
786  /**
787  * Compare this WTensorBaseSym to another one.
788  *
789  * \param other The WTensorBaseSym to compare to.
790  *
791  * \return True, iff this tensors' elements are not equal to another tensors' elements.
792  */
793  bool operator != ( WTensorBaseSym const& other ) const;
794 
795 protected:
796  /**
797  * Stores the elements of this tensor lexicographical ordered on their
798  * indices, where for each set of permutations the lexicographical lowest
799  * index is used.
800  */
801  // std::vector< Data_T > m_data;
802  boost::array< Data_T, dataSize > m_data;
803 
804 private:
805  /**
806  * A class that maps symmetric tensor indices to vector positions.
807  */
809  {
810  public:
811  /**
812  * Standard constructor. The mapping is calculated here.
813  */
814  PositionIndexer();
815 
816  /**
817  * Get the mapped position.
818  *
819  * \param pos An array of indices.
820  *
821  * \return The position that corresponds to the indices.
822  */
823  template< typename Index_T >
824  inline std::size_t operator[] ( Index_T pos[] ) const;
825 
826  /**
827  * Declare a compile-time constant as enum and not as static constant.
828  */
829  enum
830  {
831  /**
832  * The number of data elements.
833  */
834  dataSize = WBinom< order + dim - 1, order >::value
835  };
836 
837  private:
838  /**
839  * Maps the indices to a vector element position.
840  */
842  };
843 
844  /**
845  * A static PositionIndexer that maps tensor indices to vector positions.
846  */
847  static PositionIndexer const m_indexer;
848 };
849 
850 // initialize the indexer object as a static object
851 template< std::size_t order, std::size_t dim, typename Data_T >
853 
854 // ######################## impl of WTensorBaseSym::PositionIndexer #####################################
855 
856 template< std::size_t order, std::size_t dim, typename Data_T >
858 {
859  // the map uses lexical ordering of vectors
860  std::map< boost::array< std::size_t, order >, std::size_t > m;
861 
862  // fill the map with all possible combinations of indices, where
863  // every combination of indices appears in ascending order of indices
864  boost::array< std::size_t, order > pos;
865  pos.assign( 0 );
866 
867  for( std::size_t k = 0; k < dataSize; ++k )
868  {
869  // enumerate the position
870  // m[ pos ] = k;
871  m.insert( std::make_pair( pos, k ) );
872 
873  // get the next sorted combination
874  positionIterateSortedOneStep< order, dim >( pos );
875  }
876 
877  // now iterate all possible sets of indices
878  pos.assign( 0 );
879 
880  boost::array< std::size_t, order > _p;
881  _p.assign( 0 );
882 
883  for( std::size_t k = 0; k < WPower< dim, order >::value; ++k )
884  {
885  _p = pos;
886 
887  // sort the indices in _p
888  std::sort( _p.begin(), _p.end() );
889 
890  // now map the arbitrary ordered indices to the position of the ordered set in m (and thus in m_data)
891  m_positions[ &pos[ 0 ] ] = m[ _p ];
892 
893  // the map should already knows the sorted position,
894  // it should never be added by std::map::operator [] at this point
895  WAssert( m.size() == dataSize, "" );
896 
897  // get the next position
898  positionIterateOneStep< order, dim >( pos );
899  }
900 }
901 
902 template< std::size_t order, std::size_t dim, typename Data_T >
903 template< typename Index_T >
905 {
906  return m_positions[ pos ];
907 }
908 
909 // ######################## impl of WTensorBaseSym #####################################
910 
911 template< std::size_t order, std::size_t dim, typename Data_T >
913 {
914  m_data.assign( Data_T() );
915 }
916 
917 template< std::size_t order, std::size_t dim, typename Data_T >
919 {
920  WAssert( dataSize == m_data.size(), "Number of given components does not match the order and dimension of this symmetric tensor" );
921  std::copy( &data[ 0 ], &data[ 0 ] + data.size(), &m_data[ 0 ] );
922 }
923 
924 template< std::size_t order, std::size_t dim, typename Data_T >
925 WTensorBaseSym< order, dim, Data_T >::WTensorBaseSym( const boost::array< Data_T, dataSize >& data )
926 {
927  std::copy( &data[ 0 ], &data[ 0 ] + dataSize, &m_data[ 0 ] );
928 }
929 
930 template< std::size_t order, std::size_t dim, typename Data_T >
932  : m_data( t.m_data )
933 {
934 }
935 
936 template< std::size_t order, std::size_t dim, typename Data_T >
938 {
939  m_data = t.m_data;
940  return *this;
941 }
942 
943 template< std::size_t order, std::size_t dim, typename Data_T >
945 {
946  return dim;
947 }
948 
949 template< std::size_t order, std::size_t dim, typename Data_T >
951 {
952  return order;
953 }
954 
955 template< std::size_t order, std::size_t dim, typename Data_T >
957 {
958  WAssert( m_data.size() == values.size(), "Number of given components does not match the order and dimension of this symmetric tensor" );
959  std::copy( &values[ 0 ], &values[ 0 ] + values.size(), &m_data[ 0 ] );
960 }
961 
962 template< std::size_t order, std::size_t dim, typename Data_T >
963 void WTensorBaseSym< order, dim, Data_T >::setValues( boost::array< Data_T, dataSize > const& values )
964 {
965  std::copy( &values[ 0 ], &values[ 0 ] + dataSize, &m_data[ 0 ] );
966 }
967 
968 template< std::size_t order, std::size_t dim, typename Data_T >
969 template< typename Index_T >
970 Data_T& WTensorBaseSym< order, dim, Data_T >::operator[] ( std::vector< Index_T > const& indices )
971 {
972  return const_cast< Data_T& >( static_cast< WTensorBaseSym const& >( *this ).operator[] ( indices ) );
973 }
974 
975 template< std::size_t order, std::size_t dim, typename Data_T >
976 template< typename Index_T >
977 Data_T const& WTensorBaseSym< order, dim, Data_T >::operator[] ( std::vector< Index_T > const& indices ) const
978 {
979  WAssert( indices.size() >= order, "" );
980  return operator[] ( &indices[ 0 ] );
981 }
982 
983 template< std::size_t order, std::size_t dim, typename Data_T >
984 template< typename Index_T >
986 {
987  return const_cast< Data_T& >( static_cast< WTensorBaseSym const& >( *this ).operator[] ( indices ) );
988 }
989 
990 template< std::size_t order, std::size_t dim, typename Data_T >
991 template< typename Index_T >
992 Data_T const& WTensorBaseSym< order, dim, Data_T >::operator[] ( Index_T indices[] ) const
993 {
994  std::size_t p = m_indexer[ indices ];
995  WAssert( p < m_data.size(), "" );
996  return m_data[ p ];
997 }
998 
999 template< std::size_t order, std::size_t dim, typename Data_T >
1001 {
1002  return m_data == other.m_data;
1003 }
1004 
1005 template< std::size_t order, std::size_t dim, typename Data_T >
1007 {
1008  return m_data != other.m_data;
1009 }
1010 
1011 // ######################### WTensorBaseSym for order == 0 ##########################
1012 
1013 /**
1014  * \tparam dim The dimension of the tensor, i.e. the number of components
1015  * in each direction.
1016  * \tparam Data_T The datatype of the components, double by default.
1017 
1018  * Specialization for order = 0. This essentially encapsulates a scalar. The purpose of
1019  * this specialization is compatibility for generic tensor functions.
1020  */
1021 template< std::size_t dim, typename Data_T >
1022 class WTensorBaseSym< 0, dim, Data_T >
1023 {
1024  friend class ::WTensorBaseSymTest;
1025  friend class ::WTensorFuncTest;
1026 
1027 public:
1028  // implementations are inline as they are trivial
1029  /**
1030  * Standard constructor.
1031  *
1032  * All elements are set to Data_T().
1033  */
1035  : m_data( Data_T() )
1036  {
1037  }
1038 
1039  /**
1040  * Copy constructor.
1041  *
1042  * \param t The tensor to copy from.
1043  */
1044  WTensorBaseSym( WTensorBaseSym const& t ) // NOLINT
1045  : m_data( t.m_data )
1046  {
1047  }
1048 
1049  /**
1050  * Copy operator.
1051  *
1052  * \param t The tensor to copy from.
1053  *
1054  * \return *this.
1055  */
1057  {
1058  m_data = t.m_data;
1059  return *this;
1060  }
1061 
1062  /**
1063  * Get the dimension of this tensor.
1064  *
1065  * \return The dimension of this tensor.
1066  */
1067  std::size_t getDimension() const
1068  {
1069  return dim;
1070  }
1071 
1072  /**
1073  * Get the order of this tensor.
1074  *
1075  * \return The order of this tensor.
1076  */
1077  std::size_t getOrder() const
1078  {
1079  return 0;
1080  }
1081 
1082  /**
1083  * Get the value of this scalar.
1084  *
1085  * \return A reference to the element.
1086  */
1087  template< typename Index_T >
1088  Data_T& operator[] ( std::vector< Index_T > const& /* indices */ )
1089  {
1090  return m_data;
1091  }
1092 
1093  /**
1094  * Get the value of this scalar.
1095  *
1096  * \return A reference to the element.
1097  */
1098  template< typename Index_T >
1099  Data_T const& operator[] ( std::vector< Index_T > const& /* indices */ ) const
1100  {
1101  return m_data;
1102  }
1103 
1104  /**
1105  * Get the value of this scalar.
1106  *
1107  * \return A reference to the element.
1108  */
1109  template< typename Index_T >
1110  Data_T& operator[] ( Index_T[] /* indices */ )
1111  {
1112  return m_data;
1113  }
1114 
1115  /**
1116  * Get the value of this scalar.
1117  *
1118  * \return A reference to the element.
1119  */
1120  template< typename Index_T >
1121  Data_T const& operator[] ( Index_T[] /* indices */ ) const
1122  {
1123  return m_data;
1124  }
1125 
1126  /**
1127  * Compare this WTensorBase to another one.
1128  *
1129  * \param other The WBensorBase to compare to.
1130  *
1131  * \return True, iff this tensors' elements are equal to another tensors' elements.
1132  */
1133  bool operator == ( WTensorBaseSym const& other ) const
1134  {
1135  return m_data == other.m_data;
1136  }
1137 
1138  /**
1139  * Compare this WTensorBase to another one.
1140  *
1141  * \param other The WBensorBase to compare to.
1142  *
1143  * \return True, iff this tensors' elements are not equal to another tensors' elements.
1144  */
1145  bool operator != ( WTensorBaseSym const& other ) const
1146  {
1147  return m_data != other.m_data;
1148  }
1149 
1150  /**
1151  * Declare a compile-time constant as enum and not as static constant.
1152  */
1153  enum
1154  {
1155  /**
1156  * The number of elements to store.
1157  */
1159  };
1160 
1161 protected:
1162  /**
1163  * Stores the value.
1164  */
1165  Data_T m_data;
1166 
1167 private:
1168 };
1169 
1170 // ################################### class WTensorFunc<> ######################################
1171 
1172 /**
1173  * Implements functions that should only be defined for certain values of order.
1174  *
1175  * \tparam TensorBase_T Either WTensorBase<> or WTensorBaseSym<>
1176  * \tparam order The order of the tensor.
1177  * \tparam dim The dimension of the tensor, i.e. the number of components
1178  * in each direction.
1179  * \tparam Data_T The datatype of the components, double by default.
1180  */
1181 //next line is nolint because brainlint cannot find the declaration of TensorBase_T
1182 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t order, std::size_t dim, typename Data_T > //NOLINT
1183 class WTensorFunc : public TensorBase_T< order, dim, Data_T >
1184 {
1185 public:
1186  /**
1187  * Default constructor.
1188  */
1189  WTensorFunc();
1190 
1191  /**
1192  * Initializes the tensor with the given data.
1193  *
1194  * \param data Components in same ordering as the components of the TensorBase class.
1195  */
1196  explicit WTensorFunc( const WValue< Data_T >& data );
1197 
1198  /**
1199  * Initializes the tensor with the given data.
1200  *
1201  * \param data Components in same ordering as the components of the TensorBase class.
1202  */
1203  explicit WTensorFunc( const boost::array< Data_T, TensorBase_T< order, dim, Data_T >::dataSize >& data );
1204 };
1205 
1206 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t order, std::size_t dim, typename Data_T >
1208  : TensorBase_T< order, dim, Data_T >()
1209 {
1210 }
1211 
1212 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t order, std::size_t dim, typename Data_T >
1214  : TensorBase_T< order, dim, Data_T >( data )
1215 {
1216 }
1217 
1218 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t order, std::size_t dim, typename Data_T >
1220  : TensorBase_T< order, dim, Data_T >( data )
1221 {
1222 }
1223 
1224 
1225 /**
1226  * Implements the operator () for an order of 6.
1227  *
1228  * \tparam TensorBase_T Either WTensorBase<> or WTensorBaseSym<>
1229  * \tparam dim The dimension of the tensor, i.e. the number of components
1230  * in each direction.
1231  * \tparam Data_T The datatype of the components, double by default.
1232  */
1233 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT
1234 class WTensorFunc< TensorBase_T, 6, dim, Data_T > : public TensorBase_T< 6, dim, Data_T >
1235 {
1236 public:
1237  /**
1238  * Default constructor.
1239  */
1240  WTensorFunc();
1241 
1242  /**
1243  * Initializes the tensor with the given data.
1244  *
1245  * \param data Components in same ordering as the components of the TensorBase class.
1246  */
1247  explicit WTensorFunc( const WValue< Data_T >& data );
1248 
1249  /**
1250  * Initializes the tensor with the given data.
1251  *
1252  * \param data Components in same ordering as the components of the TensorBase class.
1253  */
1254  explicit WTensorFunc( const boost::array< Data_T, TensorBase_T< 6, dim, Data_T >::dataSize >& data );
1255 
1256  /**
1257  * Access operator.
1258  *
1259  * \param i0 An index.
1260  * \param i1 An index.
1261  * \param i2 An index.
1262  * \param i3 An index.
1263  * \param i4 An index.
1264  * \param i5 An index.
1265  *
1266  * \return A reference to the element.
1267  */
1268  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 );
1269 
1270  /**
1271  * Access operator.
1272  *
1273  * \param i0 An index.
1274  * \param i1 An index.
1275  * \param i2 An index.
1276  * \param i3 An index.
1277  * \param i4 An index.
1278  * \param i5 An index.
1279  *
1280  * \return A reference to the element.
1281  */
1282  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;
1283 };
1284 
1285 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T >
1287  : TensorBase_T< 6, dim, Data_T >()
1288 {
1289 }
1290 
1291 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T >
1293  : TensorBase_T< 6, dim, Data_T >( data )
1294 {
1295 }
1296 
1297 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T >
1299  : TensorBase_T< 6, dim, Data_T >( data )
1300 {
1301 }
1302 
1303 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT
1304 Data_T& WTensorFunc< TensorBase_T, 6, dim, Data_T >::operator() ( std::size_t i0, std::size_t i1, std::size_t i2,
1305  std::size_t i3, std::size_t i4, std::size_t i5 )
1306 {
1307  return const_cast< Data_T& >( static_cast< WTensorFunc const& >( *this ).operator() ( i0, i1, i2, i3, i4, i5 ) );
1308 }
1309 
1310 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT
1311 Data_T const& WTensorFunc< TensorBase_T, 6, dim, Data_T >::operator() ( std::size_t i0, std::size_t i1, std::size_t i2,
1312  std::size_t i3, std::size_t i4, std::size_t i5 ) const
1313 {
1314  std::size_t p[] = { i0, i1, i2, i3, i4, i5 };
1316 }
1317 
1318 
1319 
1320 
1321 /**
1322  * Implements the operator () for an order of 5.
1323  *
1324  * \tparam TensorBase_T Either WTensorBase<> or WTensorBaseSym<>
1325  * \tparam dim The dimension of the tensor, i.e. the number of components
1326  * in each direction.
1327  * \tparam Data_T The datatype of the components, double by default.
1328  */
1329 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT
1330 class WTensorFunc< TensorBase_T, 5, dim, Data_T > : public TensorBase_T< 5, dim, Data_T >
1331 {
1332 public:
1333  /**
1334  * Access operator.
1335  *
1336  * \param i0 An index.
1337  * \param i1 An index.
1338  * \param i2 An index.
1339  * \param i3 An index.
1340  * \param i4 An index.
1341  *
1342  * \return A reference to the element.
1343  */
1344  Data_T& operator() ( std::size_t i0, std::size_t i1, std::size_t i2, std::size_t i3, std::size_t i4 );
1345 
1346  /**
1347  * Access operator.
1348  *
1349  * \param i0 An index.
1350  * \param i1 An index.
1351  * \param i2 An index.
1352  * \param i3 An index.
1353  * \param i4 An index.
1354  *
1355  * \return A reference to the element.
1356  */
1357  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;
1358 };
1359 
1360 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT
1361 Data_T& WTensorFunc< TensorBase_T, 5, dim, Data_T >::operator() ( std::size_t i0, std::size_t i1, std::size_t i2,
1362  std::size_t i3, std::size_t i4 )
1363 {
1364  return const_cast< Data_T& >( static_cast< WTensorFunc const& >( *this ).operator() ( i0, i1, i2, i3, i4 ) );
1365 }
1366 
1367 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT
1368 Data_T const& WTensorFunc< TensorBase_T, 5, dim, Data_T >::operator() ( std::size_t i0, std::size_t i1, std::size_t i2,
1369  std::size_t i3, std::size_t i4 ) const
1370 {
1371  std::size_t p[] = { i0, i1, i2, i3, i4 };
1373 }
1374 
1375 
1376 
1377 
1378 /**
1379  * Implements the operator () for an order of 4.
1380  *
1381  * \tparam TensorBase_T Either WTensorBase<> or WTensorBaseSym<>
1382  * \tparam dim The dimension of the tensor, i.e. the number of components
1383  * in each direction.
1384  * \tparam Data_T The datatype of the components, double by default.
1385  */
1386 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT
1387 class WTensorFunc< TensorBase_T, 4, dim, Data_T > : public TensorBase_T< 4, dim, Data_T >
1388 {
1389 public:
1390  /**
1391  * Default constructor.
1392  */
1393  WTensorFunc();
1394 
1395  /**
1396  * Initializes the tensor with the given data.
1397  *
1398  * \param data Components in same ordering as the components of the TensorBase class.
1399  */
1400  explicit WTensorFunc( const WValue< Data_T >& data );
1401 
1402  /**
1403  * Initializes the tensor with the given data.
1404  *
1405  * \param data Components in same ordering as the components of the TensorBase class.
1406  */
1407  explicit WTensorFunc( const boost::array< Data_T, TensorBase_T< 4, dim, Data_T >::dataSize >& data );
1408 
1409  /**
1410  * Access operator.
1411  *
1412  * \param i0 An index.
1413  * \param i1 An index.
1414  * \param i2 An index.
1415  * \param i3 An index.
1416  *
1417  * \return A reference to the element.
1418  */
1419  Data_T& operator() ( std::size_t i0, std::size_t i1, std::size_t i2, std::size_t i3 );
1420 
1421  /**
1422  * Access operator.
1423  *
1424  * \param i0 An index.
1425  * \param i1 An index.
1426  * \param i2 An index.
1427  * \param i3 An index.
1428  *
1429  * \return A reference to the element.
1430  */
1431  Data_T const& operator() ( std::size_t i0, std::size_t i1, std::size_t i2, std::size_t i3 ) const;
1432 };
1433 
1434 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T >
1436  : TensorBase_T< 4, dim, Data_T >()
1437 {
1438 }
1439 
1440 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T >
1442  : TensorBase_T< 4, dim, Data_T >( data )
1443 {
1444 }
1445 
1446 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T >
1448  : TensorBase_T< 4, dim, Data_T >( data )
1449 {
1450 }
1451 
1452 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT
1453 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 )
1454 {
1455  return const_cast< Data_T& >( static_cast< WTensorFunc const& >( *this ).operator() ( i0, i1, i2, i3 ) );
1456 }
1457 
1458 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT
1459 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
1460 {
1461  std::size_t p[] = { i0, i1, i2, i3 };
1463 }
1464 
1465 
1466 
1467 /**
1468  * Implements the operator () for an order of 3.
1469  *
1470  * \tparam TensorBase_T Either WTensorBase<> or WTensorBaseSym<>
1471  * \tparam dim The dimension of the tensor, i.e. the number of components
1472  * in each direction.
1473  * \tparam Data_T The datatype of the components, double by default.
1474  */
1475 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT
1476 class WTensorFunc< TensorBase_T, 3, dim, Data_T > : public TensorBase_T< 3, dim, Data_T >
1477 {
1478 public:
1479  /**
1480  * Access operator.
1481  *
1482  * \param i0 An index.
1483  * \param i1 An index.
1484  * \param i2 An index.
1485  *
1486  * \return A reference to the element.
1487  */
1488  Data_T& operator() ( std::size_t i0, std::size_t i1, std::size_t i2 );
1489 
1490  /**
1491  * Access operator.
1492  *
1493  * \param i0 An index.
1494  * \param i1 An index.
1495  * \param i2 An index.
1496  *
1497  * \return A reference to the element.
1498  */
1499  Data_T const& operator() ( std::size_t i0, std::size_t i1, std::size_t i2 ) const;
1500 };
1501 
1502 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT
1503 Data_T& WTensorFunc< TensorBase_T, 3, dim, Data_T >::operator() ( std::size_t i0, std::size_t i1, std::size_t i2 )
1504 {
1505  return const_cast< Data_T& >( static_cast< WTensorFunc const& >( *this ).operator() ( i0, i1, i2 ) );
1506 }
1507 
1508 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT
1509 Data_T const& WTensorFunc< TensorBase_T, 3, dim, Data_T >::operator() ( std::size_t i0, std::size_t i1, std::size_t i2 ) const
1510 {
1511  std::size_t p[] = { i0, i1, i2 };
1513 }
1514 
1515 /**
1516  * Implements the operator () for an order of 2 as well as casts to WMatrix.
1517  *
1518  * \tparam TensorBase_T Either WTensorBase<> or WTensorBaseSym<>
1519  * \tparam dim The dimension of the tensor, i.e. the number of components
1520  * in each direction.
1521  * \tparam Data_T The datatype of the components, double by default.
1522  */
1523 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT
1524 class WTensorFunc< TensorBase_T, 2, dim, Data_T > : public TensorBase_T< 2, dim, Data_T >
1525 {
1526 public:
1527  /**
1528  * Default constructor.
1529  */
1530  WTensorFunc();
1531 
1532  /**
1533  * Initializes the tensor with the given data.
1534  *
1535  * \param data Components in same ordering as the components of the TensorBase class.
1536  */
1537  explicit WTensorFunc( const WValue< Data_T >& data );
1538 
1539  /**
1540  * Initializes the tensor with the given data.
1541  *
1542  * \param data Components in same ordering as the components of the TensorBase class.
1543  */
1544  explicit WTensorFunc( const boost::array< Data_T, TensorBase_T< 2, dim, Data_T >::dataSize >& data );
1545 
1546  /**
1547  * Access operator.
1548  *
1549  * \param i0 An index.
1550  * \param i1 An index.
1551  *
1552  * \return A reference to the element.
1553  */
1554  Data_T& operator() ( std::size_t i0, std::size_t i1 );
1555 
1556  /**
1557  * Access operator.
1558  *
1559  * \param i0 An index.
1560  * \param i1 An index.
1561  *
1562  * \return A reference to the element.
1563  */
1564  Data_T const& operator() ( std::size_t i0, std::size_t i1 ) const;
1565 
1566  /**
1567  * Cast this 2nd-order tensor into a WMatrix.
1568  */
1569  operator WMatrix< Data_T >() const;
1570 };
1571 
1572 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T >
1574  : TensorBase_T< 2, dim, Data_T >()
1575 {
1576 }
1577 
1578 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T >
1580  : TensorBase_T< 2, dim, Data_T >( data )
1581 {
1582 }
1583 
1584 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T >
1586  : TensorBase_T< 2, dim, Data_T >( data )
1587 {
1588 }
1589 
1590 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT
1591 Data_T& WTensorFunc< TensorBase_T, 2, dim, Data_T >::operator() ( std::size_t i0, std::size_t i1 )
1592 {
1593  return const_cast< Data_T& >( static_cast< WTensorFunc const& >( *this ).operator() ( i0, i1 ) );
1594 }
1595 
1596 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT
1597 Data_T const& WTensorFunc< TensorBase_T, 2, dim, Data_T >::operator() ( std::size_t i0, std::size_t i1 ) const
1598 {
1599  std::size_t p[] = { i0, i1 };
1601 }
1602 
1603 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT
1605 {
1606  WMatrix< Data_T > m( dim, dim );
1607  for( std::size_t i = 0; i < dim; ++i )
1608  {
1609  for( std::size_t j = 0; j < dim; ++j )
1610  {
1611  m( i, j ) = this->operator() ( i, j );
1612  }
1613  }
1614  return m;
1615 }
1616 
1617 /**
1618  * Implements the operator () for an order of 1 as well as a cast to WValue.
1619  *
1620  * \tparam TensorBase_T Either WTensorBase<> or WTensorBaseSym<>
1621  * \tparam dim The dimension of the tensor, i.e. the number of components
1622  * in each direction.
1623  * \tparam Data_T The datatype of the components, double by default.
1624  */
1625 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT
1626 class WTensorFunc< TensorBase_T, 1, dim, Data_T > : public TensorBase_T< 1, dim, Data_T >
1627 {
1628 public:
1629  /**
1630  * Access operator.
1631  *
1632  * \param i0 An index.
1633  *
1634  * \return A reference to the element.
1635  */
1636  Data_T& operator() ( std::size_t i0 );
1637 
1638  /**
1639  * Access operator.
1640  *
1641  * \param i0 An index.
1642  *
1643  * \return A reference to the element.
1644  */
1645  Data_T const& operator() ( std::size_t i0 ) const;
1646 
1647  /**
1648  * Cast this tensor to a WValue.
1649  */
1650  operator WValue< Data_T > () const;
1651 };
1652 
1653 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT
1655 {
1656  return const_cast< Data_T& >( static_cast< WTensorFunc const& >( *this ).operator() ( i0 ) );
1657 }
1658 
1659 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT
1661 {
1662  std::size_t p[] = { i0 };
1664 }
1665 
1666 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT
1668 {
1669  WValue< Data_T > v( dim );
1670 
1671  for( std::size_t k = 0; k < dim; ++k )
1672  {
1673  v[ k ] = this->operator() ( k );
1674  }
1675 
1676  return v;
1677 }
1678 
1679 /**
1680  * Implements the operator () for an order of 0 and a cast to Data_T.
1681  *
1682  * \tparam TensorBase_T Either WTensorBase<> or WTensorBaseSym<>
1683  * \tparam dim The dimension of the tensor, i.e. the number of components
1684  * in each direction.
1685  * \tparam Data_T The datatype of the components, double by default.
1686  */
1687 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT
1688 class WTensorFunc< TensorBase_T, 0, dim, Data_T > : public TensorBase_T< 0, dim, Data_T >
1689 {
1690 public:
1691  /**
1692  * Access operator.
1693  *
1694  * \return A reference to the element.
1695  */
1696  Data_T& operator() ();
1697 
1698  /**
1699  * Access operator.
1700  *
1701  * \return A reference to the element.
1702  */
1703  Data_T const& operator() () const;
1704 
1705  /**
1706  * Cast this tensor to a Data_T.
1707  */
1708  operator Data_T() const;
1709 };
1710 
1711 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT
1713 {
1714  return const_cast< Data_T& >( static_cast< WTensorFunc const& >( *this ).operator() () );
1715 }
1716 
1717 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT
1719 {
1720  return TensorBase_T< 0, dim, Data_T >::template operator[]< std::size_t >( NULL );
1721 }
1722 
1723 template< template< std::size_t, std::size_t, typename > class TensorBase_T, std::size_t dim, typename Data_T > //NOLINT
1725 {
1726  return TensorBase_T< 0, dim, Data_T >::template operator[]< std::size_t >( NULL );
1727 }
1728 
1729 #endif // WTENSORBASE_H