1 #ifndef SYMENGINE_BASIC_CONVERSIONS_H
2 #define SYMENGINE_BASIC_CONVERSIONS_H
13 RCP<const P> from_basic(
const RCP<const Basic> &basic,
14 const RCP<const Basic> &gen,
bool ex =
false);
21 enable_if_t<is_a_UPoly<P>::value, RCP<const P>>
22 from_basic(
const RCP<const Basic> &basic,
bool ex =
false);
24 template <
typename T,
typename P>
25 enable_if_t<std::is_same<T, UExprDict>::value, T>
26 _basic_to_upoly(
const RCP<const Basic> &basic,
const RCP<const Basic> &gen);
28 template <
typename T,
typename P>
29 enable_if_t<std::is_base_of<UIntPolyBase<T, P>, P>::value, T>
30 _basic_to_upoly(
const RCP<const Basic> &basic,
const RCP<const Basic> &gen);
32 template <
typename T,
typename P>
33 enable_if_t<std::is_base_of<URatPolyBase<T, P>, P>::value, T>
34 _basic_to_upoly(
const RCP<const Basic> &basic,
const RCP<const Basic> &gen);
36 template <
typename P,
typename V>
41 using D =
typename P::container_type;
49 D apply(
const Basic &b)
52 return std::move(dict);
55 void dict_set(
unsigned int pow,
const Basic &x)
57 down_cast<V *>(
this)->dict_set(pow, x);
60 void bvisit(
const Pow &x)
62 if (is_a<const Integer>(*x.
get_exp())) {
63 int i = numeric_cast<int>(
64 down_cast<const Integer &>(*x.
get_exp()).as_int());
67 = pow_upoly(*P::from_container(gen, _basic_to_upoly<D, P>(
75 RCP<const Basic> genbase = gen, genpow = one, coef = one, tmp;
76 if (is_a<const Pow>(*gen)) {
77 genbase = down_cast<const Pow &>(*gen).get_base();
78 genpow = down_cast<const Pow &>(*gen).get_exp();
85 if (is_a<const Add>(*x.
get_exp())) {
86 RCP<const Add> addx = rcp_static_cast<const Add>(x.
get_exp());
87 for (
auto const &it : addx->get_dict())
88 expos.insert(
mul(it.first, it.second));
89 if (not addx->get_coef()->is_zero())
90 expos.insert(addx->get_coef());
96 for (
auto const &it : expos) {
97 tmp =
div(it, genpow);
98 if (is_a<const Integer>(*tmp)) {
99 RCP<const Integer> i = rcp_static_cast<const Integer>(tmp);
100 if (i->is_positive()) {
101 powr =
static_cast<int>(i->as_int());
105 coef =
mul(coef, pow(genbase, it));
107 dict_set(powr, *coef);
109 this->bvisit((
const Basic &)x);
113 void bvisit(
const Add &x)
116 for (
auto const &it : x.get_dict())
117 res += apply(*it.first) * apply(*it.second);
118 dict = std::move(res);
121 void bvisit(
const Mul &x)
123 D res = apply(*x.get_coef());
124 for (
auto const &it : x.get_dict())
125 res *= apply(*pow(it.first, it.second));
126 dict = std::move(res);
132 dict = P::container_from_dict(gen, {{0,
typename P::coef_type(i)}});
137 typename = enable_if_t<
138 ((std::is_base_of<UIntPolyBase<typename P::container_type, P>,
145 and (std::is_base_of<
151 or (std::is_same<P, UExprPoly>::value
155 and not std::is_same<Poly, GaloisField>::value>>
156 void bvisit(
const Poly &x)
158 dict = (P::from_poly(x))->get_poly();
161 void bvisit(
const Basic &x)
163 RCP<const Basic> genpow = one, genbase = gen, powr;
164 if (is_a<const Pow>(*gen)) {
165 genpow = down_cast<const Pow &>(*gen).get_exp();
166 genbase = down_cast<const Pow &>(*gen).get_base();
168 if (
eq(*genbase, x)) {
169 powr =
div(one, genpow);
170 if (is_a<const Integer>(*powr)) {
171 int i = numeric_cast<int>(
172 down_cast<const Integer &>(*powr).as_int());
174 dict = P::container_from_dict(
175 gen, {{i,
typename P::coef_type(1)}});
180 if (is_a<const Symbol>(*gen)) {
181 if (has_symbol(x, *gen)) {
182 throw SymEngineException(
"Not a Polynomial");
189 template <
typename Poly>
203 throw SymEngineException(
"Non-integer found");
206 void dict_set(
unsigned int pow,
const Basic &x)
208 if (is_a<const Integer>(x))
209 this->dict = Poly::container_from_dict(
211 {{pow, down_cast<const Integer &>(x).as_integer_class()}});
213 throw SymEngineException(
"Non-integer found");
231 void dict_set(
unsigned int pow,
const Basic &x)
237 template <
typename Poly>
254 void dict_set(
unsigned int pow,
const Basic &x)
256 if (is_a<const Integer>(x))
257 this->dict = Poly::container_from_dict(
258 this->gen, {{pow, rational_class(
static_cast<const Integer &
>(x)
259 .as_integer_class())}});
260 else if (is_a<const Rational>(x))
261 this->dict = Poly::container_from_dict(
263 {{pow,
static_cast<const Rational &
>(x).as_rational_class()}});
265 throw SymEngineException(
"Non-rational found");
269 template <
typename T,
typename P>
270 enable_if_t<std::is_same<T, UExprDict>::value, T>
271 _basic_to_upoly(
const RCP<const Basic> &basic,
const RCP<const Basic> &gen)
274 return v.apply(*basic);
277 template <
typename T,
typename P>
278 enable_if_t<std::is_base_of<UIntPolyBase<T, P>, P>::value, T>
279 _basic_to_upoly(
const RCP<const Basic> &basic,
const RCP<const Basic> &gen)
281 BasicToUIntPoly<P> v(gen);
282 return v.apply(*basic);
285 template <
typename T,
typename P>
286 enable_if_t<std::is_base_of<URatPolyBase<T, P>, P>::value, T>
287 _basic_to_upoly(
const RCP<const Basic> &basic,
const RCP<const Basic> &gen)
289 BasicToURatPoly<P> v(gen);
290 return v.apply(*basic);
293 template <
typename P>
294 RCP<const P> from_basic(
const RCP<const Basic> &basic,
295 const RCP<const Basic> &gen,
bool ex)
297 RCP<const Basic>
exp = basic;
300 return P::from_container(
301 gen, _basic_to_upoly<typename P::container_type, P>(
exp, gen));
304 template <
typename P>
305 enable_if_t<is_a_UPoly<P>::value, RCP<const P>>
306 from_basic(
const RCP<const Basic> &basic,
bool ex)
308 RCP<const Basic>
exp = basic;
312 umap_basic_num tmp = _find_gens_poly(
exp);
315 throw SymEngineException(
"Did not find exactly 1 generator");
317 RCP<const Basic> gen = pow(tmp.begin()->first, tmp.begin()->second);
318 return P::from_container(
319 gen, _basic_to_upoly<typename P::container_type, P>(
exp, gen));
322 template <
typename P>
323 enable_if_t<std::is_same<MIntPoly, P>::value,
typename P::container_type>
324 _basic_to_mpoly(
const RCP<const Basic> &basic,
const set_basic &gens);
326 template <
typename P,
typename V>
330 using Dict =
typename P::container_type;
331 using Vec =
typename Dict::vec_type;
336 umap_basic_uint gens_map;
341 dict.vec_size =
static_cast<int>(gens.size());
343 RCP<const Basic> genpow, genbase;
346 for (
auto it : gens) {
349 if (is_a<const Pow>(*it)) {
350 genpow = down_cast<const Pow &>(*it).get_exp();
351 genbase = down_cast<const Pow &>(*it).get_base();
353 auto ite = gens_pow.find(genbase);
354 if (ite == gens_pow.end())
355 gens_pow[genbase] = {genpow};
357 gens_pow[genbase].push_back(genpow);
362 Dict apply(
const Basic &b)
365 return std::move(dict);
368 void dict_set(Vec pow,
const Basic &x)
370 down_cast<V *>(
this)->dict_set(pow, x);
373 void bvisit(
const Pow &x)
375 if (is_a<const Integer>(*x.
get_exp())) {
376 int i = numeric_cast<int>(
377 down_cast<const Integer &>(*x.
get_exp()).as_int());
379 dict = Dict::pow(_basic_to_mpoly<P>(x.
get_base(), gens), i);
384 Vec zero_v(gens.size(), 0);
385 RCP<const Basic> coef = one, tmp;
386 RCP<const Integer> i;
388 auto ite = gens_pow.find(x.
get_base());
390 if (ite != gens_pow.end()) {
394 if (is_a<const Add>(*x.
get_exp())) {
395 RCP<const Add> addx = rcp_static_cast<const Add>(x.
get_exp());
396 for (
auto const &it : addx->get_dict())
397 expos.insert(
mul(it.first, it.second));
398 if (not addx->get_coef()->is_zero())
399 expos.insert(addx->get_coef());
404 for (
auto const &it : expos) {
408 for (
auto powr : ite->second) {
410 if (is_a<const Integer>(*tmp)) {
411 i = rcp_static_cast<const Integer>(tmp);
412 if (i->is_positive()) {
413 zero_v[gens_map[pow(ite->first, powr)]]
414 =
static_cast<int>(i->as_int());
422 coef =
mul(coef, pow(ite->first, it));
424 dict_set(zero_v, *coef);
431 void bvisit(
const Add &x)
434 for (
auto const &it : x.get_dict())
435 res += apply(*it.first) * apply(*it.second);
436 dict = std::move(res);
439 void bvisit(
const Mul &x)
441 Dict res = apply(*x.get_coef());
442 for (
auto const &it : x.get_dict())
443 res *= apply(*pow(it.first, it.second));
444 dict = std::move(res);
450 Vec zero_v(gens.size(), 0);
451 dict = P::container_from_dict(gens, {{zero_v, i}});
454 void bvisit(
const Basic &x)
456 RCP<const Basic> powr;
457 Vec zero_v(gens.size(), 0);
460 if (it != gens_pow.end()) {
462 for (
auto pows : it->second) {
463 powr =
div(one, pows);
464 if (is_a<const Integer>(*powr)) {
465 int i = numeric_cast<int>(
466 down_cast<const Integer &>(*powr).as_int());
469 zero_v[gens_map[pow(it->first, pows)]] = i;
470 dict = P::container_from_dict(
471 gens, {{zero_v,
typename P::coef_type(1)}});
493 throw SymEngineException(
"Non-integer found");
496 void dict_set(vec_uint pow,
const Basic &x)
498 if (is_a<const Integer>(x))
499 dict = MIntPoly::container_from_dict(
501 {{pow, down_cast<const Integer &>(x).as_integer_class()}});
503 throw SymEngineException(
"Non-integer found");
518 Vec v(gens.size(), 0);
519 dict = MExprPoly::container_from_dict(gens, {{v, x.
rcp_from_this()}});
522 void dict_set(vec_int pow,
const Basic &x)
524 dict = MExprPoly::container_from_dict(gens, {{pow, x.
rcp_from_this()}});
528 template <
typename P>
529 enable_if_t<std::is_same<MIntPoly, P>::value,
typename P::container_type>
530 _basic_to_mpoly(
const RCP<const Basic> &basic,
const set_basic &gens)
533 return v.apply(*basic);
536 template <
typename P>
537 enable_if_t<std::is_same<MExprPoly, P>::value,
typename P::container_type>
538 _basic_to_mpoly(
const RCP<const Basic> &basic,
const set_basic &gens)
540 BasicToMExprPoly v(gens);
541 return v.apply(*basic);
544 template <
typename P>
545 RCP<const P> from_basic(
const RCP<const Basic> &basic, set_basic &gens,
548 RCP<const Basic>
exp = basic;
553 return P::from_container(gens, _basic_to_mpoly<P>(
exp, gens));
556 template <
typename P>
558 std::is_base_of<MSymEnginePoly<typename P::container_type, P>, P>::value,
560 from_basic(
const RCP<const Basic> &basic,
bool ex =
false)
562 RCP<const Basic>
exp = basic;
566 umap_basic_num tmp = _find_gens_poly(
exp);
569 gens.insert(pow(it.first, it.second));
571 return P::from_container(gens, _basic_to_mpoly<P>(
exp, gens));
The base class for representing addition in symbolic expressions.
const RCP< const Number > & get_coef() const
The lowest unit of symbolic representation.
RCP< T > rcp_from_this()
Get RCP<T> pointer to self (it will cast the pointer to T)
const integer_class & as_integer_class() const
Convert to integer_class.
RCP< const Basic > get_exp() const
RCP< const Basic > get_base() const
const rational_class & as_rational_class() const
Convert to rational_class.
Main namespace for SymEngine package.
RCP< const Basic > mul(const RCP< const Basic > &a, const RCP< const Basic > &b)
Multiplication.
RCP< const Basic > exp(const RCP< const Basic > &x)
Returns the natural exponential function E**x = pow(E, x)
bool eq(const Basic &a, const Basic &b)
Checks equality for a and b
RCP< const Basic > div(const RCP< const Basic > &a, const RCP< const Basic > &b)
Division.
SYMENGINE_EXPORT RCP< const Basic > expand(const RCP< const Basic > &self, bool deep=true)
Expands self