1 #ifndef SYMENGINE_SUBS_H
2 #define SYMENGINE_SUBS_H
12 RCP<const Basic>
xreplace(
const RCP<const Basic> &x,
13 const map_basic_basic &subs_dict,
bool cache =
true);
17 RCP<const Basic> subs(
const RCP<const Basic> &x,
18 const map_basic_basic &subs_dict,
bool cache =
true);
22 RCP<const Basic>
msubs(
const RCP<const Basic> &x,
23 const map_basic_basic &subs_dict,
bool cache =
true);
26 RCP<const Basic>
ssubs(
const RCP<const Basic> &x,
27 const map_basic_basic &subs_dict,
bool cache =
true);
33 RCP<const Basic> result_;
34 const map_basic_basic &subs_dict_;
35 map_basic_basic visited;
40 : subs_dict_(subs_dict), cache(cache)
47 void bvisit(
const Basic &x)
52 void bvisit(
const Add &x)
54 SymEngine::umap_basic_num d;
55 RCP<const Number> coef;
57 auto it = subs_dict_.find(x.
get_coef());
58 if (it != subs_dict_.end()) {
65 for (
const auto &p : x.get_dict()) {
68 if (it != subs_dict_.end()) {
71 it = subs_dict_.find(p.second);
72 if (it != subs_dict_.end()) {
74 mul(it->second, apply(p.first)));
84 void bvisit(
const Mul &x)
86 RCP<const Number> coef = one;
88 for (
const auto &p : x.get_dict()) {
89 RCP<const Basic> factor_old;
90 if (
eq(*p.second, *one)) {
93 factor_old = make_rcp<Pow>(p.first, p.second);
95 RCP<const Basic>
factor = apply(factor_old);
96 if (
factor == factor_old) {
98 Mul::dict_add_term_new(outArg(coef), d, p.second, p.first);
100 imulnum(outArg(coef), rcp_static_cast<const Number>(
factor));
101 }
else if (is_a<Mul>(*
factor)) {
102 RCP<const Mul> tmp = rcp_static_cast<const Mul>(
factor);
103 imulnum(outArg(coef), tmp->get_coef());
104 for (
const auto &q : tmp->get_dict()) {
105 Mul::dict_add_term_new(outArg(coef), d, q.second, q.first);
108 RCP<const Basic>
exp, t;
110 Mul::dict_add_term_new(outArg(coef), d,
exp, t);
115 RCP<const Basic>
factor = apply(x.get_coef());
117 imulnum(outArg(coef), rcp_static_cast<const Number>(
factor));
118 }
else if (is_a<Mul>(*
factor)) {
119 RCP<const Mul> tmp = rcp_static_cast<const Mul>(
factor);
120 imulnum(outArg(coef), tmp->get_coef());
121 for (
const auto &q : tmp->get_dict()) {
122 Mul::dict_add_term_new(outArg(coef), d, q.second, q.first);
125 RCP<const Basic>
exp, t;
127 Mul::dict_add_term_new(outArg(coef), d,
exp, t);
132 void bvisit(
const Pow &x)
134 RCP<const Basic> base_new = apply(x.
get_base());
135 RCP<const Basic> exp_new = apply(x.
get_exp());
139 result_ = pow(base_new, exp_new);
149 result_ = x.
create(result_);
156 RCP<const Basic> a = apply(x.
get_arg1());
157 RCP<const Basic> b = apply(x.
get_arg2());
159 result_ = x.rcp_from_this();
167 for (
auto &elem : v) {
176 for (
auto &elem : v) {
184 RCP<const Basic> a = apply(x.get_expr());
185 auto c = apply(x.get_set());
186 if (not is_a_Set(*c))
187 throw SymEngineException(
"expected an object of type Set");
188 RCP<const Set> b = rcp_static_cast<const Set>(c);
189 if (a == x.get_expr() and b == x.get_set())
192 result_ = x.create(a, b);
195 void bvisit(
const And &x)
198 for (
const auto &elem : x.get_container()) {
199 auto a = apply(elem);
200 if (not is_a_Boolean(*a))
201 throw SymEngineException(
"expected an object of type Boolean");
202 v.insert(rcp_static_cast<const Boolean>(a));
204 result_ = logical_and(v);
207 void bvisit(
const Or &x)
210 for (
const auto &elem : x.get_container()) {
211 auto a = apply(elem);
212 if (not is_a_Boolean(*a))
213 throw SymEngineException(
"expected an object of type Boolean");
214 v.insert(rcp_static_cast<const Boolean>(a));
216 result_ = logical_or(v);
219 void bvisit(
const Not &x)
221 RCP<const Basic> a = apply(x.get_arg());
222 if (not is_a_Boolean(*a))
223 throw SymEngineException(
"expected an object of type Boolean");
224 result_ = logical_not(rcp_static_cast<const Boolean>(a));
227 void bvisit(
const Xor &x)
230 for (
const auto &elem : x.get_container()) {
231 auto a = apply(elem);
232 if (not is_a_Boolean(*a))
233 throw SymEngineException(
"expected an object of type Boolean");
234 v.push_back(rcp_static_cast<const Boolean>(a));
236 result_ = logical_xor(v);
242 for (
const auto &elem : x.get_container()) {
243 v.insert(apply(elem));
245 result_ = x.create(v);
250 RCP<const Basic> s = apply(x.get_symbol());
251 RCP<const Basic> expr = apply(x.get_expr());
252 auto bs_ = apply(x.get_baseset());
253 if (not is_a_Set(*bs_))
254 throw SymEngineException(
"expected an object of type Set");
255 RCP<const Set> bs = rcp_static_cast<const Set>(bs_);
256 if (s == x.get_symbol() and expr == x.get_expr()
257 and bs == x.get_baseset()) {
260 result_ = x.create(s, expr, bs);
264 void bvisit(
const Union &x)
267 for (
const auto &elem : x.get_container()) {
268 auto a = apply(elem);
269 if (not is_a_Set(*a))
270 throw SymEngineException(
"expected an object of type Set");
271 v.insert(rcp_static_cast<const Set>(a));
273 result_ = x.create(v);
279 pwv.reserve(pw.get_vec().size());
280 for (
const auto &expr_pred : pw.get_vec()) {
281 const auto expr = apply(*expr_pred.first);
282 const auto pred = apply(*expr_pred.second);
284 std::make_pair(expr, rcp_static_cast<const Boolean>(pred)));
286 result_ = piecewise(std::move(pwv));
291 auto expr = apply(x.get_arg());
292 for (
const auto &sym : x.get_symbols()) {
294 if (not is_a<Symbol>(*s)) {
295 throw SymEngineException(
"expected an object of type Symbol");
297 expr = expr->diff(rcp_static_cast<const Symbol>(s));
302 void bvisit(
const Subs &x)
304 auto expr = apply(x.get_arg());
305 map_basic_basic new_subs_dict;
306 for (
const auto &sym : x.get_dict()) {
307 insert(new_subs_dict, apply(sym.first), apply(sym.second));
309 result_ = subs(expr, new_subs_dict);
314 auto it = subs_dict_.find(I);
315 if (it != subs_dict_.end()) {
316 result_ =
add(apply(x.real_part()),
317 mul(apply(x.imaginary_part()), it->second));
323 RCP<const Basic> apply(
const Basic &x)
328 RCP<const Basic> apply(
const RCP<const Basic> &x)
331 auto it = visited.find(x);
332 if (it != visited.end()) {
333 result_ = it->second;
336 insert(visited, x, result_);
339 auto it = subs_dict_.find(x);
340 if (it != subs_dict_.end()) {
341 result_ = it->second;
351 inline RCP<const Basic>
xreplace(
const RCP<const Basic> &x,
352 const map_basic_basic &subs_dict,
bool cache)
361 using XReplaceVisitor::bvisit;
363 SubsVisitor(
const map_basic_basic &subs_dict_,
bool cache =
true)
368 void bvisit(
const Pow &x)
370 RCP<const Basic> base_new = apply(x.
get_base());
371 RCP<const Basic> exp_new = apply(x.
get_exp());
372 if (subs_dict_.size() == 1 and is_a<Pow>(*((*subs_dict_.begin()).first))
374 *down_cast<const Pow &>(*(*subs_dict_.begin()).first)
377 = down_cast<const Pow &>(*(*subs_dict_.begin()).first);
378 if (
eq(*subs_first.get_base(), *base_new)) {
379 auto newexpo =
div(exp_new, subs_first.get_exp());
380 if (
is_a_Number(*newexpo) or is_a<Constant>(*newexpo)) {
381 result_ = pow((*subs_dict_.begin()).second, newexpo);
389 result_ = pow(base_new, exp_new);
396 map_basic_basic m, n;
399 for (
const auto &p : subs_dict_) {
402 if (
eq(*x.get_arg(), *p.first)) {
403 RCP<const Basic> t = p.second;
404 for (
auto &sym : x.get_symbols()) {
405 if (not is_a<Symbol>(*sym)) {
406 throw SymEngineException(
"Error, expected a Symbol.");
408 t = t->diff(rcp_static_cast<const Symbol>(sym));
414 for (
const auto &p : subs_dict_) {
416 if (
eq(*x.get_arg()->subs({{p.first, p.second}}), *x.get_arg()))
421 if (is_a<Symbol>(*p.first) and is_a<Symbol>(*p.second)
423 *x.get_arg()->diff(rcp_static_cast<const Symbol>(p.second)),
425 insert(n, p.first, p.second);
428 for (
const auto &d : x.get_symbols()) {
429 if (is_a<Symbol>(*d)) {
430 s = rcp_static_cast<const Symbol>(d);
433 if (
neq(*zero, *(p.first->diff(s)))
434 ||
neq(*zero, *(p.second->diff(s)))) {
445 insert(n, p.first, p.second);
447 insert(m, p.first, p.second);
450 auto t = x.get_arg()->
subs(n);
451 for (
auto &p : x.get_symbols()) {
452 auto t2 = p->subs(n);
453 if (not is_a<Symbol>(*t2)) {
454 throw SymEngineException(
"Error, expected a Symbol.");
456 t = t->diff(rcp_static_cast<const Symbol>(t2));
461 result_ = make_rcp<const Subs>(t, m);
465 void bvisit(
const Subs &x)
467 map_basic_basic m, n;
468 for (
const auto &p : subs_dict_) {
470 for (
const auto &s : x.get_dict()) {
471 if (
neq(*(s.first->subs({{p.first, p.second}})), *(s.first))) {
479 insert(n, p.first, p.second);
482 for (
const auto &s : x.get_dict()) {
483 insert(m, s.first, apply(s.second));
485 RCP<const Basic> presub = x.get_arg()->subs(n);
486 if (is_a<Subs>(*presub)) {
487 for (
auto &q : down_cast<const Subs &>(*presub).get_dict()) {
488 insert(m, q.first, q.second);
490 result_ = down_cast<const Subs &>(*presub).get_arg()->subs(m);
492 result_ = presub->subs(m);
500 using XReplaceVisitor::bvisit;
502 MSubsVisitor(
const map_basic_basic &d,
bool cache =
true)
512 void bvisit(
const Subs &x)
514 map_basic_basic m = x.get_dict();
515 for (
const auto &p : subs_dict_) {
516 m[p.first] = p.second;
518 result_ =
msubs(x.get_arg(), m);
525 using XReplaceVisitor::bvisit;
527 SSubsVisitor(
const map_basic_basic &d,
bool cache =
true)
537 for (
auto &p : x.get_symbols()) {
541 result_ = Derivative::create(t, m);
544 void bvisit(
const Subs &x)
546 map_basic_basic m = x.get_dict();
547 for (
const auto &p : subs_dict_) {
548 m[p.first] = p.second;
550 result_ =
ssubs(x.get_arg(), m);
555 inline RCP<const Basic>
msubs(
const RCP<const Basic> &x,
556 const map_basic_basic &subs_dict,
bool cache)
563 inline RCP<const Basic>
ssubs(
const RCP<const Basic> &x,
564 const map_basic_basic &subs_dict,
bool cache)
570 inline RCP<const Basic> subs(
const RCP<const Basic> &x,
571 const map_basic_basic &subs_dict,
bool cache)
573 SubsVisitor b(subs_dict, cache);
The base class for representing addition in symbolic expressions.
static RCP< const Basic > from_dict(const RCP< const Number > &coef, umap_basic_num &&d)
Create an appropriate instance from dictionary quickly.
static void coef_dict_add_term(const Ptr< RCP< const Number >> &coef, umap_basic_num &d, const RCP< const Number > &c, const RCP< const Basic > &term)
Updates the numerical coefficient and the dictionary.
const RCP< const Number > & get_coef() const
The lowest unit of symbolic representation.
RCP< const Basic > subs(const map_basic_basic &subs_dict) const
Substitutes 'subs_dict' into 'self'.
ComplexBase Class for deriving all complex classes.
RCP< T > rcp_from_this()
Get RCP<T> pointer to self (it will cast the pointer to T)
RCP< const Basic > create(const vec_basic &x) const override
Method to construct classes with canonicalization.
static void as_base_exp(const RCP< const Basic > &self, const Ptr< RCP< const Basic >> &exp, const Ptr< RCP< const Basic >> &base)
Convert to a base and exponent form.
static RCP< const Basic > from_dict(const RCP< const Number > &coef, map_basic_basic &&d)
Create a Mul from a dict.
virtual RCP< const Basic > create(const vec_basic &v) const =0
Method to construct classes with canonicalization.
vec_basic get_args() const override
Returns the list of arguments.
virtual RCP< const Basic > create(const RCP< const Basic > &arg) const =0
Method to construct classes with canonicalization.
RCP< const Basic > get_arg() const
RCP< const Basic > get_exp() const
RCP< const Basic > get_base() const
virtual RCP< const Basic > create(const RCP< const Basic > &a, const RCP< const Basic > &b) const =0
Method to construct classes with canonicalization.
RCP< const Basic > get_arg1() const
RCP< const Basic > get_arg2() const
Main namespace for SymEngine package.
bool is_a_Number(const Basic &b)
RCP< const Basic > add(const RCP< const Basic > &a, const RCP< const Basic > &b)
Adds two objects (safely).
int factor(const Ptr< RCP< const Integer >> &f, const Integer &n, double B1)
RCP< const Basic > mul(const RCP< const Basic > &a, const RCP< const Basic > &b)
Multiplication.
SYMENGINE_EXPORT RCP< const Basic > msubs(const RCP< const Basic > &x, const map_basic_basic &subs_dict, bool cache=true)
Subs which treat f(t) and Derivative(f(t), t) as separate variables.
RCP< const Basic > exp(const RCP< const Basic > &x)
Returns the natural exponential function E**x = pow(E, x)
void insert(T1 &m, const T2 &first, const T3 &second)
bool eq(const Basic &a, const Basic &b)
Checks equality for a and b
bool neq(const Basic &a, const Basic &b)
Checks inequality for a and b
RCP< const Basic > div(const RCP< const Basic > &a, const RCP< const Basic > &b)
Division.
SYMENGINE_EXPORT RCP< const Basic > xreplace(const RCP< const Basic > &x, const map_basic_basic &subs_dict, bool cache=true)
Mappings in the subs_dict are applied to the expression tree of x
SYMENGINE_EXPORT RCP< const Basic > ssubs(const RCP< const Basic > &x, const map_basic_basic &subs_dict, bool cache=true)
SymPy compatible subs.