5 #ifndef SYMENGINE_UINT_BASE_H
6 #define SYMENGINE_UINT_BASE_H
15 #ifdef HAVE_SYMENGINE_FLINT
16 #include <symengine/flint_wrapper.h>
20 #ifdef HAVE_SYMENGINE_PIRANHA
21 #include <piranha/mp_integer.hpp>
22 #include <piranha/mp_rational.hpp>
29 #if SYMENGINE_INTEGER_CLASS == SYMENGINE_GMPXX \
30 || SYMENGINE_INTEGER_CLASS == SYMENGINE_GMP
31 #ifdef HAVE_SYMENGINE_FLINT
32 inline integer_class to_mp_class(
const fz_t &i)
35 fmpz_get_mpz(x.get_mpz_t(), i.get_fmpz_t());
38 inline rational_class to_mp_class(
const fq_t &i)
41 fmpq_get_mpq(x.get_mpq_t(), i.get_fmpq_t());
46 #ifdef HAVE_SYMENGINE_PIRANHA
50 mpz_set(x.get_mpz_t(), i.get_mpz_view());
56 mpq_set(x.get_mpq_t(), i.get_mpq_view());
61 #elif SYMENGINE_INTEGER_CLASS == SYMENGINE_PIRANHA
62 #ifdef HAVE_SYMENGINE_FLINT
63 inline integer_class to_mp_class(
const fz_t &i)
66 fmpz_get_mpz(get_mpz_t(x), i.get_fmpz_t());
69 inline rational_class to_mp_class(
const fq_t &i)
72 fmpz_get_mpz(get_mpz_t(s._num()), i.get_num().get_fmpz_t());
73 fmpz_get_mpz(get_mpz_t(s._den()), i.get_den().get_fmpz_t());
78 #elif SYMENGINE_INTEGER_CLASS == SYMENGINE_FLINT
79 #ifdef HAVE_SYMENGINE_PIRANHA
82 return integer_class(x.get_mpz_view());
86 return rational_class(x.get_mpq_view());
92 inline integer_class to_mp_class(
const integer_class &i)
97 inline rational_class to_mp_class(
const rational_class &i)
103 template <
typename Key,
typename Value,
typename Wrapper>
108 typedef Key key_type;
117 dict_ = {{0, Value(i)}};
122 for (
auto &iter : p) {
123 if (iter.second != Value(0))
124 dict_[iter.first] = iter.second;
130 for (
auto &iter : p) {
131 if (iter.second != Value(0)) {
157 for (
unsigned int i = 0; i < v.
size(); i++) {
158 if (v[i] != Value(0)) {
165 Wrapper &operator=(Wrapper &&other) SYMENGINE_NOEXCEPT
169 return static_cast<Wrapper &
>(*this);
172 friend Wrapper operator+(
const Wrapper &a,
const Wrapper &b)
179 Wrapper &operator+=(
const Wrapper &other)
181 for (
auto &iter : other.dict_) {
183 if (t != dict_.
end() and t->first == iter.first) {
184 t->second += iter.second;
185 if (t->second == 0) {
189 dict_.
insert(t, {iter.first, iter.second});
192 return static_cast<Wrapper &
>(*this);
195 friend Wrapper operator-(
const Wrapper &a,
const Wrapper &b)
202 Wrapper operator-()
const
205 for (
auto &iter : c.dict_)
207 return static_cast<Wrapper &
>(c);
210 Wrapper &operator-=(
const Wrapper &other)
212 for (
auto &iter : other.dict_) {
214 if (t != dict_.
end() and t->first == iter.first) {
215 t->second -= iter.second;
216 if (t->second == 0) {
220 dict_.
insert(t, {iter.first, -iter.second});
223 return static_cast<Wrapper &
>(*this);
226 static Wrapper mul(
const Wrapper &a,
const Wrapper &b)
228 if (a.get_dict().empty())
230 if (b.get_dict().empty())
234 for (
const auto &i1 : a.dict_)
235 for (
const auto &i2 : b.dict_)
236 p.dict_[i1.first + i2.first] += i1.second * i2.second;
238 for (
auto it = p.dict_.cbegin(); it != p.dict_.cend();) {
239 if (it->second == 0) {
248 static Wrapper pow(
const Wrapper &a,
unsigned int p)
250 Wrapper tmp = a, res(1);
265 template <
typename FromPoly>
266 static Wrapper from_poly(
const FromPoly &p)
269 for (
auto it = p.begin(); it != p.end(); ++it)
270 t.dict_[it->first] = it->second;
274 friend Wrapper operator*(
const Wrapper &a,
const Wrapper &b)
276 return Wrapper::mul(a, b);
279 Wrapper &operator*=(
const Wrapper &other)
282 return static_cast<Wrapper &
>(*this);
284 if (other.dict_.empty()) {
286 return static_cast<Wrapper &
>(*this);
290 if (other.dict_.size() == 1
291 and other.dict_.find(0) != other.dict_.end()) {
292 auto t = other.dict_.begin();
293 for (
auto &i1 : dict_)
294 i1.second *= t->second;
295 return static_cast<Wrapper &
>(*this);
298 Wrapper res = Wrapper::mul(
static_cast<Wrapper &
>(*
this), other);
299 res.dict_.swap(this->dict_);
300 return static_cast<Wrapper &
>(*this);
303 friend bool operator==(
const Wrapper &a,
const Wrapper &b)
305 return a.dict_ == b.dict_;
308 bool operator!=(
const Wrapper &other)
const
310 return not(*
this == other);
325 return dict_.
empty();
332 return dict_.
rbegin()->first;
335 Value get_coeff(Key x)
const
337 auto ite = dict_.
find(x);
338 if (ite != dict_.
end())
347 return dict_.
rbegin()->second;
353 template <
typename Container,
typename Poly>
357 RCP<const Basic> var_;
361 UPolyBase(
const RCP<const Basic> &var, Container &&container)
362 : var_{var}, poly_{container}
366 typedef Container container_type;
373 virtual int size()
const = 0;
379 return eq(*var_, *(down_cast<const Poly &>(o).var_))
380 and poly_ == down_cast<const Poly &>(o).poly_;
384 inline const RCP<const Basic> &get_var()
const
389 inline const Container &get_poly()
const
399 static RCP<const Poly> from_container(
const RCP<const Basic> &var,
402 return make_rcp<const Poly>(var,
std::move(d));
406 template <
typename Cont,
typename Poly>
417 inline int get_degree()
const
419 return this->get_poly().degree();
422 static RCP<const Poly> from_dict(
const RCP<const Basic> &var,
425 return Poly::from_container(
426 var, Poly::container_from_dict(var,
std::move(d)));
429 RCP<const Basic> as_symbolic()
const
431 auto it = (down_cast<const Poly &>(*
this)).begin();
432 auto end = (down_cast<const Poly &>(*
this)).end();
435 for (; it != end; ++it) {
438 else if (it->first == 1) {
443 mul(it->second.get_basic(), this->get_var()));
444 }
else if (it->second == 1)
448 pow(this->get_var(),
integer(it->first))));
450 if (this->get_poly().empty())
457 template <
typename Container,
typename Poly,
typename Cf>
461 typedef Cf coef_type;
463 UNonExprPoly(
const RCP<const Basic> &var, Container &&container)
469 virtual Cf get_coeff(
unsigned int i)
const = 0;
471 virtual Cf eval(
const Cf &x)
const = 0;
477 for (
unsigned int i = 0; i < v.
size(); ++i)
482 inline int get_degree()
const
484 return numeric_cast<int>(this->get_poly().degree());
489 return get_coeff(get_degree());
492 static RCP<const Poly> from_dict(
const RCP<const Basic> &var,
495 return Poly::from_container(
496 var, Poly::container_from_dict(var,
std::move(d)));
500 template <
typename Container,
typename Poly>
504 UIntPolyBase(
const RCP<const Basic> &var, Container &&container)
510 RCP<const Basic> as_symbolic()
const
512 auto it = (down_cast<const Poly &>(*
this)).begin();
513 auto end = (down_cast<const Poly &>(*
this)).end();
516 for (; it != end; ++it) {
517 integer_class m = it->second;
519 if (it->first == 0) {
521 }
else if (it->first == 1) {
541 template <
typename Container,
typename Poly>
545 URatPolyBase(
const RCP<const Basic> &var, Container &&container)
551 RCP<const Basic> as_symbolic()
const
553 auto it = (down_cast<const Poly &>(*
this)).begin();
554 auto end = (down_cast<const Poly &>(*
this)).end();
557 for (; it != end; ++it) {
558 rational_class m = it->second;
560 if (it->first == 0) {
562 }
else if (it->first == 1) {
567 {{this->get_var(), one}}));
575 {{this->get_var(),
integer(it->first)}}));
583 template <
typename T,
typename Int>
596 return (lhs.ptr_ == rhs.ptr_) and (lhs.i_ == rhs.i_);
601 return not(*
this == rhs);
611 return std::make_shared<std::pair<unsigned, Int>>(
612 numeric_cast<unsigned>(i_),
613 ptr_->get_coeff_ref(numeric_cast<unsigned>(i_)));
617 template <
typename T,
typename Int>
624 if (this->ptr_->get_coeff_ref(numeric_cast<unsigned>(this->i_)) == 0
625 and this->i_ < this->ptr_->size()) {
633 while (this->i_ < this->ptr_->size()) {
634 if (this->ptr_->get_coeff_ref(numeric_cast<unsigned>(this->i_))
643 template <
typename T,
typename Int>
655 while (this->i_ >= 0) {
656 if (this->ptr_->get_coeff_ref(numeric_cast<unsigned>(this->i_))
665 template <
typename P>
667 static const bool value
671 template <
typename Poly>
672 RCP<const Poly> add_upoly(
const Poly &a,
const Poly &b)
674 if (!(a.get_var()->__eq__(*b.get_var())))
675 throw SymEngineException(
"Error: variables must agree.");
677 auto dict = a.get_poly();
678 dict += b.get_poly();
679 return Poly::from_container(a.get_var(),
std::move(dict));
682 template <
typename Poly>
683 RCP<const Poly> neg_upoly(
const Poly &a)
685 auto dict = a.get_poly();
687 return Poly::from_container(a.get_var(),
std::move(dict));
690 template <
typename Poly>
691 RCP<const Poly> sub_upoly(
const Poly &a,
const Poly &b)
693 if (!(a.get_var()->__eq__(*b.get_var())))
694 throw SymEngineException(
"Error: variables must agree.");
696 auto dict = a.get_poly();
697 dict -= b.get_poly();
698 return Poly::from_container(a.get_var(),
std::move(dict));
701 template <
typename Poly>
702 RCP<const Poly> mul_upoly(
const Poly &a,
const Poly &b)
704 if (!(a.get_var()->__eq__(*b.get_var())))
705 throw SymEngineException(
"Error: variables must agree.");
707 auto dict = a.get_poly();
708 dict *= b.get_poly();
709 return Poly::from_container(a.get_var(),
std::move(dict));
712 template <
typename Poly>
713 RCP<const Poly> quo_upoly(
const Poly &a,
const Poly &b)
715 if (!(a.get_var()->__eq__(*b.get_var())))
716 throw SymEngineException(
"Error: variables must agree.");
718 auto dict = a.get_poly();
719 dict /= b.get_poly();
720 return Poly::from_dict(a.get_var(),
std::move(dict));
Classes and functions relating to the binary operation of addition.
The base class for SymEngine.
The lowest unit of symbolic representation.
static RCP< const Basic > from_dict(const RCP< const Number > &coef, map_basic_basic &&d)
Create a Mul from a dict.
static RCP< const Number > from_mpq(const rational_class &i)
bool __eq__(const Basic &o) const override
hash_t __hash__() const override=0
int compare(const Basic &o) const override=0
vec_basic get_args() const override
Returns the list of arguments.
Main namespace for SymEngine package.
std::enable_if< std::is_integral< T >::value, RCP< const Integer > >::type integer(T i)
bool eq(const Basic &a, const Basic &b)
Checks equality for a and b
RCP< const Basic > mul(const RCP< const Basic > &a, const RCP< const Basic > &b)
Multiplication.
RCP< const Basic > add(const RCP< const Basic > &a, const RCP< const Basic > &b)
Adds two objects (safely).
RCP< const Number > rational(long n, long d)
convenience creator from two longs