usymenginepoly.h
1 #ifndef SYMENGINE_USYMENGINEPOLY_H
2 #define SYMENGINE_USYMENGINEPOLY_H
3 
4 #include <symengine/polys/upolybase.h>
5 
6 namespace SymEngine
7 {
8 
9 namespace detail
10 {
11 template <typename T>
12 inline void mp_pow_ui_dispatch(T &res, const T &base, unsigned long exp)
13 {
14  mp_pow_ui(res, base, exp);
15 }
16 } // namespace detail
17 
18 template <typename Container, template <typename X, typename Y> class BaseType,
19  typename Poly>
20 class USymEnginePoly : public BaseType<Container, Poly>
21 {
22 public:
23  using Cf = typename BaseType<Container, Poly>::coef_type;
24  using Key = typename Container::key_type;
25 
26  USymEnginePoly(const RCP<const Basic> &var, Container &&dict)
27  : BaseType<Container, Poly>(var, std::move(dict))
28  {
29  }
30 
31  int compare(const Basic &o) const
32  {
33  SYMENGINE_ASSERT(is_a<Poly>(o))
34  const Poly &s = down_cast<const Poly &>(o);
35 
36  if (this->get_poly().size() != s.get_poly().size())
37  return (this->get_poly().size() < s.get_poly().size()) ? -1 : 1;
38 
39  int cmp = unified_compare(this->get_var(), s.get_var());
40  if (cmp != 0)
41  return cmp;
42 
43  return unified_compare(this->get_poly().dict_, s.get_poly().dict_);
44  }
45 
46  bool is_canonical(const Container &dict) const
47  {
48  // Check if dictionary contains terms with coeffienct 0
49  for (auto iter : dict.dict_)
50  if (iter.second == 0)
51  return false;
52  return true;
53  }
54 
55  static RCP<const Poly> from_vec(const RCP<const Basic> &var,
56  const std::vector<Cf> &v)
57  {
58  return make_rcp<const Poly>(var, Container::from_vec(v));
59  }
60 
61  static Container container_from_dict(const RCP<const Basic> &var,
62  std::map<Key, Cf> &&d)
63  {
64  return Container(d);
65  }
66 
67  template <typename FromPoly>
68  static enable_if_t<is_a_UPoly<FromPoly>::value, RCP<const Poly>>
69  from_poly(const FromPoly &p)
70  {
71  return Poly::from_container(p.get_var(),
72  std::move(Container::from_poly(p)));
73  }
74 
75  Cf eval(const Cf &x) const
76  {
77  Key last_deg = this->get_poly().dict_.rbegin()->first;
78  Cf result(0), x_pow;
79 
80  for (auto it = this->get_poly().dict_.rbegin();
81  it != this->get_poly().dict_.rend(); ++it) {
82  detail::mp_pow_ui_dispatch(x_pow, x, last_deg - (*it).first);
83  last_deg = (*it).first;
84  result = (*it).second + x_pow * result;
85  }
86  detail::mp_pow_ui_dispatch(x_pow, x, last_deg);
87  result *= x_pow;
88 
89  return result;
90  }
91 
92  inline const std::map<Key, Cf> &get_dict() const
93  {
94  return this->get_poly().dict_;
95  }
96 
97  inline Cf get_coeff(Key x) const
98  {
99  return this->get_poly().get_coeff(x);
100  }
101 
102  typedef typename std::map<Key, Cf>::const_iterator iterator;
103  typedef typename std::map<Key, Cf>::const_reverse_iterator r_iterator;
104  iterator begin() const
105  {
106  return this->get_poly().dict_.begin();
107  }
108  iterator end() const
109  {
110  return this->get_poly().dict_.end();
111  }
112  r_iterator obegin() const
113  {
114  return this->get_poly().dict_.rbegin();
115  }
116  r_iterator oend() const
117  {
118  return this->get_poly().dict_.rend();
119  }
120 
121  int size() const
122  {
123  if (this->get_poly().dict_.empty())
124  return 0;
125  return this->get_degree() + 1;
126  }
127 };
128 
129 template <typename Container, template <typename X, typename Y> class BaseType,
130  typename Poly>
131 RCP<const Poly> pow_upoly(const USymEnginePoly<Container, BaseType, Poly> &a,
132  unsigned int p)
133 {
134  auto dict = Poly::container_type::pow(a.get_poly(), p);
135  return Poly::from_container(a.get_var(), std::move(dict));
136 }
137 } // namespace SymEngine
138 
139 #endif
The lowest unit of symbolic representation.
Definition: basic.h:97
Main namespace for SymEngine package.
Definition: add.cpp:19
RCP< const Basic > exp(const RCP< const Basic > &x)
Returns the natural exponential function E**x = pow(E, x)
Definition: pow.cpp:271
int unified_compare(const T &a, const T &b)
Definition: dict.h:205