piranha  0.10
t_substitutable_series.hpp
1 /* Copyright 2009-2017 Francesco Biscani (bluescarni@gmail.com)
2 
3 This file is part of the Piranha library.
4 
5 The Piranha library is free software; you can redistribute it and/or modify
6 it under the terms of either:
7 
8  * the GNU Lesser General Public License as published by the Free
9  Software Foundation; either version 3 of the License, or (at your
10  option) any later version.
11 
12 or
13 
14  * the GNU General Public License as published by the Free Software
15  Foundation; either version 3 of the License, or (at your option) any
16  later version.
17 
18 or both in parallel, as here.
19 
20 The Piranha library is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 for more details.
24 
25 You should have received copies of the GNU General Public License and the
26 GNU Lesser General Public License along with the Piranha library. If not,
27 see https://www.gnu.org/licenses/. */
28 
29 #ifndef PIRANHA_T_SUBSTITUTABLE_SERIES_HPP
30 #define PIRANHA_T_SUBSTITUTABLE_SERIES_HPP
31 
32 #include <string>
33 #include <type_traits>
34 #include <utility>
35 
36 #include <piranha/forwarding.hpp>
37 #include <piranha/math.hpp>
38 #include <piranha/series.hpp>
39 #include <piranha/symbol_utils.hpp>
40 #include <piranha/type_traits.hpp>
41 
42 namespace piranha
43 {
44 
45 namespace detail
46 {
47 
48 // Tag for the t_subs toolbox.
49 struct t_substitutable_series_tag {
50 };
51 }
52 
54 
78 template <typename Series, typename Derived>
79 class t_substitutable_series : public Series, detail::t_substitutable_series_tag
80 {
81  typedef Series base;
82  // Detect t_subs term.
83  template <typename Term, typename T, typename U>
84  struct t_subs_term_score {
85  static const unsigned value
87  + (static_cast<unsigned>(key_has_t_subs<typename Term::key_type, T, U>::value) << 1u);
88  };
89  template <typename T, typename U, typename Term = typename Series::term_type, typename = void>
90  struct t_subs_utils {
91  static_assert(t_subs_term_score<Term, T, U>::value == 0u, "Wrong t_subs_term_score value.");
92  };
93  // Case 1: t_subs on cf only.
94  template <typename T, typename U, typename Term>
95  struct t_subs_utils<T, U, Term, enable_if_t<t_subs_term_score<Term, T, U>::value == 1u>> {
96  template <typename T1, typename U1, typename Term1>
97  using return_type_ = decltype(math::t_subs(std::declval<typename Term1::cf_type const &>(),
98  std::declval<std::string const &>(), std::declval<T1 const &>(),
99  std::declval<U1 const &>())
100  * std::declval<Derived const &>());
101  template <typename T1, typename U1, typename Term1>
102  using return_type = enable_if_t<std::is_constructible<return_type_<T1, U1, Term1>, int>::value
104  return_type_<T1, U1, Term1>>;
105  template <typename T1, typename U1, typename Term1>
106  static return_type<T1, U1, Term1> subs(const Term1 &t, const std::string &name, const symbol_idx &, const T1 &c,
107  const U1 &s, const symbol_fset &s_set)
108  {
109  Derived tmp;
110  tmp.m_symbol_set = s_set;
111  tmp.insert(Term1(typename Term1::cf_type(1), t.m_key));
112  return math::t_subs(t.m_cf, name, c, s) * tmp;
113  }
114  };
115  // Case 2: t_subs on key only.
116  template <typename T, typename U, typename Term>
117  struct t_subs_utils<T, U, Term, typename std::enable_if<t_subs_term_score<Term, T, U>::value == 2u>::type> {
118  template <typename T1, typename U1, typename Term1>
119  using return_type_ = decltype(std::declval<typename Term1::key_type const &>()
120  .t_subs(std::declval<const symbol_idx &>(), std::declval<T1 const &>(),
121  std::declval<U1 const &>(), std::declval<symbol_fset const &>())[0u]
122  .first
123  * std::declval<Derived const &>());
124  template <typename T1, typename U1, typename Term1>
125  using return_type = typename std::enable_if<std::is_constructible<return_type_<T1, U1, Term1>, int>::value
127  return_type_<T1, U1, Term1>>::type;
128  template <typename T1, typename U1, typename Term1>
129  static return_type<T1, U1, Term1> subs(const Term1 &t, const std::string &, const symbol_idx &idx, const T1 &c,
130  const U1 &s, const symbol_fset &s_set)
131  {
132  return_type<T1, U1, Term1> retval(0);
133  const auto key_subs = t.m_key.t_subs(idx, c, s, s_set);
134  for (const auto &x : key_subs) {
135  Derived tmp;
136  tmp.m_symbol_set = s_set;
137  tmp.insert(Term1(t.m_cf, x.second));
138  retval += x.first * tmp;
139  }
140  return retval;
141  }
142  };
143 // NOTE: we have no way of testing this at the moment, so better leave it out at present time.
144 #if 0
145  // Case 3: t_subs on cf and key.
146  template <typename T, typename U, typename Term>
147  struct t_subs_utils<T,U,Term,typename std::enable_if<t_subs_term_score<Term,T,U>::value == 3u>::type>
148  {
149  typedef decltype(std::declval<typename Term::key_type>().t_subs(std::declval<std::string>(),std::declval<T>(),
150  std::declval<U>(),std::declval<symbol_set>())) key_t_subs_type;
151  typedef decltype(math::t_subs(std::declval<Series>(),std::declval<std::string>(),std::declval<T>(),std::declval<U>()))
152  cf_t_subs_type;
153  typedef decltype(std::declval<typename key_t_subs_type::value_type::first_type>() * std::declval<Series>() *
154  std::declval<cf_t_subs_type>()) type;
155  };
156 #endif
157  // Final type definition.
158  template <typename T, typename U>
159  using t_subs_type
160  = decltype(t_subs_utils<T, U>::subs(std::declval<typename Series::term_type const &>(),
161  std::declval<const std::string &>(), std::declval<const symbol_idx &>(),
162  std::declval<const T &>(), std::declval<const U &>(),
163  std::declval<symbol_fset const &>()));
164 
165 public:
167  t_substitutable_series() = default;
174 
183 
191  {
193  PIRANHA_TT_CHECK(is_series, Derived);
194  PIRANHA_TT_CHECK(std::is_base_of, t_substitutable_series, Derived);
195  }
198 
218  template <typename T, typename U>
219  t_subs_type<T, U> t_subs(const std::string &name, const T &c, const U &s) const
220  {
221  t_subs_type<T, U> retval(0);
222  const auto idx = ss_index_of(this->m_symbol_set, name);
223  for (const auto &t : this->m_container) {
224  retval += t_subs_utils<T, U>::subs(t, name, idx, c, s, this->m_symbol_set);
225  }
226  return retval;
227  }
228 };
229 
230 namespace detail
231 {
232 
233 // Enabler for the t_subs_impl specialisation for t_subs_series.
234 template <typename Series, typename U, typename V>
235 using t_subs_impl_t_subs_series_enabler = typename std::enable_if<
236  std::is_base_of<t_substitutable_series_tag, Series>::value
237  && is_returnable<decltype(std::declval<const Series &>().t_subs(
238  std::declval<const std::string &>(), std::declval<const U &>(), std::declval<const V &>()))>::value>::type;
239 }
240 
241 namespace math
242 {
243 
245 
249 template <typename Series, typename U, typename V>
250 struct t_subs_impl<Series, U, V, detail::t_subs_impl_t_subs_series_enabler<Series, U, V>> {
252 
264  auto operator()(const Series &series, const std::string &name, const U &c, const V &s) const
265  -> decltype(series.t_subs(name, c, s))
266  {
267  return series.t_subs(name, c, s);
268  }
269 };
270 }
271 }
272 
273 #endif
t_substitutable_series & operator=(const t_substitutable_series &other)=default
Copy assignment operator.
Type trait to detect the presence of the piranha::math::t_subs function.
Definition: math.hpp:2280
In-place addable type trait.
STL namespace.
#define PIRANHA_FORWARDING_CTOR(Derived, Base)
Constructor-forwarding macro.
Definition: forwarding.hpp:50
detail::math_t_subs_type< T, U, V > t_subs(const T &x, const std::string &name, const U &c, const V &s)
Trigonometric substitution.
Definition: math.hpp:936
Forwarding macros.
boost::container::flat_set< std::string > symbol_fset
Flat set of symbols.
t_subs_type< T, U > t_subs(const std::string &name, const T &c, const U &s) const
Trigonometric substitution.
Toolbox for series that support trigonometric substitution.
symbol_fset::size_type symbol_idx
Symbol index.
symbol_idx ss_index_of(const symbol_fset &ref, const std::string &name)
Identify the index of a symbol in a symbol_fset.
Default functor for the implementation of piranha::math::t_subs().
Definition: math.hpp:892
Series class.
Definition: series_fwd.hpp:45
Root piranha namespace.
Definition: array_key.hpp:52
t_substitutable_series()=default
Defaulted default constructor.
Type traits.
Type trait to detect the presence of the trigonometric substitution method in keys.
Definition: math.hpp:2328
#define PIRANHA_TT_CHECK(tt,...)
Macro for static type trait checks.
Type trait to detect series types.
Definition: series_fwd.hpp:49
#define PIRANHA_FORWARDING_ASSIGNMENT(Derived, Base)
Assignment-forwarding macro.
Definition: forwarding.hpp:68
auto operator()(const Series &series, const std::string &name, const U &c, const V &s) const -> decltype(series.t_subs(name, c, s))
Call operator.