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
32inline integer_class to_mp_class(
const fz_t &i)
38inline rational_class to_mp_class(
const fq_t &i)
46#ifdef HAVE_SYMENGINE_PIRANHA
47inline integer_class to_mp_class(
const piranha::integer &i)
50 mpz_set(x.get_mpz_t(), i.get_mpz_view());
53inline rational_class to_mp_class(
const piranha::rational &i)
56 mpq_set(x.get_mpq_t(), i.get_mpq_view());
61#elif SYMENGINE_INTEGER_CLASS == SYMENGINE_PIRANHA
62#ifdef HAVE_SYMENGINE_FLINT
63inline integer_class to_mp_class(
const fz_t &i)
69inline 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
80inline integer_class to_mp_class(
const piranha::integer &x)
82 return integer_class(x.get_mpz_view());
84inline rational_class to_mp_class(
const piranha::rational &x)
86 return rational_class(x.get_mpq_view());
92inline integer_class to_mp_class(
const integer_class &i)
97inline rational_class to_mp_class(
const rational_class &i)
103template <
typename Key,
typename Value,
typename Wrapper>
108 typedef Key key_type;
117 dict_ = {{0,
Value(i)}};
122 for (
auto &
iter : p) {
130 for (
auto &
iter : p) {
157 for (
unsigned int i = 0; i < v.
size(); i++) {
158 if (v[i] !=
Value(0)) {
169 return static_cast<Wrapper &
>(*this);
183 if (t != dict_.
end()
and t->first ==
iter.first) {
184 t->second +=
iter.second;
185 if (t->second == 0) {
192 return static_cast<Wrapper &
>(*this);
205 for (
auto &
iter :
c.dict_)
214 if (t != dict_.
end()
and t->first ==
iter.first) {
215 t->second -=
iter.second;
216 if (t->second == 0) {
223 return static_cast<Wrapper &
>(*this);
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) {
265 template <
typename FromPoly>
269 for (
auto it = p.begin();
it != p.end(); ++
it)
270 t.dict_[
it->first] =
it->second;
276 return Wrapper::mul(a, b);
282 return static_cast<Wrapper &
>(*this);
284 if (
other.dict_.empty()) {
286 return static_cast<Wrapper &
>(*this);
290 if (
other.dict_.size() == 1
292 auto t =
other.dict_.begin();
293 for (
auto &
i1 : dict_)
294 i1.second *= t->second;
295 return static_cast<Wrapper &
>(*this);
299 res.dict_.swap(this->dict_);
300 return static_cast<Wrapper &
>(*this);
305 return a.dict_ == b.dict_;
325 return dict_.
empty();
332 return dict_.
rbegin()->first;
335 Value get_coeff(Key x)
const
347 return dict_.
rbegin()->second;
353template <
typename Container,
typename Poly>
357 RCP<const Basic> var_;
373 virtual int size()
const = 0;
384 inline const RCP<const Basic> &get_var()
const
406template <
typename Cont,
typename Poly>
417 inline int get_degree()
const
419 return this->get_poly().degree();
425 return Poly::from_container(
426 var, Poly::container_from_dict(var,
std::move(
d)));
429 RCP<const Basic> as_symbolic()
const
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)
447 args.push_back(
mul(
it->second.get_basic(),
448 pow(this->get_var(),
integer(
it->first))));
450 if (this->get_poly().empty())
451 args.push_back(zero);
457template <
typename Container,
typename Poly,
typename Cf>
461 typedef Cf coef_type;
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
489 return get_coeff(get_degree());
495 return Poly::from_container(
496 var, Poly::container_from_dict(var,
std::move(
d)));
500template <
typename Container,
typename Poly>
510 RCP<const Basic> as_symbolic()
const
516 for (;
it != end; ++
it) {
517 integer_class m =
it->second;
519 if (
it->first == 0) {
521 }
else if (
it->first == 1) {
523 args.push_back(this->get_var());
541template <
typename Container,
typename Poly>
551 RCP<const Basic> as_symbolic()
const
557 for (;
it != end; ++
it) {
558 rational_class m =
it->second;
560 if (
it->first == 0) {
562 }
else if (
it->first == 1) {
564 args.push_back(this->get_var());
567 {{this->get_var(), one}}));
575 {{this->get_var(),
integer(
it->first)}}));
583template <
typename T,
typename Int>
611 return std::make_shared<std::pair<unsigned, Int>>(
617template <
typename T,
typename Int>
643template <
typename T,
typename Int>
655 while (this->i_ >= 0) {
667 static const bool value
671template <
typename Poly>
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));
682template <
typename Poly>
685 auto dict = a.get_poly();
687 return Poly::from_container(a.get_var(),
std::move(dict));
690template <
typename Poly>
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));
701template <
typename Poly>
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));
712template <
typename Poly>
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.
bool eq(const Basic &a, const Basic &b)
Checks equality for a and b
void hash_combine(hash_t &seed, const T &v)
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).
std::enable_if< std::is_integral< T >::value, RCP< constInteger > >::type integer(T i)