CEPS  24.01
Cardiac ElectroPhysiology Simulator
CepsFunction.hpp
Go to the documentation of this file.
1 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2  This file is part of CEPS.
3 
4  CEPS is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  CEPS is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with CEPS (see file LICENSE at root of project).
16  If not, see <https://www.gnu.org/licenses/>.
17 
18 
19  Copyright 2019-2024 Inria, Universite de Bordeaux
20 
21  Authors, in alphabetical order:
22 
23  Pierre-Elliott BECUE, Florian CARO, Yves COUDIERE(*), Andjela DAVIDOVIC,
24  Charlie DOUANLA-LONTSI, Marc FUENTES, Mehdi JUHOOR, Michael LEGUEBE(*),
25  Pauline MIGERDITICHAN, Valentin PANNETIER(*), Nejib ZEMZEMI.
26  * : currently active authors
27 
28 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
30 #pragma once
31 
32 #include <functional>
33 
40 
41 namespace ceps
42 {
43 
49  template <typename _Signature>
50  struct Function;
51 
53  template <class _Fn>
54  struct ResultOfImpl
55  {
57  using type = _Fn;
58  };
59 
61  template <typename _Res, typename... _Args>
62  struct ResultOfImpl<Function<_Res(_Args...)>>
63  {
65  using type = _Res;
66  };
67 
69  template <template <class> class _DerivedFn, class _Signature>
70  requires std::derived_from<_DerivedFn<_Signature>, Function<_Signature>>
71  struct ResultOfImpl<_DerivedFn<_Signature>>
72  {
75  };
76 
78  template <class _Fn>
80 
88  template <typename _Res, typename... _Args>
89  struct Function<_Res(_Args...)>
90  {
91 
93  using ReturnType = _Res;
94 
96  using SignatureType = _Res(_Args...);
97 
99  Function() = default;
100 
102  Function(const Function&) = default;
103 
105  Function(Function&&) noexcept = default;
106 
108  Function&
109  operator= (const Function&) = default;
110 
112  Function&
113  operator=(Function&&) noexcept = default;
114 
116  virtual ~Function() = default;
117 
119  _Res
120  virtual eval(_Args... args) = 0;
121 
128  _Res
129  virtual operator() (_Args... args) final
130  {
131  return this->eval(std::forward<_Args>(args)...);
132  }
133 
134  };
135 
136  // ==========================================================================================
137 
139  template <class _Class, class _MemberPtr>
141 
143  template <class _Res, class _Class, class... _Args>
144  struct MemberFunction<_Class, _Res(_Class::*)(_Args...)> : public Function<_Res(_Args...)>
145  {
146 
147  _Class* m_obj;
148  _Res(_Class::*m_pmf)(_Args...);
149 
151  MemberFunction(_Class& obj, _Res(_Class::*pmf)(_Args...)) :
152  m_obj (&obj),
153  m_pmf (pmf)
154  {}
155 
158  m_obj (that.m_obj),
159  m_pmf (that.m_pmf)
160  {}
161 
163  ~MemberFunction() override
164  {}
165 
167  _Res
168  eval(_Args... args) final
169  {
170  return ((*m_obj).*m_pmf)(std::forward<_Args> (args)...);
171  }
172  };
173 
176  template <typename _Res, typename _Class, typename... _Args>
177  struct MemberFunction<_Class*, _Res(_Class::*)(_Args...)> : public Function<_Res(_Args...)>
178  {
179 
180  _Class* m_obj;
181  _Res(_Class::*m_pmf)(_Args...);
182 
184  MemberFunction(_Class *obj, _Res(_Class::*pmf)(_Args...)) :
185  m_obj(obj),
186  m_pmf(pmf)
187  {}
188 
191  m_obj(that.m_obj),
192  m_pmf(that.m_pmf)
193  {}
194 
196  ~MemberFunction() override
197  {}
198 
200  _Res
201  eval(_Args... args) final
202  {
203  return ((*m_obj).*m_pmf)(std::forward<_Args>(args)...);
204  }
205  };
206 
208  template <class _Class, class _Res, class... _Args>
209  inline auto
210  asFunction(_Class obj,_Res(_Class::*fn)(_Args...)) noexcept
211  {
212  return MemberFunction<_Class,_Res(_Class::*)(_Args...)>(obj,fn);
213  }
214 
217  template <class _Class, class _Res, class... _Args>
218  inline auto
219  asFunction(_Class *obj,_Res(_Class::*fn)(_Args...)) noexcept
220  {
221  return MemberFunction<_Class*,_Res(_Class::*)(_Args...)>(obj,fn);
222  }
223 
225  template <class _Class, class _Res, class... _Args>
226  inline auto
227  newFunction(_Class obj,_Res(_Class::*fn)(_Args...)) noexcept
228  {
229  return ceps::getNew<MemberFunction<_Class,_Res(_Class::*)(_Args...)>> (obj,fn);
230  }
231 
234  template <class _Class, class _Res, class... _Args>
235  inline auto
236  newFunction(_Class* obj,_Res(_Class::*fn)(_Args...)) noexcept
237  {
238  return ceps::getNew<MemberFunction<_Class*,_Res(_Class::*)(_Args...)>>(obj,fn);
239  }
240 
241  // ==========================================================================================
242 
244  template <class _Signature>
246 
248  template <class _Res, class... _Args>
249  struct ConstantFunction<_Res(_Args...)> : public Function<_Res(_Args...)>
250  {
251 
252  const _Res& m_var;
253 
255  explicit ConstantFunction(const _Res& var) :
256  m_var(var)
257  {}
258 
261  m_var(that.m_var)
262  {}
263 
265  ~ConstantFunction() override
266  {}
267 
269  _Res
270  eval(_Args... /*args*/) override
271  {
272  return m_var;
273  }
274  };
275 
277  template <class _Res, class... _Args>
278  inline ConstantFunction<_Res(_Args...)>
279  asFunction (const _Res &arg) noexcept
280  {
281  return ConstantFunction<_Res(_Args...)>(arg);
282  }
283 
285  template <CepsSize _N, class _Object, class _Signature>
287 
289  template <CepsSize _N, class _Object, class _Res, class... _Args>
290  struct PiecewiseFunction<_N, _Object, _Res(_Args...)> : public Function<_Res(_Args...)>
291  {
292  public:
294  using KeyType = std::remove_cvref_t<std::tuple_element_t<_N, CepsTuple<_Args...>>>;
297 
300  m_map(map)
301  {}
302 
305  m_map(that.m_map)
306  {}
307 
310  {}
311 
313  _Res
314  eval(_Args... args) final
315  {
316  KeyType key = std::get<_N> (std::forward_as_tuple<_Args...>(args...));
317  CEPS_ABORT_IF (not m_map.contains(key), "no key : " << key);
318  return std::invoke(&m_map.at(key), args...);
319  }
320  };
321 
322  template<char _Op, typename _T1, typename _T2>
324 
326  template<typename _T1, typename _T2>
327  struct ResultOfOperationStruct<'+', _T1, _T2>
328  {
330  using type = decltype(CepsMathOperation<_T1, _T2>::plus(std::declval<_T1>(),std::declval<_T2>()));
331  };
332 
334  template<typename _T1, typename _T2>
335  struct ResultOfOperationStruct<'-', _T1, _T2>
336  {
338  using type = decltype(CepsMathOperation<_T1, _T2>::minus(std::declval<_T1>(),std::declval<_T2>()));
339  };
340 
342  template<typename _T1, typename _T2>
343  struct ResultOfOperationStruct<'*', _T1, _T2>
344  {
346  using type = decltype(CepsMathOperation<_T1, _T2>::mult(std::declval<_T1>(),std::declval<_T2>()));
347  };
348 
350  template<typename _T1, typename _T2>
351  struct ResultOfOperationStruct<'/', _T1, _T2>
352  {
354  using type = decltype(CepsMathOperation<_T1, _T2>::div(std::declval<_T1>(),std::declval<_T2>()));
355  };
356 
358  template<char _Op, typename _T1, typename _T2>
359  using ResultOfOperation = typename ResultOfOperationStruct<_Op, _T1, _T2>::type;
360 
363  template <char _Op, typename _Res1, typename _Res2, typename... _Args>
364  struct FunctionOperation:
365  public Function<ResultOfOperation<_Op, _Res1, _Res2>(_Args...)>
366  {
368  using Fn1 = Function<_Res1 (_Args...)>;
370  using Fn2 = Function<_Res2 (_Args...)>;
372  using Result = ResultOfOperation<_Op, _Res1, _Res2>;
373 
374  const Fn1* m_fn1; ///< @brief left operand
375  const Fn2* m_fn2; ///< @brief right operand
376 
378  FunctionOperation(const Fn1* fn1, const Fn2* fn2) :
379  m_fn1 (fn1),
380  m_fn2 (fn2)
381  {}
382 
384  FunctionOperation(const FunctionOperation& fp) = default;
385 
387  FunctionOperation&
388  operator=(const FunctionOperation& fp) = default;
389 
390  Result
391  eval(_Args... args) override
392  {
393  _Res1 res1 = this->m_fn1->operator()(std::forward<_Args> (args)...);
394  _Res2 res2 = this->m_fn2->operator()(std::forward<_Args> (args)...);
395 
396  if constexpr (_Op == '+')
397  return CepsMathOperation<_Res1, _Res2>::plus(res1, res2);
398  if constexpr (_Op == '-')
399  return CepsMathOperation<_Res1, _Res2>::minus(res1, res2);
400  if constexpr (_Op == '*')
401  return CepsMathOperation<_Res1, _Res2>::mult(res1, res2);
402  if constexpr (_Op == '/')
403  return CepsMathOperation<_Res1, _Res2>::div(res1, res2);
404  }
405  };
406 
407 } // namespace ceps
408 
409 template<typename _T1, typename _T2, typename... _Args>
410 ceps::FunctionOperation<'+', _T1, _T2, _Args...>
411 operator+(const ceps::Function<_T1(_Args...)>& f1, const ceps::Function<_T2(_Args...)>& f2)
412 {
413  return {&f1,&f2};
414 }
415 
416 template<typename _T1, typename _T2, typename... _Args>
417 ceps::FunctionOperation<'-', _T1, _T2, _Args...>
418 operator-(const ceps::Function<_T1(_Args...)>& f1, const ceps::Function<_T2(_Args...)>& f2)
419 {
420  return {&f1,&f2};
421 }
422 
423 template<typename _T1, typename _T2, typename... _Args>
424 ceps::FunctionOperation<'*', _T1, _T2, _Args...>
425 operator*(const ceps::Function<_T1(_Args...)>& f1, const ceps::Function<_T2(_Args...)>& f2)
426 {
427  return {&f1,&f2};
428 }
429 
430 template<typename _T1, typename _T2, typename... _Args>
431 ceps::FunctionOperation<'/', _T1, _T2, _Args...>
432 operator/(const ceps::Function<_T1(_Args...)>& f1, const ceps::Function<_T2(_Args...)>& f2)
433 {
434  return {&f1,&f2};
435 }
#define CEPS_ABORT_IF(condition, message)
Stops the execution with a message if condition is true. If testing is enabled, only throws a runtime...
std::map< _Key, _Tp, _Compare, _Alloc > CepsMap
C++ map.
Definition: CepsTypes.hpp:196
std::tuple< _Args... > CepsTuple
C++ tuple.
Definition: CepsTypes.hpp:188
size_t CepsSize
Size unsigned.
Definition: CepsTypes.hpp:126
A namespace for all utility methods.
auto newFunction(_Class obj, _Res(_Class::*fn)(_Args...)) noexcept
Transforms a member function of class into a MemberFunction struct.
auto asFunction(_Class obj, _Res(_Class::*fn)(_Args...)) noexcept
Transforms a member function of class into a MemberFunction struct.
_Type * getNew(_Args... args)
Allocates memory for one object. Be careful, the expansion of arguments may produce some weird result...
Definition: CepsMemory.hpp:170
typename ResultOfImpl< _Fn >::type ResultOf
Used to get the return type of a function.
Ceps math operator functor, holds (+,-,*,/) definitions depending on mathematical definitions,...
_Res eval(_Args...) override
Call operator.
ConstantFunction(const _Res &var)
Constructor with value.
const _Res & m_var
Returned value.
ConstantFunction(const ConstantFunction &that)
Copy constructor.
Specialization of ceps::Function that returns constant values.
_Res(_Args...) SignatureType
signature type
Function()=default
Construct a new Function object.
Function(Function &&) noexcept=default
Copy constructor.
_Res ReturnType
Return type definition.
Function(const Function &)=default
Copy constructor.
function caller : abstract base, only contains an variadic operator()
MemberFunction(const MemberFunction &that)
Copy constructor.
MemberFunction(_Class &obj, _Res(_Class::*pmf)(_Args...))
Constructor with member function.
_Res eval(_Args... args) final
Call operator.
_Class * m_obj
A pointer to the instance of the member.
_Res eval(_Args... args) final
Call operator.
MemberFunction(const MemberFunction &that)
Copy constructor.
MemberFunction(_Class *obj, _Res(_Class::*pmf)(_Args...))
Constructor with member function ptr.
Just to say that MemberFunction will be templated.
PiecewiseFunction(const PiecewiseFunction &that)
Copy constructor.
std::remove_cvref_t< std::tuple_element_t< _N, CepsTuple< _Args... > >> KeyType
extract the type that designate the region
PiecewiseFunction(const CepsMap< KeyType, _Object > &map)
Constructor with values.
_Res eval(_Args... args) final
Call operator.
Specialization of ceps::Function with several constant values.
typename ResultOfImpl< Function< _Signature > >::type type
the type to return
Simply to indicate that ResultOfImpl will be a template to be specialized.
_Fn type
the type to return
decltype(CepsMathOperation< _T1, _T2 >::minus(std::declval< _T1 >(), std::declval< _T2 >())) type
Type of result of substraction.
decltype(CepsMathOperation< _T1, _T2 >::plus(std::declval< _T1 >(), std::declval< _T2 >())) type
Type of result of addition.