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