5 #ifndef SYMENGINE_UINTPOLY_PIRANHA_H
6 #define SYMENGINE_UINTPOLY_PIRANHA_H
8 #include <symengine/polys/upolybase.h>
13 #ifdef HAVE_SYMENGINE_PIRANHA
14 #include <piranha/monomial.hpp>
15 #include <piranha/polynomial.hpp>
16 #include <piranha/mp_rational.hpp>
17 #include <piranha/mp_integer.hpp>
18 #include <piranha/math.hpp>
19 #include <piranha/type_traits.hpp>
21 #if SYMENGINE_INTEGER_CLASS != SYMENGINE_PIRANHA
29 template <
typename U,
typename V>
31 enable_if_t<
std::is_integral<U>::value
32 and (std::is_same<V, integer_class>::value
33 or std::is_same<V, rational_class>::value)>> {
34 template <
typename T2>
35 V operator()(
const V &r,
const T2 &x)
const
44 struct gcd_impl<
SymEngine::integer_class, SymEngine::integer_class> {
45 SymEngine::integer_class operator()(
const SymEngine::integer_class &r,
46 const SymEngine::integer_class &x)
const
48 SymEngine::integer_class res;
55 struct divexact_impl<
SymEngine::integer_class> {
56 void operator()(SymEngine::integer_class &r,
57 const SymEngine::integer_class &x,
58 const SymEngine::integer_class &y)
const
60 SymEngine::integer_class rem;
61 mp_tdiv_qr(r, rem, x, y);
62 if (rem != SymEngine::integer_class(0)) {
63 piranha_throw(inexact_division);
68 struct divexact_impl<
SymEngine::rational_class> {
69 void operator()(SymEngine::rational_class &r,
70 const SymEngine::rational_class &x,
71 const SymEngine::rational_class &y)
const
79 struct has_exact_ring_operations<
SymEngine::integer_class> {
80 static const bool value =
true;
83 struct has_exact_ring_operations<
SymEngine::rational_class> {
84 static const bool value =
true;
95 struct gcd_impl<
SymEngine::rational_class, SymEngine::rational_class> {
96 SymEngine::rational_class
97 operator()(
const SymEngine::rational_class &r,
98 const SymEngine::rational_class &x)
const
100 return SymEngine::rational_class(1);
108 using pmonomial = piranha::monomial<unsigned int>;
109 using pintpoly = piranha::polynomial<integer_class, pmonomial>;
110 using pratpoly = piranha::polynomial<rational_class, pmonomial>;
112 template <
typename Cf,
typename Container>
116 typedef decltype(std::declval<Container &>()._container().
begin()) ptr_type;
122 PiranhaForIter(ptr_type ptr) : ptr_{ptr} {}
124 bool operator==(
const PiranhaForIter &rhs)
126 return (ptr_ == rhs.ptr_);
131 return (ptr_ != rhs.ptr_);
134 PiranhaForIter operator++()
147 return std::make_shared<std::pair<unsigned int, const Cf &>>(
148 *(ptr_->m_key.begin()), ptr_->m_cf);
152 template <
typename Container,
template <
typename X,
typename Y>
class BaseType,
154 class UPiranhaPoly :
public BaseType<Container, Poly>
157 using Cf =
typename BaseType<Container, Poly>::coef_type;
158 using term =
typename Container::term_type;
160 UPiranhaPoly(
const RCP<const Basic> &var, Container &&dict)
161 : BaseType<Container, Poly>(var,
std::
move(dict))
165 int compare(
const Basic &o)
const
167 SYMENGINE_ASSERT(is_a<Poly>(o))
168 const Poly &s = down_cast<const Poly &>(o);
169 int cmp = this->get_var()->compare(*s.get_var());
172 if (this->get_poly() == s.get_poly())
174 return (this->get_poly().hash() < s.get_poly().hash()) ? -1 : 1;
177 static Container container_from_dict(
const RCP<const Basic> &var,
182 p.set_symbol_set(ss);
185 p.insert(term(it.second, pmonomial{it.first}));
190 static RCP<const Poly> from_vec(
const RCP<const Basic> &var,
195 p.set_symbol_set(ss);
196 for (
unsigned int i = 0; i < v.
size(); i++) {
198 p.insert(term(v[i], pmonomial{i}));
201 return make_rcp<const Poly>(var,
std::move(p));
204 template <
typename FromPoly>
205 static enable_if_t<is_a_UPoly<FromPoly>::value, RCP<const Poly>>
206 from_poly(
const FromPoly &f)
209 piranha::symbol_set ss(
211 p.set_symbol_set(ss);
212 for (
auto it = f.begin(); it != f.end(); ++it)
213 p.insert(term(it->second, pmonomial{it->first}));
214 return Poly::from_container(f.get_var(),
std::move(p));
217 Cf eval(
const Cf &x)
const
220 = {{detail::poly_print(this->get_var()), x}};
221 return piranha::math::evaluate<Cf, Container>(this->get_poly(), t);
224 Cf get_coeff(
unsigned int x)
const
226 return this->get_poly().find_cf(pmonomial{x});
229 const Cf &get_coeff_ref(
unsigned int x)
const
233 term temp = term(0, pmonomial{x});
234 auto it = this->get_poly()._container().find(temp);
235 if (it == this->get_poly()._container().
end())
242 if (this->get_poly().size() == 0)
244 return this->get_degree() + 1;
249 typedef PiranhaForIter<Cf, Container> iterator;
251 iterator
begin()
const
253 return iterator(this->get_poly()._container().
begin());
257 return iterator(this->get_poly()._container().
end());
259 r_iterator obegin()
const
261 return r_iterator(this->
template rcp_from_this_cast<Poly>(),
264 r_iterator oend()
const
266 return r_iterator(this->
template rcp_from_this_cast<Poly>(), -1);
270 class UIntPolyPiranha
271 :
public UPiranhaPoly<pintpoly, UIntPolyBase, UIntPolyPiranha>
276 UIntPolyPiranha(
const RCP<const Basic> &var, pintpoly &&dict);
278 hash_t __hash__()
const;
282 class URatPolyPiranha
283 :
public UPiranhaPoly<pratpoly, URatPolyBase, URatPolyPiranha>
288 URatPolyPiranha(
const RCP<const Basic> &var, pratpoly &&dict);
290 hash_t __hash__()
const;
293 inline RCP<const UIntPolyPiranha> gcd_upoly(
const UIntPolyPiranha &a,
294 const UIntPolyPiranha &b)
296 if (!(a.get_var()->__eq__(*b.get_var())))
297 throw SymEngineException(
"Error: variables must agree.");
299 pintpoly gcdx(std::get<0>(pintpoly::gcd(a.get_poly(), b.get_poly())));
301 if (gcdx.find_cf(pmonomial{gcdx.degree()}) < 0)
302 piranha::math::negate(gcdx);
303 return make_rcp<const UIntPolyPiranha>(a.get_var(),
std::move(gcdx));
306 inline RCP<const URatPolyPiranha> gcd_upoly(
const URatPolyPiranha &a,
307 const URatPolyPiranha &b)
309 if (!(a.get_var()->__eq__(*b.get_var())))
310 throw SymEngineException(
"Error: variables must agree.");
312 pratpoly gcdx(std::get<0>(pratpoly::gcd(a.get_poly(), b.get_poly())));
314 gcdx *= (1 / gcdx.find_cf(pmonomial{gcdx.degree()}));
315 return make_rcp<const URatPolyPiranha>(a.get_var(),
std::move(gcdx));
318 inline RCP<const UIntPolyPiranha> lcm_upoly(
const UIntPolyPiranha &a,
319 const UIntPolyPiranha &b)
321 if (!(a.get_var()->__eq__(*b.get_var())))
322 throw SymEngineException(
"Error: variables must agree.");
324 pintpoly lcmx(std::get<0>(pintpoly::gcd(a.get_poly(), b.get_poly())));
325 lcmx = (a.get_poly() * b.get_poly()) / lcmx;
326 if (lcmx.find_cf(pmonomial{lcmx.degree()}) < 0)
327 piranha::math::negate(lcmx);
328 return make_rcp<const UIntPolyPiranha>(a.get_var(),
std::move(lcmx));
331 inline RCP<const URatPolyPiranha> lcm_upoly(
const URatPolyPiranha &a,
332 const URatPolyPiranha &b)
334 if (!(a.get_var()->__eq__(*b.get_var())))
335 throw SymEngineException(
"Error: variables must agree.");
337 pratpoly lcmx(std::get<0>(pratpoly::gcd(a.get_poly(), b.get_poly())));
338 lcmx = (a.get_poly() * b.get_poly()) / lcmx;
339 lcmx *= (1 / lcmx.find_cf(pmonomial{lcmx.degree()}));
340 return make_rcp<const URatPolyPiranha>(a.get_var(),
std::move(lcmx));
343 template <
typename Container,
template <
typename X,
typename Y>
class BaseType,
345 RCP<const Poly> pow_upoly(
const UPiranhaPoly<Container, BaseType, Poly> &a,
348 return make_rcp<const Poly>(a.get_var(),
349 std::move(piranha::math::pow(a.get_poly(), p)));
352 template <
typename Container,
template <
typename X,
typename Y>
class BaseType,
354 bool divides_upoly(
const UPiranhaPoly<Container, BaseType, Poly> &a,
355 const Poly &b,
const Ptr<RCP<const Poly>> &res)
357 if (!(a.get_var()->__eq__(*b.get_var())))
358 throw SymEngineException(
"Error: variables must agree.");
362 piranha::math::divexact(z, b.get_poly(), a.get_poly());
363 *res = Poly::from_container(a.get_var(),
std::move(z));
365 }
catch (
const piranha::math::inexact_division &) {
#define IMPLEMENT_TYPEID(SYMENGINE_ID)
Inline members and functions.
The lowest unit of symbolic representation.
Main namespace for SymEngine package.
RCP< const Symbol > symbol(const std::string &name)
inline version to return Symbol