Loading...
Searching...
No Matches
basic_conversions.cpp
1#include <symengine/visitor.h>
2#include <symengine/polys/basic_conversions.h>
3
4namespace SymEngine
5{
6// all throughout Number refers to either a Rational or an Integer only
7umap_basic_num _find_gens_poly_pow(const RCP<const Basic> &x,
8 const RCP<const Basic> &base);
9
10class PolyGeneratorVisitor : public BaseVisitor<PolyGeneratorVisitor>
11{
12private:
13 // the generators are pow(it.first, it.second)
14 // those which are not Pow are stored as (x, one)
15 // numbers must always be positive and of the form (1/d, d belongs to N)
16 umap_basic_num gen_set;
17
18public:
19 umap_basic_num apply(const Basic &b)
20 {
21 b.accept(*this);
22 return std::move(gen_set);
23 }
24
25 // adds curr to gen_set, or updates already existing gen
26 void add_to_gen_set(const RCP<const Basic> &base,
27 const RCP<const Number> &exp)
28 {
29 auto it = gen_set.find(base);
30 if (it == gen_set.end()) {
31 gen_set[base] = exp;
32 return;
33 }
34
37 = down_cast<const Rational &>(*exp).get_den();
38 if (is_a<const Rational>(*it->second))
39 gen_set[base] = divnum(
40 one,
41 lcm(*den,
42 *down_cast<const Rational &>(*it->second).get_den()));
43 else
44 gen_set[base] = divnum(one, den);
45 }
46 }
47
48 void bvisit(const Pow &x)
49 {
50 if (is_a<const Integer>(*x.get_exp())) {
51 if (down_cast<const Integer &>(*x.get_exp()).is_positive()) {
52 x.get_base()->accept(*this);
53 } else {
54 add_to_gen_set(pow(x.get_base(), minus_one), one);
55 }
56
57 } else if (is_a<const Rational>(*x.get_exp())) {
58
59 RCP<const Basic> base = x.get_base();
62 if (r->is_negative())
63 base = pow(base, minus_one);
64 add_to_gen_set(base, divnum(one, r->get_den()));
65
66 } else {
68 = _find_gens_poly_pow(x.get_exp(), x.get_base());
69 for (auto it : pow_pairs)
70 add_to_gen_set(pow(x.get_base(), it.first), it.second);
71 }
72 }
73
74 void bvisit(const Add &x)
75 {
76 for (auto it : x.get_dict())
77 it.first->accept(*this);
78 }
79
80 void bvisit(const Mul &x)
81 {
82 for (auto it : x.get_dict())
83 it.first->accept(*this);
84 }
85
86 void bvisit(const Number &x)
87 {
88 // intentionally blank
89 }
90
91 void bvisit(const Basic &x)
92 {
93 add_to_gen_set(x.rcp_from_this(), one);
94 }
95};
96
97class PolyGeneratorVisitorPow : public BaseVisitor<PolyGeneratorVisitorPow>
98{
99private:
100 // the generators are mul(it.first, it.second) not Pow
101 // the_base is the base of the Pow (whose exp we are currently dealing)
102 // numbers must always be positive and of the form (1/d, d belongs to N)
103 umap_basic_num gen_set;
104 RCP<const Basic> the_base;
105
106public:
107 umap_basic_num apply(const Basic &b, const RCP<const Basic> &base)
108 {
109 the_base = base;
110 b.accept(*this);
111 return std::move(gen_set);
112 }
113
114 void bvisit(const Add &x)
115 {
116 if (not x.get_coef()->is_zero())
117 x.get_coef()->accept(*this);
118
119 for (auto it : x.get_dict()) {
120 RCP<const Number> mulx = one, divx = one;
121
122 if (it.second->is_negative())
123 mulx = minus_one;
124
125 if (is_a<const Rational>(*it.second))
126 divx = down_cast<const Rational &>(*it.second).get_den();
127
128 gen_set[mul(mulx, it.first)] = divnum(one, divx);
129 }
130 }
131
132 void bvisit(const Mul &x)
133 {
134 // won't handle cases like 2**((x+1)(x+2))
135 // needs `expand` to have been called
136 RCP<const Number> mulx = one, divx = one;
137
138 if (x.get_coef()->is_negative())
139 mulx = minus_one;
140
141 if (is_a<const Rational>(*x.get_coef()))
142 divx = down_cast<const Rational &>(*x.get_coef()).get_den();
143
144 auto dict = x.get_dict();
145 gen_set[Mul::from_dict(mulx, std::move(dict))] = divnum(one, divx);
146 }
147
148 void bvisit(const Number &x)
149 {
150 if (not is_a_Number(*pow(the_base, x.rcp_from_this()))) {
151 if (x.is_positive())
152 gen_set[one] = x.rcp_from_this_cast<const Number>();
153 else
154 gen_set[minus_one]
155 = mulnum(x.rcp_from_this_cast<const Number>(), minus_one);
156 }
157 }
158
159 void bvisit(const Basic &x)
160 {
161 gen_set[x.rcp_from_this()] = one;
162 }
163};
164
165umap_basic_num _find_gens_poly(const RCP<const Basic> &x)
166{
168 return v.apply(*x);
169}
170
171umap_basic_num _find_gens_poly_pow(const RCP<const Basic> &x,
172 const RCP<const Basic> &base)
173{
174 PolyGeneratorVisitorPow v;
175 return v.apply(*x, base);
176}
177
178} // namespace SymEngine
The base class for representing addition in symbolic expressions.
Definition add.h:27
const RCP< const Number > & get_coef() const
Definition add.h:142
The lowest unit of symbolic representation.
Definition basic.h:97
RCP< const T2 > rcp_from_this_cast() const
Get RCP<T2> pointer to self (it will cast the pointer to T2)
RCP< T > rcp_from_this()
Get RCP<T> pointer to self (it will cast the pointer to T)
static RCP< const Basic > from_dict(const RCP< const Number > &coef, map_basic_basic &&d)
Create a Mul from a dict.
Definition mul.cpp:115
virtual bool is_positive() const =0
RCP< const Basic > get_base() const
Definition pow.h:37
RCP< const Basic > get_exp() const
Definition pow.h:42
T end(T... args)
T find(T... args)
T move(T... args)
Main namespace for SymEngine package.
Definition add.cpp:19
bool is_a_Number(const Basic &b)
Definition number.h:130
void hash_combine(hash_t &seed, const T &v)
Definition basic-inl.h:95
RCP< const Basic > exp(const RCP< const Basic > &x)
Returns the natural exponential function E**x = pow(E, x)
Definition pow.cpp:271
RCP< const Integer > lcm(const Integer &a, const Integer &b)
Least Common Multiple.
Definition ntheory.cpp:49
RCP< const Basic > mul(const RCP< const Basic > &a, const RCP< const Basic > &b)
Multiplication.
Definition mul.cpp:352
RCP< const Number > mulnum(const RCP< const Number > &self, const RCP< const Number > &other)
Multiply self and other
Definition number.h:93
RCP< const Number > divnum(const RCP< const Number > &self, const RCP< const Number > &other)
Divide self and other
Definition number.h:99