SUNphi  1.0
Assign.hpp
Go to the documentation of this file.
1 #ifndef _ASSIGN_HPP
2 #define _ASSIGN_HPP
3 
4 /// \file Assign.hpp
5 ///
6 /// \brief Defines a class which assigns rhs SmET to lhs one
7 ///
8 /// These are the steps:
9 ///
10 /// - The call to \c A=B, with \c A being a \c SmET, is intercepted. If \c A is
11 /// not assignable an exception is issued. This step is performed in each individual \c SmET,
12 /// because \c operator= must be a static member function. The function \c assign(A,B) is called.
13 /// - All call to \c assign where \c B is not a \c SmET are intercepted.
14 /// If \c B fundamental type is of a type that can be cast to the fundamental
15 /// type of A, then we return \c A=scalar(B). Otherwise an exception is issued.
16 /// - If B does not contain all components of \c A, an exception is issued.
17 /// - Preliminary manipulation is performed, allowing to specific pattern recognition,
18 /// obtained by overloading \c assign and using appropriate \c SFINAE mechanism.
19 /// - The default \c assign function is called, which returns the rhs as expected
20 /// allowing to perform chain assignement on the expected return.
21 /// - The \c Assigner is created inside assign.
22 /// - If the \c Assigner has mergeable components, they are merged.
23 /// - If the innermost component is vectorizable, it is vectorized.
24 /// - The execution of the assigner is dispatched to the thread pool.
25 ///
26 
27 #include <ios/Logger.hpp>
28 #include <smet/BinarySmET.hpp>
29 #include <smet/Reference.hpp>
30 #include <smet/ScalarWrap.hpp>
31 
32 namespace SUNphi
33 {
34  /// Defines the assignement operator, calling assign
35 #define PROVIDE_SMET_ASSIGNEMENT_OPERATOR(UNARY_SMET /*!< Name of the NnarySmET */)
36  /*! Assign from another object */
37  template <typename Oth> /* Other type */
38  DECLAUTO operator=(Oth&& oth) /*!< Other object */
39  {
40  if(0)
41  {
42  using namespace std;
43  cout<<"Operator=, triggering assignement to "<<this<<" of "<<&oth<<endl;
44  }
45  assign(*this,forw<Oth>(oth));
46 
47  return
48  *this;
49  }
50 
51  // Base type to qualify as an \c Assigner
53 
54  /// Class to assign a \c SmET to another one
55  template <typename _Ref1, // Type of l.h.s
56  typename _Ref2, // Type of r.h.s
57  typename TK1=typename RemRef<_Ref1>::Tk, // \c TensKind of the l.h.s
58  typename TK2=typename RemRef<_Ref2>::Tk> // \c TensKind of the r.h.s
59  class Assigner :
60  public BaseAssigner, // Inherit from \c BaseAssigner to detect in expression
61  public BinarySmET<Assigner<_Ref1,_Ref2>> // Inherit from \c BinarySmET
62  {
65 
66  // Check that the r.h.s Fund type can be converted into l.h.s
69  FundTypeOf<_Ref1>>,
70  "Need to be able to convert the r.h.s into l.h.s fundamental types");
71 
72  public:
73 
74  /// Returns the size of a component
75  template <typename TC,
76  typename=ConstrainIsTensComp<TC>>
77  int compSize() const
78  {
79  // Returns the size if it's in the l.h.s \c Tk or in the r.h.s one
81  return
82  ref1.template compSize<TC>();
83  else
84  CRASH<<"Cannot refer to a TensComp which is not in the l.h.s";
85  }
86 
88 
89  // Attributes
92 
93  /// \c TensorKind of the result is the same of l.h.s
95 
96  /// Fundamental type is of the same type of the l.h.s
98 
101 
103 
104  // Returns a component-merged version
105  PROVIDE_GET_MERGED_COMPS_VIEW(/*! Merge appropriately the two references and returns their assignement */,
106  return
109 
110  /// Provides either the const or non-const evaluator
111 #define PROVIDE_CONST_OR_NOT_DEFAULT_EVALUATOR(QUALIFIER)
112  /*! QUALIFIER evaluator for Assigner, evaluating r.h.s */
113  template <typename...Args> /* Type of the arguments */
114  DECLAUTO eval(const Args&...args) /*!< Components to get */
115  QUALIFIER
116  {
117  STATIC_ASSERT_ARE_N_TYPES(Tk::nTypes,args);
118 
119  return ref2.eval(forw<Args>(args)...);
120  }
121 
124 
125 #undef PROVIDE_CONST_OR_NOT_DEFAULT_EVALUATOR
126 
128  };
129 
130  /// Default assigner taking only \c SmET as left argument
131  ///
132  /// \c Rhs can be a \c SmET or not, in which case it is wrapped into a Scalar
133  template <typename Lhs, // Type of the l.h.s \c SmET
134  typename Rhs, // Type of the r.h.s
138  void assign(Lhs&& lhs, ///< Left hand side, \c SmET to act upon
139  Rhs&& rhs, ///< Right hand side
141  {
143 
144  //take note whether the second member is a SmET, then loop on it
145  const bool rhsIsSmET=
146  isSmET<Rhs>;
147 
148  if constexpr(not rhsIsSmET)
149  return assign(forw<Lhs>(lhs),scalarWrap(forw<Rhs>(rhs)));
150 // else
151 // {
152 
153 // if constexpr(TkOf<Lhs>::template contains<TkOf<Rhs>>)
154 // {
155 // /// Outermost TensComp of rhs
156 // using RhsFirstComp=
157 // Unqualified<TupleElementType<0,typename TkOf<Rhs>::types>>;
158 
159 // /// Maximal value reachable from the component
160 // const int maxEntry=
161 // rhs.template compSize<RhsFirstComp>();
162 
163 // #ifdef DEBUG_ASSIGN
164 // using namespace std;
165 // cout<<" Assign: "<<RhsFirstComp::name()<<" "<<maxEntry;
166 // cout.flush();
167 // cout<<", lhs: "<<&lhs;
168 // cout.flush();
169 // cout<<", rhs: "<<&rhs;
170 // cout.flush();
171 // cout<<", storage1: "<<getStor(lhs)._v;
172 // cout.flush();
173 // cout<<", storage2: "<<getStor(rhs)._v;
174 // cout.flush();
175 // cout<<endl;
176 // #endif
177 
178 // // Assigns all entries
179 // for(int i=0;i<maxEntry;i++)
180 // bind<RhsFirstComp>(forw<Lhs>(lhs),i)=
181 // bind<RhsFirstComp>(forw<Rhs>(rhs),i);
182 // }
183 // else
184 // {
185 // /// Tens Kind of the lhs expression
186 // using TKL=
187 // typename RemRef<Lhs>::Tk;
188 
189 // /// Outermost TensComp of lhs
190 // using LhsFirstComp=
191 // Unqualified<TupleElementType<0,typename TKL::types>>;
192 
193 // /// Maximal value reachable from the component
194 // const int maxEntry=
195 // lhs.template compSize<LhsFirstComp>();
196 
197 // /// Assigns all entries
198 // for(int i=0;i<maxEntry;i++)
199 // bind<LhsFirstComp>(forw<Lhs>(lhs),i)=
200 // rhs;
201 // }
202 // }
203  }
204 }
205 
206 #endif
#define STATIC_ASSERT_IS_SMET(...)
Definition: BaseSmET.hpp:257
#define STATIC_ASSERT_ARE_N_TYPES(N, UNEXP_PARPACK)
Static assert if not passing exactly N types.
Definition: TypeTraits.hpp:422
#define PROVIDE_TK(...)
Provides the Tk member.
Definition: BaseSmET.hpp:94
#define PROVIDE_BINARY_SMET_SIMPLE_CREATOR(BINARY_SMET)
Defines a simple creator taking a reference.
Definition: BinarySmET.hpp:48
#define PROVIDE_FUND(...)
Provides the Fund member.
Definition: BaseSmET.hpp:108
#define CRASH
Initialize the crasher.
Definition: Crash.hpp:13
#define PROVIDE_GET_MERGED_COMPS_VIEW(DESCRIPTION,...)
Provides a getMergedCompsView method, taking Is as template parameter.
Definition: BaseSmET.hpp:216
#define NON_CONST_QUALIF
Empty token to be used in macro expecting qualifier.
Definition: TypeTraits.hpp:35
#define SFINAE_WORSEN_DEFAULT_VERSION_TEMPLATE_PARS
Definition: SFINAE.hpp:58
#define PROVIDE_CONST_OR_NOT_DEFAULT_EVALUATOR(QUALIFIER)
Provides either the const or non-const evaluator.
Definition: Assign.hpp:111
#define PROVIDE_BINARY_SMET_REFS
Provide the reference to the objects.
Definition: BinarySmET.hpp:41
#define SFINAE_ON_TEMPLATE_ARG(...)
Definition: SFINAE.hpp:24
#define PROVIDE_POS_OF_TCS_IN_RES_TK_AND_MERGED_DELIMS_FOR_REF(ID)
Definition: BaseSmET.hpp:236
#define SFINAE_WORSEN_DEFAULT_VERSION_ARGS_CHECK
Check that no extra arg is passed.
Definition: SFINAE.hpp:66
#define NOT_STORING
Set the SmET to not-storing.
Definition: BaseSmET.hpp:86
decltype(auto) operator+(T1 &&smet1, T2 &&smet2)
Implement smet1+smet2.
Definition: Add.hpp:87
#define FORWARD_IS_ALIASING_TO_PAIR_OF_REFS
Definition: BinarySmET.hpp:81
#define PROVIDE_MERGEABLE_COMPS_ACCORDING_TO_TWO_REFS
Definition: BinarySmET.hpp:202
#define CONST_QUALIF
Token to be used in macro indicating "const" keyword.
Definition: TypeTraits.hpp:38
#define SFINAE_WORSEN_DEFAULT_VERSION_ARGS
Provide empty list of args, used to unprioritize default version.
Definition: SFINAE.hpp:62
#define DECLAUTO
Short name for decltype(auto)
#define DEFINE_BASE_TYPE(TYPE,...)
Definition: TypeTraits.hpp:526