piranha  0.10
trigonometric_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_TRIGONOMETRIC_SERIES_HPP
30 #define PIRANHA_TRIGONOMETRIC_SERIES_HPP
31 
32 #include <algorithm>
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 trigonometric series.
49 struct trigonometric_series_tag {
50 };
51 }
52 
54 
87 template <typename Series>
88 class trigonometric_series : public Series, detail::trigonometric_series_tag
89 {
90  PIRANHA_TT_CHECK(is_series, Series);
91  typedef Series base;
92  // Utilities to detect trigonometric terms.
93  template <typename Cf>
94  struct cf_trig_score {
95  static const int value
97  };
98  template <typename Key>
99  struct key_trig_score {
102  };
103  // Type checks for the degree/order type.
104  template <typename T>
105  using common_type_checks = conjunction<is_less_than_comparable<T>, is_returnable<T>>;
106 // Total versions.
107 #define PIRANHA_DEFINE_TRIG_PROPERTY_GETTER(property) \
108  template <typename Term, enable_if_t<cf_trig_score<typename Term::cf_type>::value == 4u \
109  && key_trig_score<typename Term::key_type>::value == 0u, \
110  int> = 0> \
111  static auto get_t_##property(const Term &t, const symbol_fset &)->decltype(math::t_##property(t.m_cf)) \
112  { \
113  return math::t_##property(t.m_cf); \
114  } \
115  template <typename Term, enable_if_t<cf_trig_score<typename Term::cf_type>::value == 0u \
116  && key_trig_score<typename Term::key_type>::value == 4u, \
117  int> = 0> \
118  static auto get_t_##property(const Term &t, const symbol_fset &s)->decltype(t.m_key.t_##property(s)) \
119  { \
120  return t.m_key.t_##property(s); \
121  } \
122  template <typename T> \
123  using t_##property##_type_ = decltype( \
124  get_t_##property(std::declval<const typename T::term_type &>(), std::declval<const symbol_fset &>())); \
125  template <typename T> \
126  using t_##property##_type \
127  = enable_if_t<common_type_checks<t_##property##_type_<T>>::value, t_##property##_type_<T>>;
128  PIRANHA_DEFINE_TRIG_PROPERTY_GETTER(degree)
129  PIRANHA_DEFINE_TRIG_PROPERTY_GETTER(ldegree)
130  PIRANHA_DEFINE_TRIG_PROPERTY_GETTER(order)
131  PIRANHA_DEFINE_TRIG_PROPERTY_GETTER(lorder)
132 #undef PIRANHA_DEFINE_TRIG_PROPERTY_GETTER
133 // Partial versions.
134 #define PIRANHA_DEFINE_PARTIAL_TRIG_PROPERTY_GETTER(property) \
135  template <typename Term, enable_if_t<cf_trig_score<typename Term::cf_type>::value == 4u \
136  && key_trig_score<typename Term::key_type>::value == 0u, \
137  int> = 0> \
138  static auto get_t_##property(const Term &t, const symbol_idx_fset &, const symbol_fset &names) \
139  ->decltype(math::t_##property(t.m_cf, names)) \
140  { \
141  return math::t_##property(t.m_cf, names); \
142  } \
143  template <typename Term, enable_if_t<cf_trig_score<typename Term::cf_type>::value == 0u \
144  && key_trig_score<typename Term::key_type>::value == 4u, \
145  int> = 0> \
146  static auto get_t_##property(const Term &t, const symbol_idx_fset &idx, const symbol_fset &names) \
147  ->decltype(t.m_key.t_##property(idx, names)) \
148  { \
149  return t.m_key.t_##property(idx, names); \
150  } \
151  template <typename T> \
152  using pt_##property##_type_ \
153  = decltype(get_t_##property(std::declval<const typename T::term_type &>(), \
154  std::declval<const symbol_idx_fset &>(), std::declval<const symbol_fset &>())); \
155  template <typename T> \
156  using pt_##property##_type \
157  = enable_if_t<common_type_checks<pt_##property##_type_<T>>::value, pt_##property##_type_<T>>;
158  PIRANHA_DEFINE_PARTIAL_TRIG_PROPERTY_GETTER(degree)
159  PIRANHA_DEFINE_PARTIAL_TRIG_PROPERTY_GETTER(ldegree)
160  PIRANHA_DEFINE_PARTIAL_TRIG_PROPERTY_GETTER(order)
161  PIRANHA_DEFINE_PARTIAL_TRIG_PROPERTY_GETTER(lorder)
162 #undef PIRANHA_DEFINE_PARTIAL_TRIG_PROPERTY_GETTER
163 public:
165  trigonometric_series() = default;
167  trigonometric_series(const trigonometric_series &) = default;
172 
179  trigonometric_series &operator=(const trigonometric_series &other) = default;
181 
189  {
190  PIRANHA_TT_CHECK(is_series, trigonometric_series);
191  }
194 
203  template <typename T = trigonometric_series>
204  t_degree_type<T> t_degree() const
205  {
206  using term_type = typename T::term_type;
207  auto it = std::max_element(
208  this->m_container.begin(), this->m_container.end(), [this](const term_type &t1, const term_type &t2) {
209  return this->get_t_degree(t1, this->m_symbol_set) < this->get_t_degree(t2, this->m_symbol_set);
210  });
211  return (it == this->m_container.end()) ? t_degree_type<T>(0) : get_t_degree(*it, this->m_symbol_set);
212  }
214 
225  template <typename T = trigonometric_series>
226  pt_degree_type<T> t_degree(const symbol_fset &names) const
227  {
228  using term_type = typename T::term_type;
229  const auto idx = ss_intersect_idx(this->m_symbol_set, names);
230  auto it = std::max_element(this->m_container.begin(), this->m_container.end(),
231  [this, &idx](const term_type &t1, const term_type &t2) {
232  return this->get_t_degree(t1, idx, this->m_symbol_set)
233  < this->get_t_degree(t2, idx, this->m_symbol_set);
234  });
235  return (it == this->m_container.end()) ? pt_degree_type<T>(0) : get_t_degree(*it, idx, this->m_symbol_set);
236  }
238 
247  template <typename T = trigonometric_series>
248  t_ldegree_type<T> t_ldegree() const
249  {
250  using term_type = typename T::term_type;
251  auto it = std::min_element(
252  this->m_container.begin(), this->m_container.end(), [this](const term_type &t1, const term_type &t2) {
253  return this->get_t_ldegree(t1, this->m_symbol_set) < this->get_t_ldegree(t2, this->m_symbol_set);
254  });
255  return (it == this->m_container.end()) ? t_ldegree_type<T>(0) : get_t_ldegree(*it, this->m_symbol_set);
256  }
258 
269  template <typename T = trigonometric_series>
270  pt_ldegree_type<T> t_ldegree(const symbol_fset &names) const
271  {
272  using term_type = typename T::term_type;
273  const auto idx = ss_intersect_idx(this->m_symbol_set, names);
274  auto it = std::min_element(this->m_container.begin(), this->m_container.end(),
275  [this, &idx](const term_type &t1, const term_type &t2) {
276  return this->get_t_ldegree(t1, idx, this->m_symbol_set)
277  < this->get_t_ldegree(t2, idx, this->m_symbol_set);
278  });
279  return (it == this->m_container.end()) ? pt_ldegree_type<T>(0) : get_t_ldegree(*it, idx, this->m_symbol_set);
280  }
282 
291  template <typename T = trigonometric_series>
292  t_order_type<T> t_order() const
293  {
294  using term_type = typename T::term_type;
295  auto it = std::max_element(
296  this->m_container.begin(), this->m_container.end(), [this](const term_type &t1, const term_type &t2) {
297  return this->get_t_order(t1, this->m_symbol_set) < this->get_t_order(t2, this->m_symbol_set);
298  });
299  return (it == this->m_container.end()) ? t_order_type<T>(0) : get_t_order(*it, this->m_symbol_set);
300  }
302 
313  template <typename T = trigonometric_series>
314  pt_order_type<T> t_order(const symbol_fset &names) const
315  {
316  using term_type = typename T::term_type;
317  const auto idx = ss_intersect_idx(this->m_symbol_set, names);
318  auto it = std::max_element(
319  this->m_container.begin(), this->m_container.end(), [this, &idx](const term_type &t1, const term_type &t2) {
320  return this->get_t_order(t1, idx, this->m_symbol_set) < this->get_t_order(t2, idx, this->m_symbol_set);
321  });
322  return (it == this->m_container.end()) ? pt_order_type<T>(0) : get_t_order(*it, idx, this->m_symbol_set);
323  }
325 
334  template <typename T = trigonometric_series>
335  t_lorder_type<T> t_lorder() const
336  {
337  using term_type = typename T::term_type;
338  auto it = std::min_element(
339  this->m_container.begin(), this->m_container.end(), [this](const term_type &t1, const term_type &t2) {
340  return this->get_t_lorder(t1, this->m_symbol_set) < this->get_t_lorder(t2, this->m_symbol_set);
341  });
342  return (it == this->m_container.end()) ? t_lorder_type<T>(0) : get_t_lorder(*it, this->m_symbol_set);
343  }
345 
356  template <typename T = trigonometric_series>
357  pt_lorder_type<T> t_lorder(const symbol_fset &names) const
358  {
359  using term_type = typename T::term_type;
360  const auto idx = ss_intersect_idx(this->m_symbol_set, names);
361  auto it = std::min_element(this->m_container.begin(), this->m_container.end(),
362  [this, &idx](const term_type &t1, const term_type &t2) {
363  return this->get_t_lorder(t1, idx, this->m_symbol_set)
364  < this->get_t_lorder(t2, idx, this->m_symbol_set);
365  });
366  return (it == this->m_container.end()) ? pt_lorder_type<T>(0) : get_t_lorder(*it, idx, this->m_symbol_set);
367  }
368 };
369 
370 namespace math
371 {
372 
374 
378 template <typename Series>
379 struct t_degree_impl<Series,
380  typename std::enable_if<std::is_base_of<detail::trigonometric_series_tag, Series>::value>::type> {
382 
393  template <typename... Args>
394  auto operator()(const Series &ts, const Args &... args) const -> decltype(ts.t_degree(args...))
395  {
396  return ts.t_degree(args...);
397  }
398 };
399 
401 
405 template <typename Series>
406 struct t_ldegree_impl<Series,
407  typename std::enable_if<std::is_base_of<detail::trigonometric_series_tag, Series>::value>::type> {
409 
420  template <typename... Args>
421  auto operator()(const Series &ts, const Args &... args) const -> decltype(ts.t_ldegree(args...))
422  {
423  return ts.t_ldegree(args...);
424  }
425 };
426 
428 
432 template <typename Series>
433 struct t_order_impl<Series,
434  typename std::enable_if<std::is_base_of<detail::trigonometric_series_tag, Series>::value>::type> {
436 
447  template <typename... Args>
448  auto operator()(const Series &ts, const Args &... args) const -> decltype(ts.t_order(args...))
449  {
450  return ts.t_order(args...);
451  }
452 };
453 
455 
459 template <typename Series>
460 struct t_lorder_impl<Series,
461  typename std::enable_if<std::is_base_of<detail::trigonometric_series_tag, Series>::value>::type> {
463 
474  template <typename... Args>
475  auto operator()(const Series &ts, const Args &... args) const -> decltype(ts.t_lorder(args...))
476  {
477  return ts.t_lorder(args...);
478  }
479 };
480 }
481 }
482 
483 #endif
Default functor for the implementation of piranha::math::t_degree().
Definition: math.hpp:1429
pt_lorder_type< T > t_lorder(const symbol_fset &names) const
Partial trigonometric low order.
Trigonometric series toolbox.
trigonometric_series()=default
Defaulted default constructor.
auto operator()(const Series &ts, const Args &... args) const -> decltype(ts.t_degree(args...))
Trigonometric degree operator.
symbol_idx_fset ss_intersect_idx(const symbol_fset &s1, const symbol_fset &s2)
Find the indices of the intersection of two symbol_fset.
Type trait to detect if a key type has a trigonometric degree property.
Definition: math.hpp:2105
STL namespace.
#define PIRANHA_FORWARDING_CTOR(Derived, Base)
Constructor-forwarding macro.
Definition: forwarding.hpp:50
t_order_type< T > t_order() const
Trigonometric order.
auto operator()(const Series &ts, const Args &... args) const -> decltype(ts.t_order(args...))
Trigonometric order operator.
pt_order_type< T > t_order(const symbol_fset &names) const
Partial trigonometric order.
auto operator()(const Series &ts, const Args &... args) const -> decltype(ts.t_lorder(args...))
Trigonometric low order operator.
Type trait to detect if type has a trigonometric low degree property.
Definition: math.hpp:1956
trigonometric_series & operator=(const trigonometric_series &other)=default
Copy assignment operator.
Default functor for the implementation of piranha::math::t_lorder().
Definition: math.hpp:1599
Forwarding macros.
Type trait to detect if type has a trigonometric order property.
Definition: math.hpp:1981
t_degree_type< T > t_degree() const
Trigonometric degree.
pt_degree_type< T > t_degree(const symbol_fset &names) const
Partial trigonometric degree.
Term class.
Definition: term.hpp:66
pt_ldegree_type< T > t_ldegree(const symbol_fset &names) const
Partial trigonometric low degree.
boost::container::flat_set< std::string > symbol_fset
Flat set of symbols.
Default functor for the implementation of piranha::math::t_ldegree().
Definition: math.hpp:1485
Detect if type can be returned from a function.
Type trait to detect if a key type has a trigonometric order property.
Definition: math.hpp:2173
Type trait to detect if a key type has a trigonometric low order property.
Definition: math.hpp:2207
Type trait to detect if type has a trigonometric degree property.
Definition: math.hpp:1931
Root piranha namespace.
Definition: array_key.hpp:52
t_lorder_type< T > t_lorder() const
Trigonometric low order.
auto operator()(const Series &ts, const Args &... args) const -> decltype(ts.t_ldegree(args...))
Trigonometric low degree operator.
Type traits.
t_ldegree_type< T > t_ldegree() const
Trigonometric low degree.
~trigonometric_series()
Trivial destructor.
Type trait to detect if type has a trigonometric low order property.
Definition: math.hpp:2006
Type trait to detect if a key type has a trigonometric low degree property.
Definition: math.hpp:2139
Default functor for the implementation of piranha::math::t_order().
Definition: math.hpp:1541
Type trait to detect series types.
Definition: series_fwd.hpp:49
#define PIRANHA_FORWARDING_ASSIGNMENT(Derived, Base)
Assignment-forwarding macro.
Definition: forwarding.hpp:68