RFFGen
 All Classes Namespaces Files Functions Typedefs Enumerations Groups
finalize.hh
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the C++-library RFFGen. */
4 /* Copyright 2015 Lars Lubkoll */
5 /* */
6 /* RFFGen is free software: you can redistribute it and/or modify */
7 /* it under the terms of the GNU General Public License as published by */
8 /* the Free Software Foundation, either version 3 of the License, or */
9 /* (at your option) any later version. */
10 /* */
11 /* RFFGen is distributed in the hope that it will be useful, */
12 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14 /* GNU General Public License for more details. */
15 /* */
16 /* You should have received a copy of the GNU General Public License */
17 /* along with RFFGen. If not, see <http://www.gnu.org/licenses/>. */
18 /* */
19 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
20 
21 #ifndef RFFGEN_FINALIZE_HH
22 #define RFFGEN_FINALIZE_HH
23 
24 #include <type_traits>
25 
26 #include "Util/consistencyCheck.hh"
27 #include "Util/indexedType.hh"
28 #include "variable.hh"
29 
30 namespace RFFGen
31 {
35  namespace Detail
36  {
37  template <class ReturnType>
38  struct FillDefault
39  {
40  template <class... Args>
41  __attribute__((always_inline)) ReturnType operator()(const Args&...) const
42  {
43  return 0.;
44  }
45  };
46 
47 
48  template <int id,class ReturnType, bool present>
49  struct FinalizeD1 : FillDefault<ReturnType> {};
50 
51  template <int id,class ReturnType>
52  struct FinalizeD1<id,ReturnType,true>
53  {
54  template <class F, class Arg>
55  __attribute__((always_inline)) ReturnType operator()(const F& f, const Arg& dx) const
56  {
57  return f.template d1<id>(dx);
58  }
59  };
60 
61 
62  template <int idx, int idy, class ReturnType, bool present>
63  struct FinalizeD2 : FillDefault<ReturnType> {};
64 
65  template <int idx, int idy, class ReturnType>
66  struct FinalizeD2<idx,idy,ReturnType,true>
67  {
68  template <class F, class ArgX, class ArgY>
69  __attribute__((always_inline)) ReturnType operator()(const F& f, const ArgX& dx, const ArgY& dy) const
70  {
71  return f.template d2<idx,idy>(dx,dy);
72  }
73  };
74 
75 
76  template <int idx, int idy, int idz, class ReturnType, bool present>
77  struct FinalizeD3 : FillDefault<ReturnType> {};
78 
79  template <int idx, int idy, int idz, class ReturnType>
80  struct FinalizeD3<idx,idy,idz,ReturnType,true>
81  {
82  template <class F, class Arg>
83  __attribute__((always_inline)) ReturnType operator()(const F& f, const Arg& dx, const Arg& dy, const Arg& dz) const { return f.template d3<idx,idy,idz>(dx,dy,dz); }
84  };
85 
86 
90  template <class F, bool arithmeticReturnType, bool hasVariables>
91  struct FinalizeImpl : F
92  {
93  using ReturnType = std::remove_const_t<std::remove_reference_t<decltype(std::declval<F>().d0())> >;
94 
95  template <class... Args>
96  FinalizeImpl(const Args&... args) : F(args...)
97  {}
98 
99  template <int index, class Arg>
100  void update(const Arg& x)
101  {
102  F::template updateVariable<index>(x);
103  F::update(x);
104  }
105 
106  ReturnType operator()() const
107  {
108  return F::d0();
109  }
110 
111  template < int id , class Arg >
112  ReturnType d1(const Arg& dx) const
113  {
114  static_assert( Checks::hasVariableId< F , id >() , "You are trying to compute the first derivative with respect to a variable that is not present" );
115  static_assert( Checks::checkArgument<F,Arg,id>() , "Incompatible argument in computation of first derivative." );
116  static_assert( hasConsistentFirstDerivative< F >() , "Inconsistent functional definition encountered.");
117 
118  return FinalizeD1< id , ReturnType , HasD1MemberFunction< F , IndexedType<Arg,id> >::value>()(static_cast<const F&>(*this),dx);
119  }
120 
121  template < int idx , int idy , class ArgX , class ArgY >
122  ReturnType d2(const ArgX& dx, const ArgY& dy) const
123  {
124  static_assert( Checks::hasVariableId< F , idx >() && Checks::hasVariableId< F , idy>(),
125  "You are trying to compute the second derivative with respect to at least one variable that is not present" );
126  static_assert( Checks::checkArgument<F,ArgX,idx>() , "Incompatible first argument in computation of second derivative." );
127  static_assert( Checks::checkArgument<F,ArgY,idy>() , "Incompatible second argument in computation of second derivative." );
128  static_assert( hasConsistentSecondDerivative< F , IndexedType<ArgX,idx> , IndexedType<ArgY,idy> >(), "Inconsistent functional definition encountered." );
129 
130  return FinalizeD2< idx , idy , ReturnType , HasD2MemberFunction< F , IndexedType<ArgX,idx> , IndexedType<ArgY,idy> >::value>()(static_cast<const F&>(*this),dx,dy);
131  }
132 
133  template < int idx , int idy , int idz , class ArgX , class ArgY , class ArgZ >
134  ReturnType d3(const ArgX& dx, const ArgY& dy, const ArgZ& dz) const
135  {
136  static_assert( Checks::hasVariableId< F , idx >() && Checks::hasVariableId< F , idy>() && Checks::hasVariableId< F , idz >(),
137  "You are trying to compute the third derivative with respect to at least one variable that is not present" );
138  static_assert( Checks::checkArgument<F,ArgX,idx>() , "Incompatible first argument in computation of third derivative." );
139  static_assert( Checks::checkArgument<F,ArgY,idy>() , "Incompatible second argument in computation of third derivative." );
140  static_assert( Checks::checkArgument<F,ArgZ,idz>() , "Incompatible third argument in computation of third derivative." );
141  static_assert(hasConsistentThirdDerivative< F , IndexedType<ArgX,idx> , IndexedType<ArgY,idy> , IndexedType<ArgZ,idz> >(), "Inconsistent functional definition encountered.");
142 
143  return FinalizeD3< idx , idy , idz , ReturnType ,
144  HasD3MemberFunction< F , IndexedType<ArgX,idx> , IndexedType<ArgY,idy> , IndexedType<ArgZ,idz> >::value>()(static_cast<const F&>(*this),dx,dy,dz);
145  }
146  };
147 
148  template <class F>
149  struct FinalizeImpl<F,true,true> : F
150  {
151  using ReturnType = std::remove_const_t<std::remove_reference_t<decltype(std::declval<F>().d0())> >;
152 
153  template <class... Args>
154  FinalizeImpl(const Args&... args) : F(args...)
155  {}
156 
157  template <int index, class Arg>
158  void update(const Arg& x)
159  {
160  F::template updateVariable<index>(x);
161  F::update(x);
162  }
163 
164  ReturnType operator()() const
165  {
166  return F::d0();
167  }
168 
169  template < int id , class Arg = double >
170  ReturnType d1(Arg dx=1) const
171  {
172  static_assert( Checks::hasVariableId< F , id >(), "You are trying to compute the first derivative with respect to a variable that is not present" );
173  static_assert( Checks::checkArgument<F,Arg,id>() , "Incompatible argument in computation of first derivative." );
174  static_assert( hasConsistentFirstDerivative< F >(), "Inconsistent functional definition encountered." );
175  return FinalizeD1< id , ReturnType , HasD1MemberFunction< F , IndexedType<Arg,id> >::value >()(static_cast<const F&>(*this),dx);
176  }
177 
178  template < int idx , int idy , class ArgX = double , class ArgY = double >
179  ReturnType d2(ArgX dx=1, ArgY dy=1) const
180  {
181  static_assert(Checks::hasVariableId< F , idx >() && Checks::hasVariableId< F , idy>(),
182  "You are trying to compute the second derivative with respect to at least one variable that is not present");
183  static_assert( Checks::checkArgument<F,ArgX,idx>() , "Incompatible first argument in computation of second derivative." );
184  static_assert( Checks::checkArgument<F,ArgY,idy>() , "Incompatible second argument in computation of second derivative." );
185  static_assert(hasConsistentSecondDerivative< F , IndexedType<ArgX,idx> , IndexedType<ArgY,idy> >(), "Inconsistent functional definition encountered." );
186 
187  return FinalizeD2< idx , idy , ReturnType , HasD2MemberFunction< F , IndexedType<ArgX,idx> , IndexedType<ArgY,idy> >::value >()(static_cast<const F&>(*this),dx,dy);
188  }
189 
190  template < int idx , int idy , int idz , class ArgX = double , class ArgY = double , class ArgZ = double>
191  ReturnType d3(ArgX dx=1, ArgY dy=1, ArgZ dz=1) const
192  {
193  static_assert(Checks::hasVariableId< F , idx >() && Checks::hasVariableId< F , idy>() && Checks::hasVariableId< F , idz >(),
194  "You are trying to compute the third derivative with respect to at least one variable that is not present");
195  static_assert( Checks::checkArgument<F,ArgX,idx>() , "Incompatible first argument in computation of third derivative." );
196  static_assert( Checks::checkArgument<F,ArgY,idy>() , "Incompatible second argument in computation of third derivative." );
197  static_assert( Checks::checkArgument<F,ArgZ,idz>() , "Incompatible third argument in computation of third derivative." );
198  static_assert(hasConsistentThirdDerivative< F , IndexedType<ArgX,idx> , IndexedType<ArgY,idy> , IndexedType<ArgZ,idz> >(), "Inconsistent functional definition encountered.");
199 
200  return FinalizeD3< idx , idy , idy , ReturnType ,
201  HasD3MemberFunction< F , IndexedType<ArgX,idx> , IndexedType<ArgY,idy> , IndexedType<ArgZ,idz> >::value >()(static_cast<const F&>(*this),dx,dy,dz);
202  }
203  };
204 
205  template <class F>
206  struct FinalizeImpl<F,true,false> : F
207  {
208  using ReturnType = std::remove_const_t<std::remove_reference_t<decltype(std::declval<F>().d0())> >;
209 
210  template <class... Args>
211  FinalizeImpl(const Args&... args) : F(args...)
212  {}
213 
214  template <class Arg>
215  ReturnType operator()(const Arg& x)
216  {
217  F::update(x);
218  return F::d0();
219  }
220 
221 
222  ReturnType operator()() const
223  {
224  return F::d0();
225  }
226 
227  template < int id = 0 , class Arg = double >
228  ReturnType d1(Arg dx=1) const
229  {
230  static_assert( hasConsistentFirstDerivative< F >(), "Inconsistent functional definition encountered." );
231  return FinalizeD1< id , ReturnType , HasD1MemberFunction< F , IndexedType<Arg,id> >::value >()(static_cast<const F&>(*this),dx);
232  }
233 
234  template < int idx = 0 , int idy = 0 , class ArgX = double , class ArgY = double >
235  ReturnType d2(ArgX dx=1, ArgY dy=1) const
236  {
237  static_assert( hasConsistentSecondDerivative< F , IndexedType<ArgX,idx> , IndexedType<ArgY,idy> >(), "Inconsistent functional definition encountered." );
238  return FinalizeD2< idx , idy , ReturnType , HasD2MemberFunction< F , IndexedType<ArgX,idx> , IndexedType<ArgY,idy> >::value >()(static_cast<const F&>(*this),dx,dy);
239  }
240 
241  template < int idx = 0 , int idy = 0 , int idz = 0 , class ArgX = double , class ArgY = double , class ArgZ = double>
242  ReturnType d3(ArgX dx=1, ArgY dy=1, ArgZ dz=1) const
243  {
244  static_assert( hasConsistentThirdDerivative< F , IndexedType<ArgX,idx> , IndexedType<ArgY,idy> , IndexedType<ArgZ,idz> >(), "Inconsistent functional definition encountered." );
245  return FinalizeD3< idx , idy , idy , ReturnType ,
246  HasD3MemberFunction< F , IndexedType<ArgX,idx> , IndexedType<ArgY,idy> , IndexedType<ArgZ,idz> >::value >()(static_cast<const F&>(*this),dx,dy,dz);
247  }
248  };
249 
250  template <class F>
251  struct FinalizeImpl<F,false,false> : F
252  {
253  using ReturnType = std::remove_const_t<std::remove_reference_t<decltype(std::declval<F>().d0())> >;
254 
255  template <class... Args>
256  FinalizeImpl(const Args&... args) : F(args...)
257  {}
258 
259  ReturnType operator()() const
260  {
261  return F::d0();
262  }
263 
264  template < int id = 0 , class Arg = double >
265  ReturnType d1(const Arg& dx) const
266  {
267  static_assert( hasConsistentFirstDerivative< F >(), "Inconsistent functional definition encountered." );
268  return FinalizeD1< id , ReturnType , HasD1MemberFunction< F , IndexedType<Arg,id> >::value >()(static_cast<const F&>(*this),dx);
269  }
270 
271  template < int idx = 0 , int idy = 0 , class ArgX = double , class ArgY = double >
272  ReturnType d2(const ArgX& dx, const ArgY& dy) const
273  {
274  static_assert( hasConsistentSecondDerivative< F , IndexedType<ArgX,idx> , IndexedType<ArgY,idy> >(), "Inconsistent functional definition encountered." );
275  return FinalizeD2< idx , idy , ReturnType , HasD2MemberFunction< F , IndexedType<ArgX,idx> , IndexedType<ArgY,idy> >::value >()(static_cast<const F&>(*this),dx,dy);
276  }
277 
278  template < int idx = 0 , int idy = 0 , int idz = 0 , class ArgX = double , class ArgY = double , class ArgZ = double>
279  ReturnType d3(const ArgX& dx, const ArgY& dy, const ArgZ& dz) const
280  {
281  static_assert( hasConsistentThirdDerivative< F , IndexedType<ArgX,idx> , IndexedType<ArgY,idy> , IndexedType<ArgZ,idz> >(), "Inconsistent functional definition encountered." );
282  return FinalizeD3< idx , idy , idy , ReturnType ,
283  HasD3MemberFunction< F , IndexedType<ArgX,idx> , IndexedType<ArgY,idy> , IndexedType<ArgZ,idz> >::value >()(static_cast<const F&>(*this),dx,dy,dz);
284  }
285  };
286  }
296  template <class F, bool arithmeticArgument = false>
297  using Finalize = Detail::FinalizeImpl< F , arithmeticArgument , Checks::hasVariable<F>() >;
298 
304  template <class F>
305  auto finalize(const F& f)
306  {
307  return Finalize<F>(f);
308  }
309 
315  template <class F>
316  auto finalize_scalar(const F& f)
317  {
318  return Finalize<F,true>(f);
319  }
320 }
321 
322 #endif // RFFGEN_FINALIZE_HH
Detail::FinalizeImpl< F, arithmeticArgument, Checks::hasVariable< F >() > Finalize
Finish function definition.
Definition: finalize.hh:297
auto finalize(const F &f)
Finish function definition.
Definition: finalize.hh:305
auto finalize_scalar(const F &f)
Finish function definition.
Definition: finalize.hh:316