5 #ifndef SYMENGINE_UINT_BASE_H
6 #define SYMENGINE_UINT_BASE_H
14 #include <type_traits>
17 #ifdef HAVE_SYMENGINE_FLINT
18 #include <symengine/flint_wrapper.h>
22 #ifdef HAVE_SYMENGINE_PIRANHA
23 #include <piranha/mp_integer.hpp>
24 #include <piranha/mp_rational.hpp>
31 #if SYMENGINE_INTEGER_CLASS == SYMENGINE_GMPXX \
32 || SYMENGINE_INTEGER_CLASS == SYMENGINE_GMP
33 #ifdef HAVE_SYMENGINE_FLINT
34 inline integer_class to_mp_class(
const fz_t &i)
37 fmpz_get_mpz(x.get_mpz_t(), i.get_fmpz_t());
40 inline rational_class to_mp_class(
const fq_t &i)
43 fmpq_get_mpq(x.get_mpq_t(), i.get_fmpq_t());
48 #ifdef HAVE_SYMENGINE_PIRANHA
52 mpz_set(x.get_mpz_t(), i.get_mpz_view());
58 mpq_set(x.get_mpq_t(), i.get_mpq_view());
63 #elif SYMENGINE_INTEGER_CLASS == SYMENGINE_PIRANHA
64 #ifdef HAVE_SYMENGINE_FLINT
65 inline integer_class to_mp_class(
const fz_t &i)
68 fmpz_get_mpz(get_mpz_t(x), i.get_fmpz_t());
71 inline rational_class to_mp_class(
const fq_t &i)
74 fmpz_get_mpz(get_mpz_t(s._num()), i.get_num().get_fmpz_t());
75 fmpz_get_mpz(get_mpz_t(s._den()), i.get_den().get_fmpz_t());
80 #elif SYMENGINE_INTEGER_CLASS == SYMENGINE_FLINT
81 #ifdef HAVE_SYMENGINE_PIRANHA
84 return integer_class(x.get_mpz_view());
88 return rational_class(x.get_mpq_view());
94 inline integer_class to_mp_class(
const integer_class &i)
99 inline rational_class to_mp_class(
const rational_class &i)
105 template <
typename Key,
typename Value,
typename Wrapper>
109 std::map<Key, Value> dict_;
110 typedef Key key_type;
119 dict_ = {{0, Value(i)}};
124 for (
auto &iter : p) {
125 if (iter.second != Value(0))
126 dict_[iter.first] = iter.second;
132 for (
auto it = p.begin(); it != p.end();) {
133 if (it->second == Value(0))
138 dict_ = std::move(p);
152 static Wrapper from_vec(
const std::vector<Value> &v)
156 for (
unsigned int i = 0; i < v.size(); i++) {
157 if (v[i] != Value(0)) {
164 Wrapper &operator=(Wrapper &&other) SYMENGINE_NOEXCEPT
167 dict_ = std::move(other.dict_);
168 return static_cast<Wrapper &
>(*this);
171 friend Wrapper operator+(
const Wrapper &a,
const Wrapper &b)
178 Wrapper &operator+=(
const Wrapper &other)
180 for (
auto &iter : other.dict_) {
181 auto t = dict_.lower_bound(iter.first);
182 if (t != dict_.end() and t->first == iter.first) {
183 t->second += iter.second;
184 if (t->second == 0) {
188 dict_.insert(t, {iter.first, iter.second});
191 return static_cast<Wrapper &
>(*this);
194 friend Wrapper operator-(
const Wrapper &a,
const Wrapper &b)
201 Wrapper operator-()
const
204 for (
auto &iter : c.dict_)
206 return static_cast<Wrapper &
>(c);
209 Wrapper &operator-=(
const Wrapper &other)
211 for (
auto &iter : other.dict_) {
212 auto t = dict_.lower_bound(iter.first);
213 if (t != dict_.end() and t->first == iter.first) {
214 t->second -= iter.second;
215 if (t->second == 0) {
219 dict_.insert(t, {iter.first, -iter.second});
222 return static_cast<Wrapper &
>(*this);
225 static Wrapper mul(
const Wrapper &a,
const Wrapper &b)
227 if (a.get_dict().empty())
229 if (b.get_dict().empty())
233 for (
const auto &i1 : a.dict_)
234 for (
const auto &i2 : b.dict_)
235 p.dict_[i1.first + i2.first] += i1.second * i2.second;
237 for (
auto it = p.dict_.cbegin(); it != p.dict_.cend();) {
238 if (it->second == 0) {
247 static Wrapper pow(
const Wrapper &a,
unsigned int p)
249 Wrapper tmp = a, res(1);
264 template <
typename FromPoly>
265 static Wrapper from_poly(
const FromPoly &p)
268 for (
auto it = p.begin(); it != p.end(); ++it)
269 t.dict_[it->first] = it->second;
273 friend Wrapper operator*(
const Wrapper &a,
const Wrapper &b)
275 return Wrapper::mul(a, b);
278 Wrapper &operator*=(
const Wrapper &other)
281 return static_cast<Wrapper &
>(*this);
283 if (other.dict_.empty()) {
285 return static_cast<Wrapper &
>(*this);
289 if (other.dict_.size() == 1
290 and other.dict_.find(0) != other.dict_.end()) {
291 auto t = other.dict_.begin();
292 for (
auto &i1 : dict_)
293 i1.second *= t->second;
294 return static_cast<Wrapper &
>(*this);
297 Wrapper res = Wrapper::mul(
static_cast<Wrapper &
>(*
this), other);
298 res.dict_.swap(this->dict_);
299 return static_cast<Wrapper &
>(*this);
302 friend bool operator==(
const Wrapper &a,
const Wrapper &b)
304 return a.dict_ == b.dict_;
307 bool operator!=(
const Wrapper &other)
const
309 return not(
static_cast<const Wrapper &
>(*
this) == other);
312 const std::map<Key, Value> &get_dict()
const
324 return dict_.empty();
331 return dict_.rbegin()->first;
334 Value get_coeff(Key x)
const
336 auto ite = dict_.find(x);
337 if (ite != dict_.end())
346 return dict_.rbegin()->second;
351 umap_basic_num _find_gens_poly(
const RCP<const Basic> &x);
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,
423 std::map<int, Expression> &&d)
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) {
437 args.push_back(it->second.get_basic());
438 else if (it->first == 1) {
440 args.push_back(this->get_var());
443 mul(it->second.get_basic(), this->get_var()));
444 }
else if (it->second == 1)
445 args.push_back(pow(this->get_var(),
integer(it->first)));
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);
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;
473 std::vector<Cf> multieval(
const std::vector<Cf> &v)
const
476 std::vector<Cf> res(v.size());
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,
493 std::map<unsigned, Cf> &&d)
495 return Poly::from_container(
496 var, Poly::container_from_dict(var, std::move(d)));
500 template <
typename Container,
typename Poly>
504 template <
typename It>
506 template <
typename T>
507 static auto test(
int)
508 -> decltype(std::declval<T &>().operator->()->first,
509 std::declval<T &>().operator->()->second,
512 static std::false_type test(...);
513 static const bool value = decltype(test<It>(0))::value;
516 void append_symbolic_term(vec_basic &args,
unsigned int i,
517 const integer_class &m)
const
523 args.push_back(this->get_var());
530 args.push_back(pow(this->get_var(),
integer(i)));
533 {{this->get_var(),
integer(i)}}));
538 template <
typename P = Poly,
539 typename std::enable_if<
540 is_pair_iterator<typename P::iterator>::value,
int>::type
542 RCP<const Basic> as_symbolic_impl()
const
544 const auto &
self = down_cast<const P &>(*
this);
545 auto it =
self.begin();
546 auto end =
self.end();
549 for (; it != end; ++it) {
550 append_symbolic_term(args, it->first, it->second);
555 template <
typename P = Poly,
556 typename std::enable_if<
557 not is_pair_iterator<typename P::iterator>::value,
int>::type
559 RCP<const Basic> as_symbolic_impl()
const
561 const auto &
self = down_cast<const P &>(*
this);
563 auto deg =
self.get_degree();
564 for (
int i = 0; i <= deg; ++i) {
565 integer_class m =
self.get_coeff(i);
568 append_symbolic_term(args, numeric_cast<unsigned int>(i), m);
574 UIntPolyBase(
const RCP<const Basic> &var, Container &&container)
575 : UNonExprPoly<Container, Poly, integer_class>(var,
576 std::move(container))
580 RCP<const Basic> as_symbolic()
const
582 return as_symbolic_impl();
586 template <
typename Container,
typename Poly>
590 URatPolyBase(
const RCP<const Basic> &var, Container &&container)
592 std::move(container))
596 RCP<const Basic> as_symbolic()
const
598 auto it = (down_cast<const Poly &>(*
this)).begin();
599 auto end = (down_cast<const Poly &>(*
this)).end();
602 for (; it != end; ++it) {
603 rational_class m = it->second;
605 if (it->first == 0) {
607 }
else if (it->first == 1) {
609 args.push_back(this->get_var());
612 {{this->get_var(), one}}));
616 args.push_back(pow(this->get_var(),
integer(it->first)));
620 {{this->get_var(),
integer(it->first)}}));
628 template <
typename T,
typename Int>
641 return (lhs.ptr_ == rhs.ptr_) and (lhs.i_ == rhs.i_);
646 return not(*
this == rhs);
649 std::pair<long, Int> operator*()
651 return std::make_pair(i_, ptr_->get_coeff_ref(i_));
654 std::shared_ptr<std::pair<unsigned, Int>> operator->()
656 return std::make_shared<std::pair<unsigned, Int>>(
657 numeric_cast<unsigned>(i_),
658 ptr_->get_coeff_ref(numeric_cast<unsigned>(i_)));
662 template <
typename T,
typename Int>
669 if (this->ptr_->get_coeff_ref(numeric_cast<unsigned>(this->i_)) == 0
670 and this->i_ < this->ptr_->size()) {
678 while (this->i_ < this->ptr_->size()) {
679 if (this->ptr_->get_coeff_ref(numeric_cast<unsigned>(this->i_))
688 template <
typename T,
typename Int>
700 while (this->i_ >= 0) {
701 if (this->ptr_->get_coeff_ref(numeric_cast<unsigned>(this->i_))
710 template <
typename P>
712 static const bool value
713 = std::is_base_of<UPolyBase<typename P::container_type, P>, P>::value;
716 template <
typename Poly>
717 RCP<const Poly> add_upoly(
const Poly &a,
const Poly &b)
719 if (!(a.get_var()->__eq__(*b.get_var())))
720 throw SymEngineException(
"Error: variables must agree.");
722 auto dict = a.get_poly();
723 dict += b.get_poly();
724 return Poly::from_container(a.get_var(), std::move(dict));
727 template <
typename Poly>
728 RCP<const Poly> neg_upoly(
const Poly &a)
730 auto dict = a.get_poly();
732 return Poly::from_container(a.get_var(), std::move(dict));
735 template <
typename Poly>
736 RCP<const Poly> sub_upoly(
const Poly &a,
const Poly &b)
738 if (!(a.get_var()->__eq__(*b.get_var())))
739 throw SymEngineException(
"Error: variables must agree.");
741 auto dict = a.get_poly();
742 dict -= b.get_poly();
743 return Poly::from_container(a.get_var(), std::move(dict));
746 template <
typename Poly>
747 RCP<const Poly> mul_upoly(
const Poly &a,
const Poly &b)
749 if (!(a.get_var()->__eq__(*b.get_var())))
750 throw SymEngineException(
"Error: variables must agree.");
752 auto dict = a.get_poly();
753 dict *= b.get_poly();
754 return Poly::from_container(a.get_var(), std::move(dict));
757 template <
typename Poly>
758 RCP<const Poly> quo_upoly(
const Poly &a,
const Poly &b)
760 if (!(a.get_var()->__eq__(*b.get_var())))
761 throw SymEngineException(
"Error: variables must agree.");
763 auto dict = a.get_poly();
764 dict /= b.get_poly();
765 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.
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< const Integer > >::type integer(T i)
RCP< const Basic > mul(const RCP< const Basic > &a, const RCP< const Basic > &b)
Multiplication.
bool eq(const Basic &a, const Basic &b)
Checks equality for a and b
RCP< const Number > rational(long n, long d)
convenience creator from two longs