uintpoly_flint.h
Go to the documentation of this file.
1 
5 #ifndef SYMENGINE_UINTPOLY_FLINT_H
6 #define SYMENGINE_UINTPOLY_FLINT_H
7 
8 #include <symengine/polys/upolybase.h>
9 
10 #ifdef HAVE_SYMENGINE_FLINT
11 #include <symengine/flint_wrapper.h>
12 using fzp_t = SymEngine::fmpz_poly_wrapper;
13 using fqp_t = SymEngine::fmpq_poly_wrapper;
14 
15 namespace SymEngine
16 {
17 
18 template <typename Container, template <typename X, typename Y> class BaseType,
19  typename Poly>
20 class UFlintPoly : public BaseType<Container, Poly>
21 {
22 public:
23  using Cf = typename BaseType<Container, Poly>::coef_type;
24 
25  UFlintPoly(const RCP<const Basic> &var, Container &&dict)
26  : BaseType<Container, Poly>(var, std::move(dict))
27  {
28  }
29 
30  int compare(const Basic &o) const
31  {
32  SYMENGINE_ASSERT(is_a<Poly>(o))
33  const Poly &s = down_cast<const Poly &>(o);
34 
35  if (this->get_poly().degree() != s.get_poly().degree())
36  return (this->get_poly().degree() < s.get_poly().degree()) ? -1 : 1;
37 
38  int cmp = this->get_var()->compare(*s.get_var());
39  if (cmp != 0)
40  return cmp;
41 
42  for (unsigned int i = 0; i < this->get_poly().length(); ++i) {
43  if (this->get_poly().get_coeff(i) != s.get_poly().get_coeff(i))
44  return (this->get_poly().get_coeff(i)
45  < s.get_poly().get_coeff(i))
46  ? -1
47  : 1;
48  }
49  return 0;
50  }
51 
52  static Container container_from_dict(const RCP<const Basic> &var,
54  {
55  Container f;
56  for (auto const &p : d) {
57  if (p.second != 0) {
58  typename Container::internal_coef_type r(get_mp_t(p.second));
59  f.set_coeff(p.first, r);
60  }
61  }
62  return f;
63  }
64 
65  static RCP<const Poly> from_vec(const RCP<const Basic> &var,
66  const std::vector<Cf> &v)
67  {
68  // TODO improve this (we already know the degree)
69  Container f;
70  for (unsigned int i = 0; i < v.size(); i++) {
71  if (v[i] != 0) {
72  typename Container::internal_coef_type r(get_mp_t(v[i]));
73  f.set_coeff(i, r);
74  }
75  }
76  return make_rcp<const Poly>(var, std::move(f));
77  }
78 
79  template <typename FromPoly>
80  static enable_if_t<is_a_UPoly<FromPoly>::value, RCP<const Poly>>
81  from_poly(const FromPoly &p)
82  {
83  Container f;
84  for (auto it = p.begin(); it != p.end(); ++it) {
85  typename Container::internal_coef_type r(get_mp_t(it->second));
86  f.set_coeff(it->first, r);
87  }
88  return Poly::from_container(p.get_var(), std::move(f));
89  }
90 
91  Cf eval(const Cf &x) const
92  {
93  typename Container::internal_coef_type r(get_mp_t(x));
94  return to_mp_class(this->get_poly().eval(r));
95  }
96 
97  Cf get_coeff(unsigned int x) const
98  {
99  return to_mp_class(this->get_poly().get_coeff(x));
100  }
101 
102  // can't return by reference
103  Cf get_coeff_ref(unsigned int x) const
104  {
105  return to_mp_class(this->get_poly().get_coeff(x));
106  }
107 
108  typedef ContainerForIter<Poly, Cf> iterator;
109  typedef ContainerRevIter<Poly, Cf> r_iterator;
110  iterator begin() const
111  {
112  return iterator(this->template rcp_from_this_cast<Poly>(), 0);
113  }
114  iterator end() const
115  {
116  return iterator(this->template rcp_from_this_cast<Poly>(), size());
117  }
118  r_iterator obegin() const
119  {
120  return r_iterator(this->template rcp_from_this_cast<Poly>(),
121  (long)size() - 1);
122  }
123  r_iterator oend() const
124  {
125  return r_iterator(this->template rcp_from_this_cast<Poly>(), -1);
126  }
127 
128  int size() const
129  {
130  return numeric_cast<int>(this->get_poly().length());
131  }
132 };
133 
134 class UIntPolyFlint : public UFlintPoly<fzp_t, UIntPolyBase, UIntPolyFlint>
135 {
136 public:
137  IMPLEMENT_TYPEID(SYMENGINE_UINTPOLYFLINT)
139  UIntPolyFlint(const RCP<const Basic> &var, fzp_t &&dict);
141  hash_t __hash__() const override;
142 
143 }; // UIntPolyFlint
144 
145 class URatPolyFlint : public UFlintPoly<fqp_t, URatPolyBase, URatPolyFlint>
146 {
147 public:
148  IMPLEMENT_TYPEID(SYMENGINE_URATPOLYFLINT)
150  URatPolyFlint(const RCP<const Basic> &var, fqp_t &&dict);
152  hash_t __hash__() const override;
153 }; // URatPolyFlint
154 
155 template <typename Container, template <typename X, typename Y> class BaseType,
156  typename Poly>
158 factors(const UFlintPoly<Container, BaseType, Poly> &a)
159 {
160  auto fac_wrapper = a.get_poly().factors();
161  auto &fac = fac_wrapper.get_fmpz_poly_factor_t();
163  if (fac->c != 1_z)
165  make_rcp<const Poly>(a.get_var(), numeric_cast<int>(fac->c)), 1));
166  SYMENGINE_ASSERT(fac->p != NULL and fac->exp != NULL)
167  for (long i = 0; i < fac->num; i++) {
168  fzp_t z;
169  z.swap_fmpz_poly_t(fac->p[i]);
171  make_rcp<const Poly>(a.get_var(), std::move(z)), fac->exp[i]));
172  }
173  return S;
174 }
175 
176 template <typename Container, template <typename X, typename Y> class BaseType,
177  typename Poly>
178 RCP<const Poly> gcd_upoly(const UFlintPoly<Container, BaseType, Poly> &a,
179  const Poly &b)
180 {
181  if (!(a.get_var()->__eq__(*b.get_var())))
182  throw SymEngineException("Error: variables must agree.");
183  return make_rcp<const Poly>(a.get_var(), a.get_poly().gcd(b.get_poly()));
184 }
185 
186 template <typename Container, template <typename X, typename Y> class BaseType,
187  typename Poly>
188 RCP<const Poly> lcm_upoly(const UFlintPoly<Container, BaseType, Poly> &a,
189  const Poly &b)
190 {
191  if (!(a.get_var()->__eq__(*b.get_var())))
192  throw SymEngineException("Error: variables must agree.");
193  return make_rcp<const Poly>(a.get_var(), a.get_poly().lcm(b.get_poly()));
194 }
195 
196 template <typename Container, template <typename X, typename Y> class BaseType,
197  typename Poly>
198 RCP<const Poly> pow_upoly(const UFlintPoly<Container, BaseType, Poly> &a,
199  unsigned int p)
200 {
201  return make_rcp<const Poly>(a.get_var(), a.get_poly().pow(p));
202 }
203 
204 template <typename Container, template <typename X, typename Y> class BaseType,
205  typename Poly>
206 bool divides_upoly(const UFlintPoly<Container, BaseType, Poly> &a,
207  const Poly &b, const Ptr<RCP<const Poly>> &res)
208 {
209  if (!(a.get_var()->__eq__(*b.get_var())))
210  throw SymEngineException("Error: variables must agree.");
211 
212  typename Poly::container_type q, r;
213 
214  b.get_poly().divrem(q, r, a.get_poly());
215  if (r == 0) {
216  *res = make_rcp<Poly>(a.get_var(), std::move(q));
217  return true;
218  } else {
219  return false;
220  }
221 }
222 } // namespace SymEngine
223 
224 #endif // HAVE_SYMENGINE_FLINT
225 
226 #endif // SYMENGINE_UINTPOLY_FLINT_H
#define IMPLEMENT_TYPEID(SYMENGINE_ID)
Inline members and functions.
Definition: basic.h:340
T begin(T... args)
T end(T... args)
T make_pair(T... args)
T move(T... args)
Main namespace for SymEngine package.
Definition: add.cpp:19
STL namespace.
T push_back(T... args)
T size(T... args)