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>
19 unsigned int vec_size;
22 typedef Value coef_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)
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});
312 template <
typename Container,
typename Poly>
320 typedef Container container_type;
321 typedef typename Container::coef_type coef_type;
324 : poly_{dict}, vars_{vars}
328 static RCP<const Poly> from_container(
const set_basic &vars, Container &&d)
330 return make_rcp<const Poly>(vars,
std::move(d));
335 SYMENGINE_ASSERT(is_a<Poly>(o))
337 const Poly &s = down_cast<const Poly &>(o);
339 if (vars_.
size() != s.vars_.size())
340 return vars_.
size() < s.vars_.size() ? -1 : 1;
341 if (poly_.dict_.size() != s.poly_.dict_.size())
342 return poly_.dict_.size() < s.poly_.dict_.size() ? -1 : 1;
351 template <
typename FromPoly>
352 static enable_if_t<is_a_UPoly<FromPoly>::value, RCP<const Poly>>
353 from_poly(
const FromPoly &p)
356 for (
auto it = p.begin(); it != p.end(); ++it)
357 c.dict_[{it->first}] = it->second;
360 return Poly::from_container({p.get_var()},
std::move(c));
363 static RCP<const Poly> from_dict(
const vec_basic &v,
364 typename Container::dict_type &&d)
371 for (
unsigned int i = 0; i < v.size(); i++) {
377 vec_uint trans(s.size());
378 auto mptr = m.
begin();
379 for (
unsigned int i = 0; i < s.size(); i++) {
380 trans[mptr->second] = i;
384 Container x(
std::move(d), numeric_cast<unsigned>(s.size()));
385 return Poly::from_container(
386 s,
std::move(x.translate(trans, numeric_cast<unsigned>(s.size()))));
389 static Container container_from_dict(
const set_basic &s,
390 typename Container::dict_type &&d)
392 return Container(
std::move(d), numeric_cast<unsigned>(s.size()));
400 inline const Container &get_poly()
const
405 inline const set_basic &get_vars()
const
413 if (not is_a<Poly>(o))
415 const Poly &o_ = down_cast<const Poly &>(o);
417 if (1 == poly_.dict_.size() && 1 == o_.poly_.dict_.size()) {
418 if (poly_.dict_.begin()->second != o_.poly_.dict_.begin()->second)
420 if (poly_.dict_.begin()->first == o_.poly_.dict_.begin()->first
421 && unified_eq(vars_, o_.vars_))
423 typename Container::vec_type v1, v2;
424 v1.resize(vars_.
size(), 0);
425 v2.resize(o_.vars_.size(), 0);
426 if (poly_.dict_.begin()->first == v1
427 || o_.poly_.dict_.begin()->first == v2)
430 }
else if (0 == poly_.dict_.size() && 0 == o_.poly_.dict_.size()) {
433 return (unified_eq(vars_, o_.vars_)
434 && unified_eq(poly_.dict_, o_.poly_.dict_));
448 RCP<const Basic> as_symbolic()
const;
463 RCP<const Basic> as_symbolic()
const;
477 template <
typename Poly,
typename Container>
478 set_basic get_translated_container(Container &x, Container &y,
const Poly &a,
484 unsigned int sz = reconcile(v1, v2, s, a.get_vars(), b.get_vars());
485 x = a.get_poly().translate(v1, sz);
486 y = b.get_poly().translate(v2, sz);
491 template <
typename Poly>
492 RCP<const Poly> add_mpoly(
const Poly &a,
const Poly &b)
494 typename Poly::container_type x, y;
495 set_basic s = get_translated_container(x, y, a, b);
497 return Poly::from_container(s,
std::move(x));
500 template <
typename Poly>
501 RCP<const Poly> sub_mpoly(
const Poly &a,
const Poly &b)
503 typename Poly::container_type x, y;
504 set_basic s = get_translated_container(x, y, a, b);
506 return Poly::from_container(s,
std::move(x));
509 template <
typename Poly>
510 RCP<const Poly> mul_mpoly(
const Poly &a,
const Poly &b)
512 typename Poly::container_type x, y;
513 set_basic s = get_translated_container(x, y, a, b);
515 return Poly::from_container(s,
std::move(x));
518 template <
typename Poly>
519 RCP<const Poly> neg_mpoly(
const Poly &a)
521 auto x = a.get_poly();
522 return Poly::from_container(a.get_vars(),
std::move(-x));
525 template <
typename Poly>
526 RCP<const Poly> pow_mpoly(
const Poly &a,
unsigned int n)
528 auto x = a.get_poly();
529 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.
hash_t __hash__() const override
hash_t __hash__() const override
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)