SUNphi  1.0
UnarySmET.hpp
Go to the documentation of this file.
1 #ifndef _UNARYSMET_HPP
2 #define _UNARYSMET_HPP
3 
4 /// \file UnarySmET.hpp
5 ///
6 /// \brief Header file defining basic properties of Unary SmET
7 
8 #include <iostream>
9 
10 #include <metaprogramming/SFINAE.hpp>
11 #include <smet/BaseSmET.hpp>
12 #include <smet/Reference.hpp>
13 
14 #if 0
15 namespace SUNphi
16 {
17  /// Defines the UnarySmET type traits
18  DEFINE_BASE_TYPE(UnarySmET,: public BaseSmET);
19 
20  // Defines the check for a member type "ref"
21  DEFINE_HAS_MEMBER(ref);
22 
23  /// Defines the check for a Unary SmET
24 #define STATIC_ASSERT_IS_UNARY_SMET(...)
25  STATIC_ASSERT_IS_SMET(__VA_ARGS__);
26  STATIC_ASSERT_HAS_MEMBER(ref,__VA_ARGS__)
27 
28  /// Unary SmET
29  template <typename T>
30  struct UnarySmET :
31  public SmET<T>,
32  public BaseUnarySmET
33  {
34  PROVIDE_CRTP_CAST_OPERATOR(T);
35  };
36 
37  /// Provide the reference to the object
38 #define PROVIDE_UNARY_SMET_REF
39  PROVIDE_SMET_REF()
40 
41  /// Declare that the fundamental type is the same of the reference
42 #define SAME_FUND_TYPE_OF_REF
43  /*! Same fundamental type of the reference */
44  using Fund=
45  typename RemRef<decltype(ref)>::Fund
46 
47  /////////////////////////////////////////////////////////////////
48 
49  /// Set the assignability according to the reference
50 #define ASSIGNABLE_ACCORDING_TO_REF
51  IS_ASSIGNABLE_ATTRIBUTE(/*! This SmET can be assigned if the reference can */,RemRef<decltype(ref)>::isAssignable)
52 
53  /////////////////////////////////////////////////////////////////
54 
55  /// Set the mergeable components equal to the reference
56 #define MERGEABLE_ACCORDING_TO_REF
57  PROVIDE_MERGEABLE_COMPS(/*! The components of this SmET can be merged as the reference one */,typename RemRef<decltype(ref)>::MergeableComps)
58 
59  /// Returns a version of the SmET with simple merging structure
60 #define PROVIDE_UNARY_SMET_SIMPLE_GET_MERGED_COMPS_VIEW(UNARY_SMET) /* Name of the SmET type */
61  PROVIDE_GET_MERGED_COMPS_VIEW(/*! Returns a component-merged version */,
62  auto refMerged=ref.template mergedComps<Is>();
63  return UNARY_SMET<decltype(refMerged)>(std::move(refMerged)))
64 
65  /////////////////////////////////////////////////////////////////
66 
67  /// Set the size of components according to the reference
68 #define SAME_COMP_SIZES_OF_REF
69  /*! Returns the size of a component, matching the reference */
70  template <typename TC,
71  SFINAE_WORSEN_DEFAULT_VERSION_TEMPLATE_PARS>
72  int compSize(SFINAE_WORSEN_DEFAULT_VERSION_ARGS) const
73  {
74  SFINAE_WORSEN_DEFAULT_VERSION_ARGS_CHECK;
75 
76  return
77  ref.template compSize<TC>();
78  }
79 
80  /// Set the size of a specific component
81 #define PROVIDE_COMP_SIZES_FOR(TC,...)
82  /*! Returns the size of component TC */
83  template <typename T,
84  SFINAE_ON_TEMPLATE_ARG(isSame<T,TC>)>
85  int compSize() const
86  {
87  __VA_ARGS__;
88  }
89 
90  /////////////////////////////////////////////////////////////////
91 
92  /// Defines a simple creator taking a reference
93 #define PROVIDE_UNARY_SMET_SIMPLE_CREATOR(UNARY_SMET /*!< Name of the UnarySmET */)
94  /*! Constructor taking universal reference */
95  template <typename Oth,
96  typename=EnableIf<isSame<Unqualified<Oth>,Unqualified<Ref>>>>
97  explicit UNARY_SMET(Oth&& oth) : ref(forw<Oth>(oth))
98  {
99  }
100 
101  /// Defines the assignement operator, calling assign
102 #define PROVIDE_UNARY_SMET_ASSIGNEMENT_OPERATOR(UNARY_SMET /*!< Name of the UnarySmET */)
103  /*! Assign from another object */
104  template <typename Oth> /* Other type */
105  UNARY_SMET& operator=(Oth&& oth) /*!< Other object */
106  {
107  if(0)
108  {
109  using namespace std;
110  cout<<"Operator=, triggering assignement to "<<this<<" of "<<&oth<<endl;
111  }
112  assign(*this,forw<Oth>(oth));
113 
114  return
115  *this;
116  }
117 
118  /////////////////////////////////////////////////////////////////
119 
120  /// Set aliasing according to the isAliasing of reference
121  ///
122  /// \todo enforce cehck only with TensClass, or with storing classes
123 #define FORWARD_IS_ALIASING_TO_REF
124  PROVIDE_IS_ALIASING(/*! Forward aliasing check to the reference */,
125  return ref.isAliasing(alias);)
126 
127  /// Create a simple builder with a name and a UNARY_SMET returned type
128 #define SIMPLE_UNARY_SMET_BUILDER(BUILDER, /*!< Name of builder fun */
129  UNARY_SMET) /*!< Name of the UnarySmET to build */
130  /*! Simple UNARY_SMET builder called BUILDER */
131  /*! */
132  /*! Plain UNARY_SMET getting a plain SmET */
133  template <typename T, /* Type of the SmET to get */
134  SFINAE_WORSEN_DEFAULT_VERSION_TEMPLATE_PARS>
135  UNARY_SMET<T> BUILDER(T&& smet, /*!< SmET to act upon */
136  SFINAE_WORSEN_DEFAULT_VERSION_ARGS)
137  {
138  SFINAE_WORSEN_DEFAULT_VERSION_ARGS_CHECK;
139 
140  if constexpr(0)
141  {
142  using namespace std;
143  constexpr bool IsLvalue=isLvalue<T>;
144  constexpr bool IsConst=isConst<T>;
145  cout<<"Building " #UNARY_SMET " through " #BUILDER <<endl;
146  constexpr bool Is=std::is_reference<T>::value;
147  cout<<" IsLvalue: "<<IsLvalue<<", Is: "<<Is<<", IsConst: "<<IsConst<<endl;
148  }
149  return UNARY_SMET<T>(forw<T>(smet));
150  }
151  SWALLOW_SEMICOLON_AT_GLOBAL_SCOPE
152 
153  /// Provides const or non-const evaluator
154 #define PROVIDE_UNARY_SMET_CONST_OR_NOT_DEFAULT_EVALUATOR(QUALIFIER) /*!< Const or not */
155  /*! QUALIFIER Evaluator */
156  /*! \todo add/check that const qualifier is properly added to output */
157  template <typename...Args>
158  DECLAUTO eval(const Args&...args) /*!< Parameters to pass */
159  QUALIFIER
160  {
161  STATIC_ASSERT_ARE_N_TYPES(TK::nTypes,args);
162 
163  return
164  ref.eval(forw<const Args>(args)...);
165  }
166 
167  /// Provides both const and non-const evaluators
168 #define PROVIDE_UNARY_SMET_DEFAULT_EVALUATOR
169  PROVIDE_UNARY_SMET_CONST_OR_NOT_DEFAULT_EVALUATOR(NON_CONST_QUALIF);
170  PROVIDE_UNARY_SMET_CONST_OR_NOT_DEFAULT_EVALUATOR(CONST_QUALIF)
171 
172  /// Implements a duplicated-call canceller
173  ///
174  /// Example
175  /// \code
176  /// Tens<TensKind<Compl>,double> cicc;
177  /// conj(conj(cicc)); // returns cicc
178  /// \endcode
179 #define CANCEL_DUPLICATED_UNARY_SMET_CALL(CALLER, /*!< Name of builder */
180  UNARY_SMET) /*!< Type to un-nest */
181  /*! Simplify CALLER(UNARY_SMET) expression */
182  /*! */
183  /*! Returns the nested reference */
184  template <typename T, /* Type of the expression */
185  typename RrT=RemRef<T>, /* T without ref attributes */
186  typename Ref=typename RrT::Ref, /* Type of the reference */
187  typename RrRef=RemRef<Ref>, /* Ref without ref attributes */
188  bool SmETIsLvalue=isLvalue<RrT>, /* Detect if SmET is an lvalue */
189  bool RefIsLvalue=isLvalue<RrRef>, /* Detect if Ref is an lvalue */
190  bool RefIsStoring=isStoring<RrRef>, /* Detect if Ref is storing */
191  bool RetByRef=RefIsStoring or /* Returns by val if Ref is storing, or */
192  RefIsLvalue or SmETIsLvalue, /* lvalue is involved */
193  typename Ret=Conditional<RetByRef,RrRef&,RrRef>, /* Returned type */
194  SFINAE_ON_TEMPLATE_ARG(is ## UNARY_SMET<RrT>)> /* Enable only for the UNARY_SMET required */
195  Ret CALLER(T&& smet) /*!< Quantity to un-nest */
196  {
197  if constexpr(0)
198  {
199  constexpr bool SmETIsConst=isConst<T>;
200  constexpr bool RefIsConst=isConst<Ref>;
201 
202  using namespace std;
203  cout<<"Removing duplicated call " # CALLER<<" "<<__PRETTY_FUNCTION__<<endl;
204  constexpr bool SmETIs=std::is_reference<T>::value;
205  constexpr bool RefIs=std::is_reference<Ref>::value;
206  cout<<" SmETIsLvalue: "<<SmETIsLvalue<<endl;
207  cout<<" SmETIs: "<<SmETIs<<endl;
208  cout<<" SmETIsConst: "<<SmETIsConst<<endl;
209  cout<<" RefIsLvalue: "<<RefIsLvalue<<endl;
210  cout<<" RefIs: "<<RefIs<<endl;
211  cout<<" RefIsConst: "<<RefIsConst<<endl;
212  }
213 
214  return static_cast<Ret>(smet.ref);
215  }
216  SWALLOW_SEMICOLON_AT_GLOBAL_SCOPE
217 
218  /// Implements a duplicated-call absorber
219  ///
220  /// Example
221  /// \code
222  /// Tens<TensKind<Compl>,double> cicc;
223  /// wrap(wrap(cicc)); // returns wrap(cicc)
224  /// \endcode
225 #define ABSORB_DUPLICATED_UNARY_SMET_CALL(CALLER, /*!< Name of builder */
226  UNARY_SMET) /*!< Type to absorb */
227  /*! Simplify CALLER(UNARY_SMET) expression */
228  /*! */
229  /*! Returns the reference */
230  template <typename D, /* Type of the nested UNARY_SMET */
231  SFINAE_ON_TEMPLATE_ARG(is ## UNARY_SMET<D>)> /* Enable only for the UNARY_SMET required */
232  DECLAUTO CALLER(D&& smet) /*!< UnarySmET to absorb */
233  {
234  return forw<D>(smet);
235  }
236  SWALLOW_SEMICOLON_AT_GLOBAL_SCOPE
237 
238  /// Defines a simple way to swap nested UnarySmET
239  ///
240  /// \todo we need to implement the same check done for
241  /// CANCEL_DUPLICATED_UNARY_SMET_CALL
242 #define UNARY_SMET_GOES_INSIDE(EXT_FUN, /*!< External builder */
243  UNARY_SMET, /*!< Name of the SmET */
244  INT_FUN) /*!< Internal builder */
245  /*! Simplify EXT_FUN(UNARY_SMET u) expression */
246  /*! */
247  /*! Returns INT_FUN(EXT_FUN(u.ref)) */
248  template <typename D, /* Type of the nested UNARY_SMET */
249  SFINAE_ON_TEMPLATE_ARG(is ## UNARY_SMET<D>)> /* Enable only for the UNARY_SMET required */
250  DECLAUTO EXT_FUN(D&& smet) /*!< UnarySmET to nest */
251  {
252  return INT_FUN(EXT_FUN(smet.ref));
253  }
254  SWALLOW_SEMICOLON_AT_GLOBAL_SCOPE
255 
256  /// Defines a simple way to swap an UnarySmET from rhs to lhs
257  ///
258  /// \todo why can't we make only const & on rhs?
259  /// \todo we need to enforce SmET
260 #define UNARY_SMET_GOES_ON_LHS(LHS_FUN, /*!< External builder */
261  UNARY_SMET) /*!< Name of the SmET */
262  /*! Simplify EXT_FUN(UNARY_SMET u) expression */
263  /*! */
264  /*! Returns INT_FUN(EXT_FUN(u.ref)) */
265  template <typename Lhs, /* Type of the lhs SmET */
266  typename Rhs, /* Type of the rhs UNARY_SMET */
267  SFINAE_ON_TEMPLATE_ARG(is ## UNARY_SMET<Rhs>)> /* Enable only for the UNARY_SMET required */
268  void assign(Lhs&& lhs, /*!< Lhs of the assignement */
269  Rhs&& rhs) /*!< Rhs of the assignement, to free from UNARY_SMET */
270  {
271  if(1)
272  {
273  using namespace std;
274  cout<<"Moving " #UNARY_SMET "to lhs"<<endl;
275  }
276  assign(LHS_FUN(forw<Lhs>(lhs)),rhs.ref);
277  }
278  SWALLOW_SEMICOLON_AT_GLOBAL_SCOPE
279 
280 }
281 #endif
282 
283 #endif