SUNphi  1.0
Bind.hpp
Go to the documentation of this file.
1 #ifndef _BIND_HPP
2 #define _BIND_HPP
3 
4 /// \file Bind.hpp
5 ///
6 /// \brief Defines a class which binds a component of a SmET
7 
8 #ifdef HAVE_CONFIG_H
9  #include <config.hpp>
10 #endif
11 
12 #include <ints/IntSeqRemove.hpp>
13 #include <ios/Logger.hpp>
14 #include <metaprogramming/SFINAE.hpp>
15 #include <smet/NnarySmET.hpp>
16 #include <smet/Reference.hpp>
17 #include <tens/TensClass.hpp>
18 #include <tens/TensComp.hpp>
19 
20 namespace SUNphi
21 {
22  /// Defines a Binder named NAME for type TG
23 #define DEFINE_NAMED_BINDER(TG,
24  NAME)
25  /*! Get a reference to the \c TG component \c id of \c ref */
26  template <typename T> /* Type of the bound expression */
27  DECLAUTO NAME(T&& ref, /*!< Quantity to be bind */
28  const int id) /*!< Component to bind */
29  {
30  return bind<TG>(forw<T>(ref),id);
31  }
32 
33  /// Defines a Binder named NAME for type RwTG or CnTG
34 #define DEFINE_NAMED_RW_OR_COL_BINDER(TG, /*!< Type to get */
35  NAME) /*!< Name of the bindfun */
36  /*! Returns a binder to the only Rw TG or Cn TG type available */
37  template <typename T> /* Type of the bound expression */
38  DECLAUTO NAME(T&& ref, /*!< Quantity to be bound */
39  const int id) /*!< Component to bind */
40  {
41  /*! TensKind of binding expression */
42  using Tk=
43  typename RemRef<T>::Tk;
44 
45  /*! Tuple containing all Tk types */
46  using Tp=
47  typename Tk::types;
48 
49  /*! Check if row type is available */
50  constexpr bool hasRw=
51  tupleHasType<Rw ## TG,Tp>;
52 
53  /*! Check if column type is available */
54  constexpr bool hasCn=
55  tupleHasType<Cn ## TG,Tp>;
56 
57  /*! Check that not more than one type is available */
58  constexpr bool hasOnlyOneType=
59  (hasRw+hasCn<2);
60  static_assert(hasOnlyOneType,"Both types Rw and Cn identfied!");
61 
62  /*! Check that at least one type is available */
63  constexpr bool hasAtLeastOneType=
64  (hasRw+hasCn>0);
65  static_assert(hasAtLeastOneType,"No types Rw and Cn identfied!");
66 
67  /* Identifies the type to return, on the basis of the check above */
68  using Ret=
69  Conditional<hasRw,Rw ## TG,Cn ## TG>;
70 
71  return bind<Ret>(forw<T>(ref),id);
72  }
73 
74  // Base type to qualify as Binder
76 
77  /// Class to bind a component of a SmET
78  template <typename TG, // Type to get
79  typename..._Refs> // Type to bind (passed as variadic)
80  class Binder :
81  public BaseBinder, // Inherit from \c BaseBinder to detect in expression
82  public NnarySmET<Binder<TG,_Refs...>>, // Inherit from \c NnarySmET
83  public ConstrainAreSmETs<_Refs...> // Constrain all \c Refs to be \c SmET
84  {
86 
87  /// Type to get
88  using Tg=
89  TG;
90 
91  /// Index to get
92  const int id;
93 
94  /// \c TensKind of the bound type
95  using NestedTk=
96  typename RemRef<Ref<0>>::Tk;
97 
98  /// Types of the \c TensKind
99  using NestedTypes=
100  typename NestedTk::types;
101 
103 
104  /// Position inside the reference of the type got by the bounder
105  static constexpr int pos=
106  posOfType<TG,typename NestedTk::types>;
107 
108  public:
109 
111 
112  // Attributes
115 
116  /// \c TensKind of the bound expression
117  PROVIDE_TK(typename NestedTk::template AllButType<TG>);
118 
120 
122 
124 
126 
127  PROVIDE_NNARY_GET_MERGED_COMPS_VIEW(/*! Merge the components and create a new \c Binder taking the same component */,return Binder<TG,decltype(MERGED_COMPS_VIEW_OF_REF(0))>(MERGED_COMPS_VIEW_OF_REF(0),id));
128 
129  /// Evaluator for Binder
130  ///
131  /// Internal Evaluator, inserting the id at the correct
132  /// position in the list of args. Check on type B is omitted, as
133  /// the function is called only from an already checked smet
134  template <typename...Args, // Type of the arguments */
135  int...Head, // Position of the first set of args, before insertion
136  int...Tail> // Position of the second set of args, after insertion
137  DECLAUTO binderInternalEval(IntSeq<Head...>, ///< List of position of components before id
138  IntSeq<Tail...>, ///< List of position of components after id
139  const Tuple<Args...>& targs) ///< Components to get
140  const
141  {
142  return get<0>(refs).eval(get<Head>(targs)...,
143  id,
144  get<Tail>(targs)...);
145  }
146 
147  //PROVIDE_ALSO_NON_CONST_METHOD(binderInternalEval);
148 
149  /// Evaluator, external interface
150  ///
151  /// Pass to the internal implementation the integer sequence
152  /// needed to deal properly with the insertion of the arg in the
153  /// correct position
154  template <typename...Args> ///Type of the arguments
155  DECLAUTO eval(const Args&...args) ///< Components to get
156  const
157  {
159 
160  /// Position of the args to forward before insertion
161  using Head=
162  IntsUpTo<pos>;
163 
164  if(0)
165  {
166  using namespace std;
167  cout<<" evaluating binder of component "<<Tg::name();
168  cout<<" position in NestedTk: "<<pos;
169  cout<<" of "<<NestedTk::nTypes<<" types,";
170  cout<<" id: "<<id;
171  cout<<endl;
172  }
173 
174  /// Position of the args to forward after insertion
175  using Tail=
176  typename IntsUpTo<Tk::nTypes-pos>::template Add<pos>;
177 
178  return binderInternalEval(Head{},
179  Tail{},
180  std::forward_as_tuple(args...));
181  }
182 
183  // PROVIDE_ALSO_NON_CONST_METHOD(eval);
184 
186 
188 
189  /// Constructor taking a universal reference and the id
190  ///
191  /// \todo add check on SMET
192  template <typename SMET,
193  typename=EnableIf<isSame<Unqualified<SMET>,Unqualified<Ref<0>>>>>
194  explicit Binder(SMET&& smet, ///< Reference to bind
195  int id) ///< Component to get
196  : refs(forw<SMET>(smet)),id(id)
197  {
198 #ifdef DEBUG_BINDER
199  using namespace std;
200  cout<<"Constructing binder "<<this<<", type "<<TG::name()<<", component: "<<id<<endl;
201 #endif
202  }
203 
204  /// Destructor
206  {
207 #ifdef DEBUG_BINDER
208  using namespace std;
209  cout<<"Destroying binder "<<this<<endl;
210 #endif
211  }
212  };
213 
214  /// Bind the \c id component of type \c Tg from expression \c ref
215  ///
216  /// Returns a plain binder getting from an unbind expression. Checks
217  /// demanded to Binder.
218  template <typename _Tg, // Type to get
219  typename SMET, // Type to bind, deduced from argument
221  DECLAUTO bind(SMET&& smet, ///< Quantity to bind to
222  const int id, ///< Entry of the component to bind
224  {
226 
227  /// Actual type to get
228  using Tg=
229  CompOrTwinned<_Tg,SMET>;
230 
231 #ifdef DEBUG_BINDER
232  using namespace std;
233  cout<<"Constructing a binder for type "<<Tg::name()<<" , storage: "<<getStor(ref)._v<<endl;
234 #endif
235 
236  // Build the binder
237  Binder<Tg,SMET> b(forw<SMET>(smet),id);
238 
239  // Get the TensKind
240  using Tk=
241  typename Unqualified<SMET>::Tk;
242 
243  // Count the free components of SmET
244  constexpr int N=
245  Tk::nTypes;
246 
247  // Check if fully bound
248  constexpr bool FullyBound=
249  (N==1);
250 
251  // Evaluate if fully bound
252  if constexpr(FullyBound)
253  return b.eval();
254  else
255  return b;
256  }
257 
258  // /// Bind the \c id component of type \c Tg from expression \c ref
259  // ///
260  // /// Nested binder getting an already bound expression, swapping the
261  // /// inner and outer types and components if needed.
262  // ///
263  // /// \code
264  // /// Tens<TensKind<Compl,RwSpin>,double> cicc;
265  // /// spin(reim(cicc,0),1);
266  // /// reim(spin(cicc,1),0);
267  // /// \endcode
268  // ///
269  // /// This might be not enough to ensure proper evaluation if the
270  // /// nesting occurs through a wrapper, as in the following example
271  // ///
272  // /// \code
273  // /// spin(wrap(reim(cicc,0)),1);
274  // /// reim(wrap(spin(cicc,1)),0);
275  // /// \endcode
276  // template <typename _Tg, // Type to get
277  // typename InNestedTg, //Type got by the nested bounder
278  // typename InNestedRef> // Type of the nested binder
279  // DECLAUTO bind(const Binder<InNestedTg,InNestedRef>& nb, ///< Binder to rebind
280  // const int id) ///< Component to get
281  // {
282  // // True component searched
283  // using Tg=CompOrTwinned<_Tg,Binder<InNestedTg,InNestedRef>>;
284  // // Tensor Kind of input nested binder
285  // using InNestedRefTk=typename RemRef<InNestedRef>::Tk;
286  // // Types of the Tensor Kind of nested bounder
287  // using NestedTypes=typename InNestedRefTk::types;
288  // // Position inside the nested reference of the type got by the nested bounder
289  // constexpr int InNestedNestedTgPos=posOfType<InNestedTg,NestedTypes>;
290  // // Position inside the nested reference of the type to get
291  // static constexpr int NestedTgPos=posOfType<Tg,NestedTypes>;
292  // // Keep note of whether we need to swap
293  // constexpr bool swap=(NestedTgPos>InNestedNestedTgPos);
294  // // Type got by the output nested binder
295  // using OutNestedTg=Conditional<swap,Tg,InNestedTg>;
296  // // Type got by the output binder
297  // using OutTg=Conditional<swap,InNestedTg,Tg>;
298  // // Nested component
299  // const int nestedId=nb.id;
300  // // Out external component
301  // const int outNestedId=(swap?id:nestedId);
302  // // Out component
303  // const int outId=(swap?nestedId:id);
304  // // Output Nested binder
305  // auto outNestedBinder=bind<OutNestedTg>(nb.ref,outNestedId);
306  // // Type of the output nested binder
307  // using OutNestedBinder=decltype(outNestedBinder);
308 
309  // //cout<<"Constructing a nested binder for type "<<Tg::name()<<", internal binder gets: "<<InNestedTg::name()<<", swap: "<<swap<<endl;
310  // // cout<<"OutTg: "<<OutTg::name()<<" "<<endl;
311  // return evalIfFullyBound(Binder<OutTg,OutNestedBinder>(outNestedBinder,outId));
312  // }
313 
314  // Check that a test Binder is a UnarySmET
316  Tens<TensKind<TensComp<double,1>>,double>>);
317 }
318 
319 #endif
#define AS_ASSIGNABLE_AS_REF(ID)
Get the same assignability of a given ref.
Definition: NnarySmET.hpp:197
#define MERGED_COMPS_VIEW_OF_REF(I)
Returns the merged comps view of the I-th Ref.
Definition: NnarySmET.hpp:334
#define STATIC_ASSERT_TUPLE_HAS_TYPE(T,TP)
Assert if the type T is not in the types of tuple TP.
Definition: TupleClass.hpp:211
#define PROVIDE_POS_OF_RES_TCS_IN_REFS
Provide the position of result Tk TensComp in each input.
Definition: NnarySmET.hpp:206
#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_MERGEABLE_COMPS_ACCORDING_TO_REFS_AND_EXTRA
Provide MergeableComps delimiter according to references and extra.
Definition: NnarySmET.hpp:324
#define PROVIDE_SIMPLE_NNARY_COMP_SIZE
Definition: NnarySmET.hpp:151
#define SFINAE_WORSEN_DEFAULT_VERSION_TEMPLATE_PARS
Definition: SFINAE.hpp:58
#define SAME_FUND_AS_REF(ID)
Get the same Fund type of a given ref.
Definition: NnarySmET.hpp:192
#define PROVIDE_NNARY_GET_MERGED_COMPS_VIEW(DESCRIPTION,...)
Provides a getMergedCompsView method, taking Is as template parameter.
Definition: NnarySmET.hpp:338
#define FORWARD_IS_ALIASING_TO_REFS
Definition: NnarySmET.hpp:420
decltype(auto) bind(SMET &&smet, const int id, DummyTypes...)
Definition: Bind.hpp:221
#define STATIC_ASSERT_IS_NNARY_SMET(...)
Defines the check for a Nnary SmET.
Definition: NnarySmET.hpp:394
#define PROVIDE_EXTRA_MERGE_DELIMS(...)
Add an ExtraDelims IntSeq called ExtraDelims.
Definition: NnarySmET.hpp:313
#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
~Binder()
Destructor.
Definition: Bind.hpp:205
decltype(auto) operator+(T1 &&smet1, T2 &&smet2)
Implement smet1+smet2.
Definition: Add.hpp:87
const int id
Index to get.
Definition: Bind.hpp:92
#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 PROVIDE_SMET_ASSIGNEMENT_OPERATOR(UNARY_SMET)
Defines the assignement operator, calling assign.
Definition: Assign.hpp:35
#define PROVIDE_NNARY_SMET_REFS_AND_CHECK_ARE_N(N)
Definition: NnarySmET.hpp:126
decltype(auto) evalThroughRepresentativeFunctionPassingCompsByName(Ts &&...ts)
Definition: NnarySmET.hpp:101
#define DEFINE_BASE_TYPE(TYPE,...)
Definition: TypeTraits.hpp:526