SUNphi  1.0
TensKind.hpp
Go to the documentation of this file.
1 #ifndef _TENSKIND_HPP
2 #define _TENSKIND_HPP
3 
4 /// \file TensKind.hpp
5 ///
6 /// \brief Defines the Tensor Kind
7 ///
8 /// The tensor kind defines the list of components that form a tensor
9 
10 #ifdef HAVE_CONFIG_H
11  #include <config.hpp>
12 #endif
13 
14 #include <array>
15 
16 
17 #include <ints/IntSeqInsert.hpp>
18 #include <metaprogramming/TypeTraits.hpp>
19 #include <tens/TensComp.hpp>
20 #include <tens/TwinsComp.hpp>
21 #include <tuple/Filter.hpp>
22 #include <tuple/TupleElements.hpp>
23 #include <tuple/TupleOrder.hpp>
24 #include <tuple/TupleTypeCat.hpp>
25 
26 namespace SUNphi
27 {
28  /// Dynamic sizes of a Tens
29  ///
30  /// \todo the array must be replaced with a tuple, whose types
31  /// must be deduced when instatiating the struct, such that int or
32  /// long int or whatever is appropriately used!
33  template <int N>
34  using DynSizes=
35  std::array<int,N>;
36 
37  /// Defines the BaseTensKind type traits
39 
40  /// \cond SUNphi_INTERNAL
41  /// TensKind, forward definition
42  template <class...T>
43  class TensKind;
44  /// \endcond
45 
46  /// Dynamic sizes of a Tens
47  ///
48  /// \todo the array must be replaced with a tuple, whose types
49  /// must be deduced when instatiating the struct, such that int or
50  /// long int or whatever is appropriately used!
51  template <int N>
52  using DynSizes=
53  std::array<int,N>;
54 
55  // Provide a checker for compSize presence
57 
58  /// Returns whether T is a dynamic component
59  template <typename T>
60  [[ maybe_unused ]]
61  static constexpr bool isDynamic=
62  T::isDynamic;
63 
64  /// Defines a TensKind type from a Tuple type
65  /// Static assert if TC is not dynamic
66 #define STATIC_ASSERT_IS_DYNAMIC(TC)
67  static_assert(isDynamic<TC>,"Error, Tens Comp is not dynamic")
68 
69  /// Forces type Tc to be a dynamic TensComp
70  template <typename Tc>
72  {
74  };
75 
77 
78  /// Tensor Kind used to define the structure of a tensor
79  ///
80  /// The tensor kind defines the list of components of a tensor. It
81  /// is used to the define the underlying set of components of a \c
82  /// TensorStorage, or the returned type of a SmET
83  template <class...T>
84  class TensKind : public BaseTensKind
85  {
86  // Check that all types are TensComp
87  static_assert(IntSeq<isTensComp<T>...>::hSum==sizeof...(T),"Cannot define a TensKind for types not inheriting from TensComp");
88 
89  /// Check that all types are different
91 
92  /// An integer sequence defining whether the types are dynamic or not
93  typedef IntSeq<(T::size==DYNAMIC)...> AreDynamic;
94 
95  /// Position of dynamical components
96  ///
97  /// Internal implementation
98  template <int NScanned, // Number of components scanned so far
99  int...CompsPos> // Dynamical positions found so far
100  static constexpr DECLAUTO _DynCompsPos(const IntSeq<CompsPos...>&)
101  {
102  if constexpr(NScanned==sizeof...(T))
103  // Returns
104  return intSeq<CompsPos...>;
105  else
106  if constexpr(AreDynamic::template element<NScanned>())
107  // Nest appending
109  else
110  // Nest without appending
111  return _DynCompsPos<NScanned+1>(intSeq<CompsPos...>);
112  }
113 
114  public:
115 
116  /// Name of the Tk provided with "name()" suffix
117  constexpr static const char* name()
118  {
119  return __PRETTY_FUNCTION__;
120  }
121 
122  /// Position of dynamical components
123  using DynCompsPos=
125 
126  /// Number of dynamical components
127  static constexpr int nDynamic=
128  AreDynamic::hSum;
129 
130  /// Check if the type is fully static
132  (nDynamic==0);
133 
134  /// Tuple containing all types
135  typedef Tuple<T...> types;
136 
137  /// Number of types of the kind
138  static constexpr int nTypes=
139  sizeof...(T);
140 
141  /// Check that another \c TensKind is contained
142  template <typename Oth,
143  typename=ConstrainIsTensKind<Oth>>
144  static constexpr bool contains=
145  tupleHasTypes<typename Oth::types,types>;
146 
147  /// Returns the position of a dynamical size
148  template <typename TC,
149  typename=ConstrainIsTensComp<TC>,
150  typename=ConstrainIsDynamic<TC>>
151  static constexpr TypeIf<isTensComp<TC> and isDynamic<TC>,int>
153  AreDynamic::template hSumFirst<posOfType<TC,types>>;
154 
155  // /// Position of a given type
156  // template <class Tf>
157  // static constexpr int posOfType=posOfType<Tf,Tuple<T...>>;
158 
159  // /// Get all types before one
160  // template <class Tab>
161  // using AllBeforeType=TensKindFromTuple<decltype(getHead<Tab>(Types{}))>;
162 
163  /// Get all types but one
164  template <typename Tab>
165  using AllButType=
167 
168  /// Return the position of the first component needed to vectorize
169  ///
170  /// Internal implementation, escaping when last checkable
171  /// component is reached
172  ///
173  /// \todo Add a lenghty description, this is a complicated piece
174  /// of code! The scope is not immediate to get
175  template <typename F, // Fundamental type
176  int Pos=nTypes-1, // Component searched at the moment
177  int InVectorizingSize=1, // Size of the currently scanned vectorizable components
178  bool IsLastCheckable=(Pos==0), // Determine if this is the last checkable
179  int NextPos=(IsLastCheckable?Pos:(Pos-1)), // Determine the position of next component
180  typename G=RemRef<decltype(get<Pos>(types{}))>, // Get the type of the component under exam
181  int Size=G::size, // Size of current component
182  int OutVectorizingSize=InVectorizingSize*Size, // Returned vectorized size, including current component
183  bool EnoughToVectorize=canBeSizeOfSIMDVector<F>(OutVectorizingSize), // Check if the accumulated size is enough to vectorize
184  bool CompIsVectorizing=G::template isVectorizable<F>, // Check if the current componente is vectorizable
185  bool FallBack=(not CompIsVectorizing) or IsLastCheckable> // Check if we need to fallback
187  {
188  ///Provides the result of the calculation
189  constexpr static int value=
190  FallBack? // If we need to fallback,
191  -1: // returns -1, otherwise
192  (EnoughToVectorize? // if we have accumulated enough components,
193  Pos: // we return current position, otherwise
194  Conditional<IsLastCheckable, // if this is the last checkable component,
195  std::integral_constant<int,-1>, // returns -1 otherwise
196  _firstVectorizingComp<F,NextPos,OutVectorizingSize> // we go to previous component.
197  >::value); // Value is obtained through a Conditional to avoid infinite recursion
198  };
199 
200  /// Return the position of the first component needed to vectorize
201  ///
202  /// If no factorization is possible, returns -1
203  ///
204  /// \todo Add the possibility that the accumulated size is more
205  /// than needed, so we can split the outermost component to allow
206  /// for other kind of optimization
207  ///
208  /// \todo Include a variation of the vectorization according to
209  /// the kind of SIMD vector
210  template <typename F> // Fundamental type
212  _firstVectorizingComp<F>::value; // Get the value of the internal implementation
213 
214  // /// Get all types after a given one
215  // template <class Tab>
216  // using AllAfterType=TensKindFromTuple<decltype(getTail<Tab>(Types{}))>;
217 
218  /// Get the twinned (transposed) type
219  using Twinned=
221 
222  /// Reports through an IntSeq whether a component is Matricial or not
223  using IsMatrixComp=
224  IntSeq<(hasTwin<T> and tupleHasType<T,typename Twinned::types>)...>;
225 
226  /// Insert in the IntSeq Is the points where true twinned types are present
227  template <typename Is>
228  using InsertTrueTwinnedPos=
230 
231  /// Report which components are needed to represent the Diagonal
232  using IsDiagComp=
233  IntSeq<((not tupleHasType<T,typename Twinned::types>) or posOfTypeNotAsserting<T,typename Twinned::types> >= posOfType<T,types>)...>;
234 
235  /// Position of Diagonal components
236  using DiagCompsPos=
238 
239  /// TensKind corresponding to the types of the diagonal
240  using Diag=
242 
243  /////////////////////////////////////////////////////////////////
244 
245  /// Maximal value of the index, restricted to the statical components
247  IntSeq<(T::size>=0 ? T::size : 1)...>::hMul;
248 
249  /////////////////////////////////////////////////////////////////
250 
251  /// Maximal total submultiple of a list of components
252  template <int...Ints>
255 
256  /// Total size of a list of components
257  ///
258  /// If any component is dynamic, returns DYNAMIC, otherwise the product
259  template <int...Ints>
263 
264  /////////////////////////////////////////////////////////////////
265 
266  /// Create a TensComp merging the components IComps
267  ///
268  /// Forward definition
269  template <typename Is>
270  struct TensCompsListMerged;
271 
272  /// Create a TensComp merging the components IComps
273  template <int...IComps> // Index of the components to merge
274  struct TensCompsListMerged<IntSeq<IComps...>>
275  {
276  /// First component of the groups
277  static constexpr int firstComp=
278  IntSeq<IComps...>::template element<0>();
279 
280  /// Check if we are really merging something
281  static constexpr bool realMerge=
282  (sizeof...(IComps)>1);
283 
284  /// Returns a tuple containing the merged components of group I
285  using MergedComps=
286  decltype(getIndexed(intSeq<IComps...>,
287  types{}));
288 
289  /// Product of all the max known submultiple
290  static constexpr int totMaxKnonwSubMultiple=
291  tensCompsListTotMaxKnownSubMultiple<IComps...>;
292 
293  /// Returns the totals size of the group
294  static constexpr int totSize=
295  tensCompsListTotSize<IComps...>;
296 
297  /// Resulting type
298  using type=Conditional<realMerge,
299  // Merged type if the group was larger than 1
300  TensComp<MergedComps,totSize,totMaxKnonwSubMultiple>,
301  // Otherwise return the type itself
302  TupleElementType<firstComp,types>>;
303  };
304 
305  /// Struct used to merge the components of the TensKind
306  ///
307  /// Forward definition
308  template <typename Is,
309  typename Ir>
310  struct _Merged;
311 
312  /// Determines whether an IntSeq is a valid CastMerge type for the TensKind
313  template <typename Is>
315  isOrderedIntSeq<Is> and
316  (Is::template element<0> ==0) and
317  (Is::last == nTypes);
318 
319  /// Helper to constrain the cast
320  template <typename Is>
322  {
323  static_assert(isOrderedIntSeq<Is>,"Not an ordered IntSeq");
324  static_assert(Is::template element<0>()==0, "First element not zero");
325  static_assert(Is::last==nTypes,"Last element not equal to the number of components of the TensKind");
326  };
327 
328  /// Struct used to merge the components of the TensKind
329  template <int...IDelims,
330  int...IGroups>
331  struct _Merged<IntSeq<IDelims...>,IntSeq<IGroups...>> :
332  public ConstrainIsValidCompMerge<IntSeq<IDelims...>>
333  {
334  /// Delimiters
335  using Delims=IntSeq<IDelims...>;
336 
337  /// Range associated with merge grpup I
338  template <int I> // Index of the group of components to merge
339  using Range=
340  RangeSeq<
341  Delims::template element<I>(), // Start
342  1, // Offset
343  Delims::template element<I+1>()>; // End
344 
345  /// Create a TensComp merging the components of group I
346  template <int I> // Index of the group of components to merge
347  using TensCompsGroupMerged=
348  typename TensCompsListMerged<Range<I>>::type;
349 
350  /// TensKind resulting after merging all groups
351  using type=TensKind<TensCompsGroupMerged<IGroups>...>;
352  };
353 
354  /// Merged components according to IntSeq Is
355  template <typename Is>
356  using Merged=
357  typename _Merged<Is,IntsUpTo<Is::size-1>>::type;
358 
359  /////////////////////////////////////////////////////////////////
360 
361  private:
362 
363  /// Blend the TensKind with a list of types
364  ///
365  /// Forward declaration
366  template <typename Tp>
367  class _BlendWithTypes;
368 
369  /// Blend the TensKind with a list of types
370  ///
371  /// It is assumed that the types are TensKind, and the check is
372  /// demanded to the caller
373  template <typename...Oths> // Other types
375  {
376  /// Shortcut for the name of the Tuple
377  using Tp=
378  Tuple<Oths...>;
379 
380  /// Intseq holding the information on whether the type has to be
381  /// appended or not
382  using keepType=
384 
385  /// IntSeq holding the information on whether the position has
386  /// to be appended or not
387  using keepPos=
389 
390  public:
391 
392  /// Result of blending
393  using type=TensKindFromTuple<
394  TupleTypeCatT<T...,
396  };
397 
398  public:
399 
400  /// Blend the TensKind with another one
401  ///
402  /// The TensComp already present are not appended.
403  /// Example:
404  ///
405  /// \code
406  ///
407  /// using MyTk1=TensKind<RwCol,Spin>;
408  /// using MyTk2=TensKind<RwCol,CnCol>;
409  ///
410  /// using MyTkBRes=typename MyTk1::BlendWithTensKind<MyTk2>;
411  /// // same asTensKind<RwCol,Spin,CnCol>
412  ///
413  /// \endcode
414  ///
415  template <typename OthTk,
416  typename=ConstrainIsTensKind<OthTk>>
417  using BlendWithTensKind=
418  typename _BlendWithTypes<typename OthTk::types>::type;
419  };
420 
421  /// Blend an arbitrary number of \c TensKind
422  ///
423  /// Forward declaration of the internal implementation
424  template <typename...>
425  struct _BlendTensKinds;
426 
427  /// Blend an arbitrary number of \c TensKind
428  ///
429  /// Terminator of the recursion
430  template <typename Tk> // Incoming TensKind
431  struct _BlendTensKinds<Tk>
432  {
433  /// Constrain all types to be TensKinds
434  using Constr=
435  ConstrainIsTensKind<Tk>;
436 
437  /// Resulting type (trivial type)
438  using type=
439  Tk;
440  };
441 
442  /// Blend an arbitrary number of \c TensKind
443  ///
444  /// Recursive steps
445  template <typename Head1, // First \c TensKind to blend
446  typename Head2, // Second \c TensKind to blend
447  typename...Tail> // Other \c TensKind to blend, if any
448  struct _BlendTensKinds<Head1,Head2,Tail...>
449  {
450  /// Constrain all types to be TensKinds
451  using Constr=
452  ConstrainAreTensKinds<Head1,Head2,Tail...>;
453 
454  /// Resulting type, self calling recursively
455  using type=
456  typename _BlendTensKinds<typename Head1::template BlendWithTensKind<Head2>,
457  Tail...>::type;
458  };
459 
460  /// Blend an arbitrary number of \c TensKind
461  ///
462  /// Gives visibility to the internal implementation
463  template <typename...Args>
464  using BlendTensKinds=
465  typename _BlendTensKinds<Args...>::type;
466 
467  /// Position of all the \c TensComp of \c TkToSearch in the list of Tks
468  ///
469  /// NOT_PRESENT is inserted in the absent positions
470  template <typename TkToSearch, // \c TensKind whose components have to be searched
471  typename...Tks> // List of \c TensKind where to search the components
473  Tuple<PosOfTypesNotAsserting<typename TkToSearch::types,typename Tks::types>...>;
474 
475  /// Position of all the present \c TensComp of \c TkToSearch in the list of Tks
476  template <typename TkToSearch, // \c TensKind whose components have to be searched
477  typename...Tks> // List of \c TensKind where to search the components
480 }
481 
482 #endif
#define DEFINE_HAS_MEMBER(TAG)
Definition: TypeTraits.hpp:581
#define STATIC_ASSERT_TUPLE_TYPES_ARE_ALL_DIFFERENT(T)
Assert if the Tuple contains multiple times a given type.
Definition: TupleClass.hpp:179
static constexpr const char * name()
Name of the Tk provided with "name()" suffix.
Definition: TensKind.hpp:117
#define DEFINE_VARIADIC_TYPE_FROM_TUPLE(TYPE)
Definition: TupleClass.hpp:94
static constexpr int element()
Get the I element of the sequence.
Definition: IntSeq.hpp:95
decltype(auto) operator+(T1 &&smet1, T2 &&smet2)
Implement smet1+smet2.
Definition: Add.hpp:87
#define STATIC_ASSERT_IS_DYNAMIC(TC)
Definition: TensKind.hpp:66
Forces type Tc to be a dynamic TensComp.
Definition: TensKind.hpp:71
#define DECLAUTO
Short name for decltype(auto)
Helper to constrain the cast.
Definition: TensKind.hpp:321
IntSeq<(T::size==DYNAMIC)... > AreDynamic
Check that all types are different.
Definition: TensKind.hpp:87
#define DEFINE_BASE_TYPE(TYPE,...)
Definition: TypeTraits.hpp:526