SUNphi  1.0
BaseSmET.hpp
Go to the documentation of this file.
1 #ifndef _BASESMET_HPP
2 #define _BASESMET_HPP
3 
4 /// \file BaseSmET.hpp
5 ///
6 /// \brief Header file defining basic properties of Smart Expression Templates
7 
8 #include <ints/IntSeqGetEl.hpp>
9 #include <metaprogramming/CRTP.hpp>
10 #include <metaprogramming/SwallowSemicolon.hpp>
11 #include <metaprogramming/TypeTraits.hpp>
12 #include <metaprogramming/UniversalReferences.hpp>
13 
14 #include <iostream>
15 
16 namespace SUNphi
17 {
18  /// Provides an attribute
19 #define STATIC_CONSTEXPR(DESCRIPTION,LONG_DESCRIPTION,TYPE,NAME,...)
20  DESCRIPTION
21  /*! */
22  LONG_DESCRIPTION
23  static constexpr TYPE NAME=
24  __VA_ARGS__
25 
26  /// Provides an attribute
27 #define USING(DESCRIPTION,LONG_DESCRIPTION,NAME,...)
28  DESCRIPTION
29  /*! */
30  LONG_DESCRIPTION
31  using NAME=
32  __VA_ARGS__
33 
34  /// Define a getter of an attibute, with a default
35 #define DEFINE_GETTER_WITH_DEFAULT(NAME, /*!< Name of the attribute */
36  DEFVAL /*!< Default value */)
37  /*! Provides a function to get NAME, or a DEFVAL if not present */
38  /*! and no external \c Defval is provided */
39  /*! */
40  /*! Internal implentation */
41  template <typename T,
42  auto DefVal=DEFVAL>
43  constexpr bool _get ## NAME() /*!< Type to analyze */
44  {
45  if constexpr(isClass<T>)
46  if constexpr(hasMember_ ## NAME<T>)
47  return RemRef<T>::NAME;
48 
49  return DefVal;
50  }
51 
52  /*! Provides a function to get NAME, or a DEFVAL if not present */
53  /*! */
54  /*! Gives visibility to internal implementation */
55  template <typename T,
56  auto DefVal=DEFVAL>
57  [[ maybe_unused ]]
58  constexpr bool NAME=
59  _get ## NAME<T,DEFVAL>()
60 
61  /////////////////////////////////////////////////////////////////
62 
63  /// Defines the BaseSmET type traits
65 
66  // Defines the check for a member "name"
68 
69  // Defines the check for a member "eval"
71 
72  /////////////////////////////////////////////////////////////////
73 
74  // Defines the check for a member "isStoring"
76 
77  /// Provides a isStoring attribute
78 #define IS_STORING_ATTRIBUTE(LONG_DESCRIPTION,...)
79  STATIC_CONSTEXPR(/*! Returns whether this SmET is storing */,LONG_DESCRIPTION,bool,isStoring,__VA_ARGS__)
80 
81  /// Set the \c SmET to storing
82 #define STORING
83  IS_STORING_ATTRIBUTE(/*! This \c SmET is storing */,true)
84 
85  /// Set the \c SmET to not-storing
86 #define NOT_STORING
87  IS_STORING_ATTRIBUTE(/*! This \c SmET is not storing */,false)
88 
90 
91  /////////////////////////////////////////////////////////////////
92 
93  /// Provides the \c Tk member
94 #define PROVIDE_TK(...)
95  using Tk=
96  __VA_ARGS__
97 
98  // Defines the check for a member type \c Tk
100 
101  /// Returns the fundamental type of a class
102  template <typename T,
103  typename=ConstrainIsSmET<T>>
104  using TkOf=
105  typename RemRef<T>::Tk;
106 
107  /// Provides the \c Fund member
108 #define PROVIDE_FUND(...)
109  using Fund=
110  __VA_ARGS__
111 
112  // Defines the check for a member type \c Fund
114 
115  /// Returns the fundamental type of a class
116  template <typename T,
117  typename=ConstrainIsSmET<T>>
118  using FundTypeOf=
119  typename RemRef<T>::Fund;
120 
121  /////////////////////////////////////////////////////////////////
122 
123  // Defines the check for a member variable \c isAliasing
125 
126  /// Provides a \c isAliasing method, taking \c alias as argument
127 #define PROVIDE_IS_ALIASING(LONG_DESCRIPTION,...)
128  LONG_DESCRIPTION
129  template <typename Tref>
130  bool isAliasing(const Tref& alias) const
131  {
132  __VA_ARGS__;
133  }
134 
135  /// Set aliasing according to a passed pointer (provided class member)
136  ///
137  /// \todo This is mostly broken
138 #define IS_ALIASING_ACCORDING_TO_POINTER(_p)
139  PROVIDE_IS_ALIASING( /*! Check the aliasing with reference */,
140  CRASH<<"Broken";
141 
142  const void* pAlias=
143  static_cast<const void*>(&alias);
144  const void* p=
145  static_cast<const void*>(_p);
146 
147  return pAlias==p;)
148 
149  /////////////////////////////////////////////////////////////////
150 
151  // Defines the check for a member variable \c isAssignable
153 
154  /// Provides a \c isAssignable attribute
155 #define IS_ASSIGNABLE_ATTRIBUTE(LONG_DESCRIPTION,...)
156  STATIC_CONSTEXPR(/*! Returns whether this \c SmET can be the left hand of an assignement */,LONG_DESCRIPTION,bool,isAssignable,__VA_ARGS__)
157 
158  /// Set the \c SmET as assignable
159 #define ASSIGNABLE
160  IS_ASSIGNABLE_ATTRIBUTE(/*! This \c SmET can be assigned */,true)
161 
162  /// Set the \c SmET as not-assignable
163 #define NOT_ASSIGNABLE
164  IS_ASSIGNABLE_ATTRIBUTE(/*! This \c SmET cannot be assigned */,false)
165 
166  /////////////////////////////////////////////////////////////////
167 
168  /// Provide the MergeableComps type, \c assertMergebaleWith and \c getMaximallyMergedCompsView
169  ///
170  /// The type must be an ordered \c IntSeq indicating the splitting
171  /// point of the \c TensKind, as in this example:
172  ///
173  /// \code
174  /// // Maximal splitting
175  /// Using Tk=
176  /// TensKind<Spin,Col>
177  /// PROVIDE_MERGEABLE_COMPS(/*! Description */,IntSeq<0,2>);
178  /// \endcode
179 #define PROVIDE_MERGEABLE_COMPS(LONG_DESCRIPTION,...)
180  USING(/*! List of points where the \c TensKind can be split */,LONG_DESCRIPTION,MergeableComps,__VA_ARGS__);
181 
182  /*! Assert that a given merging condition is valid */
183  template <typename Is,
184  typename=EnableIf<isIntSeq<Is>>>
185  static constexpr void assertMergeableWith()
186  {
187  static_assert(Unqualified<MergeableComps>::template isSubsetOf<Is>,"Unable to merge this components");
188  }
189 
190  /*! Returns the maximal possible merged comps view */
191  DECLAUTO getMaximallyMergedCompsView()
192  {
193  return getMergedCompsView<MergeableComps>();
194  }
195 
196  /// States that the class has no mergeable component
197 #define NOT_MERGEABLE
198  PROVIDE_MERGEABLE_COMPS(/*! The class has no mergeable componentes */,IntSeq<>)
199 
200  /// States that the class has no mergeable component
201 #define PROVIDE_MERGEABLE_COMPS_MARKING_ONE_AS_NON_MERGEABLE(LONG_DESCRIPTION,IN_MERGEABLE_COMPS,POS)
202  PROVIDE_MERGEABLE_COMPS(LONG_DESCRIPTION,
203  InsertIntSeqInOrderedIntSeq<
204  IntSeq<POS,POS+1>, /*! Position where to insert */
205  IN_MERGEABLE_COMPS, /*! Incoming mergeable components */
206  IntSeq<0,0>, /*! Shift 0 after insertion */
207  true>) /*! Ignore if already present */
208 
209  // Check that we know which components can be merged
211 
212  // Check that we know how to check if merge is valid
214 
215  /// Provides a \c getMergedCompsView method, taking Is as template parameter
216 #define PROVIDE_GET_MERGED_COMPS_VIEW(DESCRIPTION,...)
217  DESCRIPTION
218  template <typename Is> /* IntSeq delimiting the comps groups */
219  DECLAUTO getMergedCompsView()
220  const
221  {
222  /* Check that we can merge as asked */
223  assertMergeableWith<Is>();
224 
225  __VA_ARGS__;
226  }
227 
228  PROVIDE_ALSO_NON_CONST_METHOD(getMergedCompsView)
229 
230  // Check that we know how to get a MergedCompsView
232 
233  /// Provides the \c MergedDelim attribute for Refs of a given \c ID
234  ///
235  /// \todo Add some more explenation...
236 #define PROVIDE_POS_OF_TCS_IN_RES_TK_AND_MERGED_DELIMS_FOR_REF(ID)
237  /*! Position of all the \c TensComp of \c Ref ## ID in Res Tk */
238  using PosOfRef ## ID ## TcsInResTk=
239  PosOfTypesNotAsserting<typename Tk::types,typename TK ## ID::types>;
240 
241  /*! Position of all the \c TensComp of \c Ref ## ID present in Res Tk */
242  using PosOfRef ## ID ## PresTcsInResTk=
243  FilterVariadicClassPos<IsPresent,PosOfRef ## ID ## TcsInResTk>;
244 
245  /*! Merged delimiters of Ref ## ID according to MD */
246  template <typename MD> /* Required merging delimiters */
247  using MergedDelims ## ID=
248  IntSeqGetElsAfterAppending<TK ## ID::nTypes,false,MD,PosOfRef ## ID ## TcsInResTk>
249 
250  /////////////////////////////////////////////////////////////////
251 
252  /// Defines the check for a SmET
253  ///
254  /// \todo add costRead
255  /// \todo add costEval
256  /// \todo add isAliasing
257 #define STATIC_ASSERT_IS_SMET(...)
258  STATIC_ASSERT_HAS_MEMBER(eval,__VA_ARGS__);
259  STATIC_ASSERT_HAS_MEMBER(compSize,__VA_ARGS__);
260  STATIC_ASSERT_HAS_MEMBER(isAliasing,__VA_ARGS__);
261  STATIC_ASSERT_HAS_MEMBER(isAssignable,__VA_ARGS__);
262  STATIC_ASSERT_HAS_MEMBER(isStoring,__VA_ARGS__);
263  STATIC_ASSERT_HAS_MEMBER(MergeableComps,__VA_ARGS__);
264  STATIC_ASSERT_HAS_MEMBER(assertMergeableWith,__VA_ARGS__);
265  STATIC_ASSERT_HAS_MEMBER(getMergedCompsView,__VA_ARGS__);
266  STATIC_ASSERT_HAS_MEMBER(Tk,__VA_ARGS__);
267  STATIC_ASSERT_HAS_MEMBER(Fund,__VA_ARGS__)
268 
269  /// Smart Expression Templates
270  template <typename T>
271  struct SmET :
272  public BaseSmET
273  {
275 
276  /// Provide the call operator with a given qualifier
277 #define PROVIDE_CALL_OPERATOR(QUALIFIER)
278  /*! Implements the QUALIFIER call operator via \c CRTP */
279  template <typename...Oth> /* Type of the other quantity */
280  DECLAUTO operator()(Oth&&...oth) QUALIFIER /*!< Other quantit */
281  {
282  if constexpr(0)
283  std::cout<<"Using CRTP to cast call operator"<<std::endl;
284 
285  return
286  (~(*this)).eval(forw<Oth>(oth)...);
287  }
288 
291 
292 #undef PROVIDE_CALL_OPERATOR
293  };
294 
295  /// Defines a simple way to swap an SmET from rhs to lhs
296  ///
297  /// \todo why can't we make only const & on rhs?
298  /// \todo we need to enforce SmET
299 #define SMET_GOES_ON_LHS(LHS_FUN, /*!< External builder */
300  SMET) /*!< Name of the \c SmET */
301  /*! Simplify EXT_FUN( SMET u) expression */
302  /*! */
303  /*! Returns INT_FUN(EXT_FUN(u.ref)) */
304  template <typename Lhs, /* Type of the lhs \c SmET */
305  typename Rhs, /* Type of the rhs \c SMET */
306  SFINAE_ON_TEMPLATE_ARG(is ## SMET<Rhs>)> /* Enable only for the \c SMET required */
307  void assign(Lhs&& lhs, /*!< Lhs of the assignement */
308  Rhs&& rhs) /*!< Rhs of the assignement, to free from \c SMET */
309  {
310  if(1)
311  {
312  using namespace std;
313  cout<<"Moving " #SMET "to lhs"<<endl;
314  }
315  assign(LHS_FUN(forw<Lhs>(lhs)),rhs.ref);
316  }
318 
319 }
320 
321 #endif
#define DEFINE_HAS_MEMBER(TAG)
Definition: TypeTraits.hpp:581
#define CRASH
Initialize the crasher.
Definition: Crash.hpp:13
#define PROVIDE_CRTP_CAST_OPERATOR(CLASS)
Definition: CRTP.hpp:16
#define USING(DESCRIPTION, LONG_DESCRIPTION, NAME,...)
Provides an attribute.
Definition: BaseSmET.hpp:27
#define PROVIDE_MERGEABLE_COMPS(LONG_DESCRIPTION,...)
Definition: BaseSmET.hpp:179
#define IS_STORING_ATTRIBUTE(LONG_DESCRIPTION,...)
Provides a isStoring attribute.
Definition: BaseSmET.hpp:78
#define DEFINE_GETTER_WITH_DEFAULT(NAME,DEFVAL)
Define a getter of an attibute, with a default.
Definition: BaseSmET.hpp:35
#define IS_ASSIGNABLE_ATTRIBUTE(LONG_DESCRIPTION,...)
Provides a isAssignable attribute.
Definition: BaseSmET.hpp:155
#define SWALLOW_SEMICOLON_AT_GLOBAL_SCOPE
#define SFINAE_ON_TEMPLATE_ARG(...)
Definition: SFINAE.hpp:24
#define STATIC_CONSTEXPR(DESCRIPTION, LONG_DESCRIPTION, TYPE, NAME,...)
Provides an attribute.
Definition: BaseSmET.hpp:19
decltype(auto) operator+(T1 &&smet1, T2 &&smet2)
Implement smet1+smet2.
Definition: Add.hpp:87
#define PROVIDE_ALSO_NON_CONST_METHOD(NAME)
Definition: TypeTraits.hpp:376
Smart Expression Templates.
Definition: BaseSmET.hpp:271
#define DECLAUTO
Short name for decltype(auto)
#define PROVIDE_CALL_OPERATOR(QUALIFIER)
Provide the call operator with a given qualifier.
Definition: BaseSmET.hpp:277
#define STATIC_ASSERT_HAS_MEMBER(TAG,...)
Definition: TypeTraits.hpp:560
#define DEFINE_BASE_TYPE(TYPE,...)
Definition: TypeTraits.hpp:526
#define PROVIDE_IS_ALIASING(LONG_DESCRIPTION,...)
Provides a isAliasing method, taking alias as argument.
Definition: BaseSmET.hpp:127