29 #ifndef PIRANHA_LAMBDIFY_HPP 30 #define PIRANHA_LAMBDIFY_HPP 34 #include <initializer_list> 39 #include <type_traits> 40 #include <unordered_map> 44 #include <piranha/detail/sfinae_types.hpp> 46 #include <piranha/math.hpp> 47 #include <piranha/symbol_utils.hpp> 57 template <
typename T,
typename U>
58 using math_lambdified_reqs = std::integral_constant<
59 bool, conjunction<is_evaluable<T, U>, std::is_copy_constructible<T>, std::is_move_constructible<T>>::value>;
87 template <
typename T,
typename U>
90 static_assert(std::is_same<T,
typename std::decay<T>::type>::value,
"Invalid type.");
91 static_assert(std::is_same<U,
typename std::decay<U>::type>::value,
"Invalid type.");
92 static_assert(detail::math_lambdified_reqs<T, U>::value,
"Invalid types.");
97 auto names_copy(m_names);
98 std::sort(names_copy.begin(), names_copy.end());
99 if (std::unique(names_copy.begin(), names_copy.end()) != names_copy.end()) {
100 piranha_throw(std::invalid_argument,
"the list of evaluation symbols contains duplicates");
104 for (
const auto &s : m_names) {
105 if (m_extra_map.find(s) != m_extra_map.end()) {
107 "the extra symbols map contains symbol '" + s
108 +
"', which is already in the symbol list used for the construction " 109 "of the lambdified object");
111 const auto ret = m_eval_dict.emplace(std::make_pair(s, U{}));
112 piranha_assert(ret.second);
113 m_ptrs.push_back(std::addressof(ret.first->second));
116 for (
const auto &p : m_extra_map) {
117 const auto ret = m_eval_dict.emplace(std::make_pair(p.first, U{}));
118 piranha_assert(ret.second);
119 m_ptrs.push_back(std::addressof(ret.first->second));
123 void reconstruct_ptrs()
127 piranha_assert(m_ptrs.empty());
128 piranha_assert(m_eval_dict.size() >= m_extra_map.size()
129 && m_names.size() == m_eval_dict.size() - m_extra_map.size());
131 for (
const auto &s : m_names) {
132 piranha_assert(m_eval_dict.count(s) == 1u);
133 m_ptrs.push_back(std::addressof(m_eval_dict.find(s)->second));
136 for (
const auto &p : m_extra_map) {
137 piranha_assert(m_eval_dict.count(p.first) == 1u);
138 m_ptrs.push_back(std::addressof(m_eval_dict.find(p.first)->second));
141 piranha_assert(m_ptrs.size() ==
static_cast<decltype(m_ptrs.size())
>(m_names.size()) + m_extra_map.size());
155 using extra_map_type = std::unordered_map<std::string, std::function<U(const std::vector<U> &)>>;
188 : m_x(x), m_names(names), m_extra_map(extra_map)
210 : m_x(std::move(x)), m_names(names), m_extra_map(extra_map)
221 : m_x(other.m_x), m_names(other.m_names), m_eval_dict(other.m_eval_dict), m_extra_map(other.m_extra_map)
232 : m_x(
std::move(other.m_x)), m_names(
std::move(other.m_names)), m_eval_dict(
std::move(other.m_eval_dict)),
233 m_extra_map(
std::move(other.m_extra_map))
271 if (unlikely(values.size() != m_eval_dict.size() - m_extra_map.size())) {
272 piranha_throw(std::invalid_argument,
"the size of the vector of evaluation values does not " 273 "match the size of the symbol list used during construction");
275 piranha_assert(values.size() == m_names.size());
276 decltype(values.size()) i = 0u;
277 for (; i < values.size(); ++i) {
278 auto ptr = m_ptrs[
static_cast<decltype(m_ptrs.size())
>(i)];
280 ptr == std::addressof(m_eval_dict.find(m_names[static_cast<decltype(m_names.size())>(i)])->second));
289 for (
const auto &p : m_extra_map) {
290 piranha_assert(i < m_ptrs.size());
291 auto ptr = m_ptrs[
static_cast<decltype(m_ptrs.size())
>(i)];
292 piranha_assert(ptr == std::addressof(m_eval_dict.find(p.first)->second));
293 *ptr = p.second(values);
324 std::vector<std::string> retval;
325 std::transform(m_extra_map.begin(), m_extra_map.end(), std::back_inserter(retval),
326 [](
const typename extra_map_type::value_type &p) {
return p.first; });
332 std::vector<std::string> m_names;
333 std::unordered_map<std::string, U> m_eval_dict;
334 std::vector<U *> m_ptrs;
343 template <
typename T,
typename U>
344 using math_lambdify_type =
345 typename std::enable_if<math_lambdified_reqs<typename std::decay<T>::type,
typename std::decay<U>::type>::value,
346 math::lambdified<typename std::decay<T>::type,
typename std::decay<U>::type>>::type;
349 template <
typename T,
typename U>
350 using math_lambdify_extra_map_type =
typename math_lambdify_type<T, U>::extra_map_type;
396 template <
typename U,
typename T>
397 inline detail::math_lambdify_type<T, U>
lambdify(T &&x,
const std::vector<std::string> &names,
398 detail::math_lambdify_extra_map_type<T, U> extra_map = {})
400 return lambdified<typename std::decay<T>::type,
typename std::decay<U>::type>(std::forward<T>(x), names, extra_map);
411 template <
typename T,
typename U>
414 using Td =
typename std::decay<T>::type;
415 using Ud =
typename std::decay<U>::type;
416 template <
typename T1,
typename U1>
417 static auto test(
const T1 &x,
const U1 &) -> decltype(math::lambdify<U1>(x, {}),
void(), yes());
419 static const bool implementation_defined
420 = std::is_same<yes, decltype(test(std::declval<const Td &>(), std::declval<const Ud &>()))>
::value;
424 static const bool value = implementation_defined;
427 template <
typename T,
typename U>
decltype(math::evaluate(std::declval< const T & >(), std::declval< const symbol_fmap< U > & >())) eval_type
Evaluation type.
const std::vector< std::string > & get_names() const
Get evaluation names.
lambdified(const T &x, const std::vector< std::string > &names, extra_map_type extra_map={})
Constructor.
Detect the presence of piranha::math::lambdify().
boost::container::flat_map< std::string, T > symbol_fmap
Flat map of symbols.
static const bool value
Value of the type trait.
lambdified(lambdified &&other)
Move constructor.
std::unordered_map< std::string, std::function< U(const std::vector< U > &)> > extra_map_type
The map type for the custom evaluation of symbols.
lambdified(T &&x, const std::vector< std::string > &names, extra_map_type extra_map={})
Constructor (move overload).
math_evaluate_t< T, U > evaluate(const T &x, const symbol_fmap< U > &dict)
Evaluation.
#define piranha_throw(exception_type,...)
Exception-throwing macro.
const T & get_evaluable() const
Get evaluation object.
Functor interface for piranha::math::evaluate().
lambdified(const lambdified &other)
Copy constructor.
std::vector< std::string > get_extra_names() const
Get names of the symbols in the extra map.
detail::math_lambdify_type< T, U > lambdify(T &&x, const std::vector< std::string > &names, detail::math_lambdify_extra_map_type< T, U > extra_map={})
Create a functor interface for piranha::math::evaluate().
eval_type operator()(const std::vector< U > &values)
Evaluation.