1 #ifndef SYMENGINE_POLYNOMIALS_MULTIVARIATE
2 #define SYMENGINE_POLYNOMIALS_MULTIVARIATE
7 #include <symengine/polys/uexprpoly.h>
8 #include <symengine/symengine_casts.h>
13 template <
typename Vec,
typename Value,
typename Wrapper>
17 using Dict = std::unordered_map<Vec, Value, vec_hash<Vec>>;
19 unsigned int vec_size;
22 typedef Value coef_type;
23 typedef Dict dict_type;
36 auto iter = p.begin();
37 while (iter != p.end()) {
38 if (iter->second == 0) {
53 for (
auto &iter : p) {
54 if (iter.second != Value(0))
55 dict_[iter.first] = iter.second;
60 Wrapper &operator=(Wrapper &&other)
63 dict_ = std::move(other.dict_);
64 return static_cast<Wrapper &
>(*this);
67 friend Wrapper operator+(
const Wrapper &a,
const Wrapper &b)
69 SYMENGINE_ASSERT(a.vec_size == b.vec_size)
77 Wrapper &operator+=(
const Wrapper &other)
79 SYMENGINE_ASSERT(vec_size == other.vec_size)
81 for (
auto &iter : other.dict_) {
82 auto t = dict_.find(iter.first);
83 if (t != dict_.end()) {
84 t->second += iter.second;
88 dict_.insert(t, {iter.first, iter.second});
91 return static_cast<Wrapper &
>(*this);
94 friend Wrapper operator-(
const Wrapper &a,
const Wrapper &b)
96 SYMENGINE_ASSERT(a.vec_size == b.vec_size)
103 Wrapper operator-()
const
106 for (
auto &iter : c.dict_)
108 return static_cast<Wrapper &
>(c);
113 Wrapper &operator-=(
const Wrapper &other)
115 SYMENGINE_ASSERT(vec_size == other.vec_size)
117 for (
auto &iter : other.dict_) {
118 auto t = dict_.find(iter.first);
119 if (t != dict_.end()) {
120 t->second -= iter.second;
124 dict_.insert(t, {iter.first, -iter.second});
127 return static_cast<Wrapper &
>(*this);
130 static Wrapper mul(
const Wrapper &a,
const Wrapper &b)
132 SYMENGINE_ASSERT(a.vec_size == b.vec_size)
134 Wrapper p(a.vec_size);
135 for (
auto const &a_ : a.dict_) {
136 for (
auto const &b_ : b.dict_) {
138 Vec target(a.vec_size, 0);
139 for (
unsigned int i = 0; i < a.vec_size; i++)
140 target[i] = a_.first[i] + b_.first[i];
142 if (p.dict_.find(target) == p.dict_.end()) {
143 p.dict_.insert({target, a_.second * b_.second});
145 p.dict_.find(target)->second += a_.second * b_.second;
150 for (
auto it = p.dict_.begin(); it != p.dict_.end();) {
151 if (it->second == 0) {
160 static Wrapper pow(
const Wrapper &a,
unsigned int p)
162 Wrapper tmp = a, res(a.vec_size);
164 Vec zero_v(a.vec_size, 0);
165 res.dict_[zero_v] = 1_z;
180 friend Wrapper operator*(
const Wrapper &a,
const Wrapper &b)
182 SYMENGINE_ASSERT(a.vec_size == b.vec_size)
183 return Wrapper::mul(a, b);
186 Wrapper &operator*=(
const Wrapper &other)
188 SYMENGINE_ASSERT(vec_size == other.vec_size)
191 return static_cast<Wrapper &
>(*this);
193 if (other.dict_.empty()) {
195 return static_cast<Wrapper &
>(*this);
198 Vec zero_v(vec_size, 0);
200 if (other.dict_.size() == 1
201 and other.dict_.find(zero_v) != other.dict_.end()) {
202 auto t = other.dict_.begin();
203 for (
auto &i1 : dict_)
204 i1.second *= t->second;
205 return static_cast<Wrapper &
>(*this);
208 Wrapper res = Wrapper::mul(
static_cast<Wrapper &
>(*
this), other);
209 res.dict_.swap(this->dict_);
210 return static_cast<Wrapper &
>(*this);
213 bool operator==(
const Wrapper &other)
const
215 return dict_ == other.dict_;
218 bool operator!=(
const Wrapper &other)
const
220 return not(*
this == other);
223 const Dict &get_dict()
const
230 return dict_.empty();
233 Value get_coeff(Vec &x)
const
235 auto ite = dict_.find(x);
236 if (ite != dict_.end())
241 Wrapper translate(
const vec_uint &translator,
unsigned int size)
const
243 SYMENGINE_ASSERT(translator.size() == vec_size)
244 SYMENGINE_ASSERT(size >= vec_size)
248 for (
auto it : dict_) {
250 changed.resize(size, 0);
251 for (
unsigned int i = 0; i < vec_size; i++)
252 changed[translator[i]] = it.first[i];
253 d.insert({changed, it.second});
256 return Wrapper(std::move(d), size);
261 :
public UDictWrapper<vec_uint, integer_class, MIntDict>
275 MIntDict(umap_uvec_mpz &&p,
unsigned int sz)
302 MExprDict(umap_vec_expr &&p,
unsigned int sz)
314 template <
typename Container,
typename Poly>
322 typedef Container container_type;
323 typedef typename Container::coef_type coef_type;
326 : poly_{dict}, vars_{vars}
330 static RCP<const Poly> from_container(
const set_basic &vars, Container &&d)
332 return make_rcp<const Poly>(vars, std::move(d));
337 SYMENGINE_ASSERT(is_a<Poly>(o))
339 const Poly &s = down_cast<const Poly &>(o);
341 if (vars_.size() != s.vars_.size())
342 return vars_.size() < s.vars_.size() ? -1 : 1;
343 if (poly_.dict_.size() != s.poly_.dict_.size())
344 return poly_.dict_.size() < s.poly_.dict_.size() ? -1 : 1;
353 template <
typename FromPoly>
354 static enable_if_t<is_a_UPoly<FromPoly>::value, RCP<const Poly>>
355 from_poly(
const FromPoly &p)
358 for (
auto it = p.begin(); it != p.end(); ++it)
359 c.dict_[{it->first}] = it->second;
362 return Poly::from_container({p.get_var()}, std::move(c));
365 static RCP<const Poly> from_dict(
const vec_basic &v,
366 typename Container::dict_type &&d)
369 std::map<RCP<const Basic>,
unsigned int, RCPBasicKeyLess> m;
373 for (
unsigned int i = 0; i < v.size(); i++) {
379 vec_uint trans(s.size());
380 auto mptr = m.begin();
381 for (
unsigned int i = 0; i < s.size(); i++) {
382 trans[mptr->second] = i;
386 Container x(std::move(d), numeric_cast<unsigned>(s.size()));
387 return Poly::from_container(
388 s, std::move(x.translate(trans, numeric_cast<unsigned>(s.size()))));
391 static Container container_from_dict(
const set_basic &s,
392 typename Container::dict_type &&d)
394 return Container(std::move(d), numeric_cast<unsigned>(s.size()));
402 inline const Container &get_poly()
const
407 inline const set_basic &get_vars()
const
415 if (not is_a<Poly>(o))
417 const Poly &o_ = down_cast<const Poly &>(o);
419 if (1 == poly_.dict_.size() && 1 == o_.poly_.dict_.size()) {
420 if (poly_.dict_.begin()->second != o_.poly_.dict_.begin()->second)
422 if (poly_.dict_.begin()->first == o_.poly_.dict_.begin()->first
423 && unified_eq(vars_, o_.vars_))
425 typename Container::vec_type v1, v2;
426 v1.resize(vars_.size(), 0);
427 v2.resize(o_.vars_.size(), 0);
428 if (poly_.dict_.begin()->first == v1
429 || o_.poly_.dict_.begin()->first == v2)
432 }
else if (0 == poly_.dict_.size() && 0 == o_.poly_.dict_.size()) {
435 return (unified_eq(vars_, o_.vars_)
436 && unified_eq(poly_.dict_, o_.poly_.dict_));
445 :
MSymEnginePoly(vars, std::move(dict)){SYMENGINE_ASSIGN_TYPEID()}
449 hash_t __hash__()
const override;
450 RCP<const Basic> as_symbolic()
const;
453 std::map<RCP<const Basic>, integer_class,
RCPBasicKeyLess> &vals)
const;
460 :
MSymEnginePoly(vars, std::move(dict)){SYMENGINE_ASSIGN_TYPEID()}
464 hash_t __hash__()
const override;
465 RCP<const Basic> as_symbolic()
const;
477 unsigned int reconcile(vec_uint &v1, vec_uint &v2, set_basic &s,
478 const set_basic &s1,
const set_basic &s2);
480 template <
typename Poly,
typename Container>
481 set_basic get_translated_container(Container &x, Container &y,
const Poly &a,
487 unsigned int sz = reconcile(v1, v2, s, a.get_vars(), b.get_vars());
488 x = a.get_poly().translate(v1, sz);
489 y = b.get_poly().translate(v2, sz);
494 template <
typename Poly>
495 RCP<const Poly> add_mpoly(
const Poly &a,
const Poly &b)
497 typename Poly::container_type x, y;
498 set_basic s = get_translated_container(x, y, a, b);
500 return Poly::from_container(s, std::move(x));
503 template <
typename Poly>
504 RCP<const Poly> sub_mpoly(
const Poly &a,
const Poly &b)
506 typename Poly::container_type x, y;
507 set_basic s = get_translated_container(x, y, a, b);
509 return Poly::from_container(s, std::move(x));
512 template <
typename Poly>
513 RCP<const Poly> mul_mpoly(
const Poly &a,
const Poly &b)
515 typename Poly::container_type x, y;
516 set_basic s = get_translated_container(x, y, a, b);
518 return Poly::from_container(s, std::move(x));
521 template <
typename Poly>
522 RCP<const Poly> neg_mpoly(
const Poly &a)
524 auto x = a.get_poly();
525 return Poly::from_container(a.get_vars(), std::move(-x));
528 template <
typename Poly>
529 RCP<const Poly> pow_mpoly(
const Poly &a,
unsigned int n)
531 auto x = a.get_poly();
532 return Poly::from_container(a.get_vars(), Poly::container_type::pow(x, n));
#define IMPLEMENT_TYPEID(SYMENGINE_ID)
Inline members and functions.
The lowest unit of symbolic representation.
vec_basic get_args() const override
Returns the list of arguments.
bool __eq__(const Basic &o) const override
Test equality.
int compare(const Basic &o) const override
Main namespace for SymEngine package.
int unified_compare(const T &a, const T &b)