SUNphi  1.0
RelBind.hpp
Go to the documentation of this file.
1 #ifndef _REL_BIND_HPP
2 #define _REL_BIND_HPP
3 
4 /// \file RelBind.hpp
5 ///
6 /// \brief Defines a class which binds a component of a SmET w.r.t another
7 
8 #include <ints/IntSeqInsert.hpp>
9 #include <ints/IntSeqRemove.hpp>
10 #include <metaprogramming/SFINAE.hpp>
11 #include <tens/TensClass.hpp>
12 #include <tens/TensComp.hpp>
13 #include <smet/Bind.hpp>
14 
15 namespace SUNphi
16 {
17  /// Define the prototype for \c relBind function
18 #define REL_BIND_PROTOTYPE
19  template <typename _BoundType, /* TensKind to bind */
20  typename _BoundToType, /* TensKind to which bind */
21  typename SMET, /* Type to bind, deduced from argument */
22  typename _Ad, /* Adapter of the bound component */
24  DECLAUTO relBind(SMET&& smet, /*!< Quantity to bind to */
25  _Ad adapter, /*!< Adapting function */
27 
28  // Forward definition of relBind function, needed because used from the class
30 
31  // Base type to qualify as RelBinder
32  DEFINE_BASE_TYPE(RelBinder);
33 
34  /// Class to bind a component of a SmET
35  ///
36  /// The first type is the bound (invisible) one, the second one is
37  /// the free (visible) one
38  template <typename _BoundType, // TensKind to bind
39  typename _BoundToType, // TensKind to which bind
40  typename _Ad, // Adapter of the bound component
41  typename..._Refs> // Types of nested \c SMeT
42  class RelBinder :
43  public BaseRelBinder, // Inherit from \c BaseRelBinder to detect in expression
44  public NnarySmET<RelBinder<_BoundType,_BoundToType,_Ad,_Refs...>>, // Inherit from \c NnarySmET
45  public ConstrainAreSmETs<_Refs...> // Constrain all \c Refs to be \c SmET
46  {
47  public:
49 
50  /// Tens Kind of the bound type
51  using NestedTk=
52  typename RemRef<Ref<0>>::Tk;
53 
54  /// Types of the tensor kind
55  using NestedTypes=
56  typename NestedTk::types;
57 
58  // Constrain the type to which to bind to be in the Types of the TensKind
59  STATIC_ASSERT_TUPLE_HAS_TYPE(_BoundType,NestedTypes);
60 
61  // Constrain the bound type to be in the Types of the TensKind
62  STATIC_ASSERT_TUPLE_HAS_TYPE(_BoundToType,NestedTypes);
63 
64  /// Type to bind
65  using BoundType=
66  _BoundType;
67 
68  /// Type to which to bind
69  using BoundToType=
70  _BoundToType;
71 
72  private:
73 
74  /// Position inside the reference of the TensKind got by the bounder
75  static constexpr int boundPos=
76  posOfType<_BoundType,typename NestedTk::types>;
77 
78  /// Position inside the reference of the TensKind to which to bind
79  static constexpr int boundToPos=
80  posOfType<_BoundToType,typename NestedTk::types>;
81 
82  /// Adapter, used to remap the boundTo component
83  ///
84  /// The pointer is needed to allow non-member function to be
85  /// passed as adaptor, see:
86  /// https://stackoverflow.com/questions/13233213/can-a-function-type-be-a-class-template-parameter
87  AddPointerIfFunction<_Ad> adapter;
88 
89  /// Dummy type, in which the _BoundType is absolutely bound
90  using absBinder=Binder<_BoundType,Ref<0>>;
91 
92  public:
93 
94  /// TensorKind of the bound expression
95  PROVIDE_TK(typename NestedTk::template AllButType<BoundType>);
96 
97  /// Fundamental type
99 
100  // Attributes
102 
104 
106 
108 
109  /// Position inside the external TensKind to which to bind
110  static constexpr int extBoundToPos=
111  posOfType<_BoundToType,typename Tk::types>;
112 
113  PROVIDE_EXTRA_MERGE_DELIMS(IntSeq<extBoundToPos,extBoundToPos+1>);
114 
116 
118 
119  PROVIDE_NNARY_GET_MERGED_COMPS_VIEW(/*! Insert the position of bound component shifting by 1 afterwards */,
120  return relBind<_BoundType,_BoundToType>(MERGED_COMPS_VIEW_OF_REF(0),adapter));
121 
122  /// Evaluator for \c RelBinder
123  ///
124  /// Internal Evaluator, inserting the id at the correct
125  /// position in the list of args. Check on type B is omitted, as
126  /// the function is called only from an already checked smet
127  template <typename...Args, // Type of the arguments
128  typename Id, // Type of the argument of the bound component
129  int...Head, // Position of the first set of args, before insertion
130  int...Tail> // Position of the second set of args, after insertion
131  DECLAUTO relBinderInternalEval(IntSeq<Head...>, ///< List of position of components before id
132  IntSeq<Tail...>, ///< List of position of components after id
133  const Id& id, ///< Component to insert
134  const Tuple<Args...>& targs) ///< Components to get
135  const
136  {
137 
138  return get<0>(refs).eval(get<Head>(targs)...,
139  id,
140  get<Tail>(targs)...);
141  }
142 
143  PROVIDE_ALSO_NON_CONST_METHOD(relBinderInternalEval);
144 
145  /// Evaluator, external interface
146  ///
147  /// Pass to the internal implementation the integer sequence
148  /// needed to deal properly with the insertion of the arg in the
149  /// correct position
150  template <typename...Args> // Type of the arguments
151  DECLAUTO eval(const Args&...args) ///< Components to get
152  const
153  {
154  STATIC_ASSERT_ARE_N_TYPES(Tk::nTypes,args);
155 
156  using Head=IntsUpTo<boundPos>;
157 
158  /// Value of the boundTo component
159  const auto boundToId=
160  get<extBoundToPos>(Tuple<Args...>(args...));
161 
162  /// Value of the bound component
163  const decltype(boundToId) boundId=
164  adapter(boundToId);
165 
166  if(0)
167  {
168  using namespace std;
169  cout<<" evaluating rel_binder of component "<<_BoundType::name();
170  cout<<" bound to component "<<_BoundToType::name()<<",";
171  cout<<" position where to read the boun-tod component: "<<extBoundToPos;
172  cout<<" bound to component "<<_BoundToType::name();
173  cout<<" of "<<NestedTk::nTypes<<" types,";
174  cout<<" boundToId: "<<boundToId;
175  cout<<" boundId: "<<boundId;
176  cout<<endl;
177  }
178 
179  using Tail=
180  RangeSeq<boundPos,1,Tk::nTypes>;
181 
182  return relBinderInternalEval(Head{},
183  Tail{},
184  boundId,
185  std::forward_as_tuple(args...));
186  }
187 
189 
191 
192  /// Constructor taking a universal reference and the id
193  ///
194  /// \todo add check on SMET
195  template <typename SMET,
196  typename=EnableIf<isSame<Unqualified<SMET>,Unqualified<Ref<0>>>>>
197  explicit RelBinder(SMET&& smet, ///< Reference to bind
198  _Ad&& adapter) ///< Adapting function
199  : refs(std::forward_as_tuple(smet)),adapter(forw<_Ad>(adapter))
200  {
201 #ifdef DEBUG_REL_BINDER
202  using namespace std;
203  cout<<"Constructing relative binder "<<this<<", bound type "<<_BoundType::name()<<", bound to type "<<_BoundToType::name()<<endl;
204 #endif
205  }
206 
207  /// Destructor
208  ~RelBinder()
209  {
210 #ifdef DEBUG_REL_BINDER
211  using namespace std;
212  cout<<"Destroying relative binder "<<this<<endl;
213 #endif
214  }
215 
216  };
217 
218  /// Bind the component of type \c _BoundType to \c _BoundToType
219  ///
220  /// Returns a relative binder getting from an unbind expression.
221  /// Checks demanded to RelBinder
223  {
225 
226  /// Check that the two components are not twinned of each other
227  constexpr bool areTwinnedOfEachOther=
228  isSame<TwinCompOf<_BoundToType>,_BoundType>;
229 
230  using BoundType=
231  Conditional<areTwinnedOfEachOther,_BoundType,CompOrTwinned<_BoundType,SMET>>;
232  using BoundToType=
233  Conditional<areTwinnedOfEachOther,_BoundToType,CompOrTwinned<_BoundToType,SMET>>;
234 
235 #ifdef DEBUG_REL_BINDER
236  using namespace std;
237  cout<<"Constructing a rel binder for type "<<BoundType::name()<<" to type:"<<BoundToType::name()<<" , storage: "<<getStor(smet)._v<<endl;
238 #endif
239 
240  // Build the relative binder. The \c decltype is needed to allow
241  // non-member function to be passd as adapter, see
242  // https://stackoverflow.com/questions/13233213/can-a-function-type-be-a-class-template-parameter
243  RelBinder<BoundType,BoundToType,decltype(adapter),SMET> b(forw<SMET>(smet),forw<_Ad>(adapter));
244 
245  return b;
246  }
247 
248 #undef REL_BIND_PROTOTYPE
249 
250  /// Internal checks
251  namespace _RelBindInternalChecks
252  {
253  DEFINE_TENS_COMP(tc1,Tc1,NTC1,1);
254 
255  DEFINE_TENS_COMP(tc2,Tc2,NTC2,2);
256 
257  /// TensorKind of the expression
258  using Tk=
259  TensKind<Tc1,Tc2>;
260 
261  /// Tensor class of the expression
262  using T=
263  Tens<Tk,double>;
264 
265  /// Function returning the argument
266  template <typename T>
267  T wire(T t) ///< Argument to be returned
268  {
269  return t;
270  }
271 
272  // Check that a test Binder is a NnarySmET
273  STATIC_ASSERT_IS_NNARY_SMET(RelBinder<Tc1,Tc2,
274  decltype(wire<int>),T>);
275  }
276 }
277 
278 #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
#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
#define PROVIDE_ALSO_NON_CONST_METHOD(NAME)
Definition: TypeTraits.hpp:376
#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
#define REL_BIND_PROTOTYPE
Define the prototype for relBind function.
Definition: RelBind.hpp:18
#define DEFINE_BASE_TYPE(TYPE,...)
Definition: TypeTraits.hpp:526
#define DEFINE_TENS_COMP(BINDER,TYPE,CONST_NAME,HMANY)
Definition: TensComp.hpp:73