Skip to content
Snippets Groups Projects
Commit 4e45948f authored by Stéphane Del Pino's avatar Stéphane Del Pino
Browse files

Move CFunctionEmbedder in its own file

parent 557783a3
No related branches found
No related tags found
1 merge request!37Feature/language
#ifndef CFUNCTION_EMBEDDER_HPP
#define CFUNCTION_EMBEDDER_HPP
#include <PugsMacros.hpp>
#include <cmath>
#include <functional>
#include <iostream>
#include <tuple>
#include <vector>
struct ICFunctionEmbedder
{
virtual void apply(const std::vector<ASTNodeDataVariant>& x, double& f_x) = 0;
};
template <typename FX, typename... Args>
class CFunctionEmbedder : public ICFunctionEmbedder
{
private:
std::function<FX(Args...)> m_f;
using ArgsTuple = std::tuple<Args...>;
template <size_t I>
PUGS_INLINE void
_copy_value(ArgsTuple& t, const std::vector<ASTNodeDataVariant>& v) const
{
std::visit(
[&](auto v_i) {
if constexpr (std::is_arithmetic_v<decltype(v_i)>) {
std::get<I>(t) = v_i;
} else {
std::cerr << __FILE__ << ':' << __LINE__ << ": unexpected argument type!\n";
std::exit(1);
}
},
v[I]);
}
template <size_t... I>
PUGS_INLINE void
_copy_from_vector(ArgsTuple& t, const std::vector<ASTNodeDataVariant>& v, std::index_sequence<I...>) const
{
(_copy_value<I>(t, v), ...);
}
public:
PUGS_INLINE
size_t
numberOfArguments() const
{
return sizeof...(Args);
}
PUGS_INLINE
void
apply(const std::vector<ASTNodeDataVariant>& x, FX& f_x) final
{
constexpr size_t N = std::tuple_size_v<ArgsTuple>;
ArgsTuple t;
using IndexSequence = std::make_index_sequence<N>;
this->_copy_from_vector(t, x, IndexSequence{});
f_x = std::apply(m_f, t);
}
// @note This is written in a template fashion to ensure that function type
// is correct. If one uses simply CFunctionEmbedder(std::function<FX(Args...)>&&),
// types seem unchecked
template <typename FX2, typename... Args2>
CFunctionEmbedder(std::function<FX2(Args2...)> f) : m_f(f)
{
static_assert(std::is_same_v<FX, FX2>, "incorrect return type");
static_assert(sizeof...(Args) == sizeof...(Args2), "invalid number of arguments");
using Args2Tuple = std::tuple<Args2...>;
static_assert(std::is_same_v<ArgsTuple, Args2Tuple>, "invalid arguments type");
}
};
#endif // CFUNCTION_EMBEDDER_HPP
...@@ -5,13 +5,7 @@ ...@@ -5,13 +5,7 @@
#include <node_processor/INodeProcessor.hpp> #include <node_processor/INodeProcessor.hpp>
#include <cmath> #include <CFunctionEmbedder.hpp>
#include <cmath>
#include <functional>
#include <iostream>
#include <tuple>
#include <vector>
template <typename ProvidedValueType, typename ExpectedValueType> template <typename ProvidedValueType, typename ExpectedValueType>
class CFunctionArgumentProcessor final : public INodeProcessor class CFunctionArgumentProcessor final : public INodeProcessor
...@@ -38,73 +32,6 @@ class CFunctionArgumentProcessor final : public INodeProcessor ...@@ -38,73 +32,6 @@ class CFunctionArgumentProcessor final : public INodeProcessor
{} {}
}; };
struct IFunctionEmbedder
{
virtual void apply(const std::vector<ASTNodeDataVariant>& x, double& f_x) = 0;
};
template <typename FX, typename... Args>
class FunctionEmbedder : public IFunctionEmbedder
{
private:
std::function<FX(Args...)> m_f;
using ArgsTuple = std::tuple<Args...>;
template <size_t I>
void
_copy_value(ArgsTuple& t, const std::vector<ASTNodeDataVariant>& v) const
{
std::visit(
[&](auto v_i) {
if constexpr (std::is_arithmetic_v<decltype(v_i)>) {
std::get<I>(t) = v_i;
} else {
std::cerr << __FILE__ << ':' << __LINE__ << ": unexpected argument type!\n";
std::exit(1);
}
},
v[I]);
}
template <size_t... I>
void
_copy_from_vector(ArgsTuple& t, const std::vector<ASTNodeDataVariant>& v, std::index_sequence<I...>) const
{
(_copy_value<I>(t, v), ...);
}
public:
// @warning This is written in a template fashion to ensure that function type
// is correct. If one uses simply FunctionEmbedder(std::function<FX(Args...)>&&),
// types seem unchecked
template <typename FX2, typename... Args2>
FunctionEmbedder(std::function<FX2(Args2...)> f) : m_f(f)
{
static_assert(std::is_same_v<FX, FX2>, "incorrect return type");
static_assert(sizeof...(Args) == sizeof...(Args2), "invalid number of arguments");
using Args2Tuple = std::tuple<Args2...>;
static_assert(std::is_same_v<ArgsTuple, Args2Tuple>, "invalid arguments type");
}
PUGS_INLINE
size_t
numberOfArguments() const
{
return sizeof...(Args);
}
void
apply(const std::vector<ASTNodeDataVariant>& x, FX& f_x) final
{
constexpr size_t N = std::tuple_size_v<ArgsTuple>;
ArgsTuple t;
using IndexSequence = std::make_index_sequence<N>;
this->_copy_from_vector(t, x, IndexSequence{});
f_x = std::apply(m_f, t);
}
};
template <typename ReturnType, typename ExpressionValueType> template <typename ReturnType, typename ExpressionValueType>
class CFunctionExpressionProcessor final : public INodeProcessor class CFunctionExpressionProcessor final : public INodeProcessor
{ {
...@@ -113,7 +40,7 @@ class CFunctionExpressionProcessor final : public INodeProcessor ...@@ -113,7 +40,7 @@ class CFunctionExpressionProcessor final : public INodeProcessor
std::vector<ASTNodeDataVariant>& m_argument_values; std::vector<ASTNodeDataVariant>& m_argument_values;
std::unique_ptr<IFunctionEmbedder> m_embedded_function; std::unique_ptr<ICFunctionEmbedder> m_embedded_function;
public: public:
void void
...@@ -131,7 +58,7 @@ class CFunctionExpressionProcessor final : public INodeProcessor ...@@ -131,7 +58,7 @@ class CFunctionExpressionProcessor final : public INodeProcessor
CFunctionExpressionProcessor(ASTNode& node, std::vector<ASTNodeDataVariant>& argument_values) CFunctionExpressionProcessor(ASTNode& node, std::vector<ASTNodeDataVariant>& argument_values)
: m_node{node}, m_argument_values{argument_values} : m_node{node}, m_argument_values{argument_values}
{ {
m_embedded_function = std::make_unique<FunctionEmbedder<double, double, double>>( m_embedded_function = std::make_unique<CFunctionEmbedder<double, double, double>>(
std::function{[](double x, double y) -> double { return std::sin(x) * std::cos(3 * x) + y; }}); std::function{[](double x, double y) -> double { return std::sin(x) * std::cos(3 * x) + y; }});
} }
}; };
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment