RCP<const Basic> Add::subs(const map_basic_basic &subs_dict) const { RCP<const Add> self = rcp_const_cast<Add>(rcp(this)); auto it = subs_dict.find(self); if (it != subs_dict.end()) return it->second; CSymPy::umap_basic_num d; RCP<const Number> coef=coef_, coef2; RCP<const Basic> t; for (auto &p: dict_) { RCP<const Basic> term = p.first->subs(subs_dict); if (term == p.first) { Add::dict_add_term(d, p.second, p.first); } else if (is_a<Integer>(*term) && rcp_static_cast<const Integer>(term)->is_zero()) { continue; } else if (is_a_Number(*term)) { iaddnum(outArg(coef), mulnum(p.second, rcp_static_cast<const Number>(term))); } else if (is_a<Add>(*term)) { for (auto &q: (rcp_static_cast<const Add>(term))->dict_) Add::dict_add_term(d, q.second, q.first); iaddnum(outArg(coef), rcp_static_cast<const Add>(term)->coef_); } else { Add::as_coef_term(mul(p.second, term), outArg(coef2), outArg(t)); Add::dict_add_term(d, coef2, t); } } return Add::from_dict(coef, std::move(d)); }
RCP<const Basic> Mul::subs(const map_basic_basic &subs_dict) const { RCP<const Mul> self = rcp_const_cast<Mul>(rcp(this)); auto it = subs_dict.find(self); if (it != subs_dict.end()) return it->second; RCP<const Number> coef = coef_; map_basic_basic d; for (auto &p: dict_) { RCP<const Basic> factor_old = pow(p.first, p.second); RCP<const Basic> factor = factor_old->subs(subs_dict); if (factor == factor_old) { Mul::dict_add_term_new(outArg(coef), d, p.second, p.first); } else if (is_a<Integer>(*factor) && rcp_static_cast<const Integer>(factor)->is_zero()) { return zero; } else if (is_a_Number(*factor)) { imulnum(outArg(coef), rcp_static_cast<const Number>(factor)); } else if (is_a<Mul>(*factor)) { RCP<const Mul> tmp = rcp_static_cast<const Mul>(factor); imulnum(outArg(coef), tmp->coef_); for (auto &q: tmp->dict_) { Mul::dict_add_term_new(outArg(coef), d, q.second, q.first); } } else { RCP<const Basic> exp, t; Mul::as_base_exp(factor, outArg(exp), outArg(t)); Mul::dict_add_term_new(outArg(coef), d, exp, t); } } return Mul::from_dict(coef, std::move(d)); }
// Mul (t^exp) to the dict "d" void Mul::dict_add_term(map_basic_basic &d, const RCP<const Basic> &exp, const RCP<const Basic> &t) { auto it = d.find(t); if (it == d.end()) { insert(d, t, exp); } else { // Very common case, needs to be fast: if (is_a_Number(*it->second) && is_a_Number(*exp)) { RCP<const Number> tmp = rcp_static_cast<const Number>(it->second); iaddnum(outArg(tmp), rcp_static_cast<const Number>(exp)); if (tmp->is_zero()) { d.erase(it); } else { it->second = tmp; } } else { // General case: it->second = add(it->second, exp); if (is_a<Integer>(*it->second) && rcp_static_cast<const Integer>(it->second)->is_zero()) { d.erase(it); } } } }
RCP<const Basic> Basic::subs(const map_basic_basic &subs_dict) const { RCP<const Basic> self = rcp_const_cast<Basic>(rcp(this)); auto it = subs_dict.find(self); if (it == subs_dict.end()) return self; else return it->second; }
RCP<const Basic> Sec::subs(const map_basic_basic &subs_dict) const { RCP<const Sec> self = rcp_const_cast<Sec>(rcp(this)); auto it = subs_dict.find(self); if (it != subs_dict.end()) return it->second; RCP<const Basic> arg = arg_->subs(subs_dict); if (arg == arg_) return self; else return sec(arg); }
RCP<const Basic> Pow::subs(const map_basic_basic &subs_dict) const { RCP<const Pow> self = rcp_const_cast<Pow>(rcp(this)); auto it = subs_dict.find(self); if (it != subs_dict.end()) return it->second; RCP<const Basic> base_new = base_->subs(subs_dict); RCP<const Basic> exp_new = exp_->subs(subs_dict); if (base_new == base_ && exp_new == exp_) return self; else return pow(base_new, exp_new); }
RCP<const Basic> Add::subs(const map_basic_basic &subs_dict) const { RCP<const Add> self = rcp_from_this_cast<const Add>(); auto it = subs_dict.find(self); if (it != subs_dict.end()) return it->second; SymEngine::umap_basic_num d; RCP<const Number> coef; it = subs_dict.find(coef_); if (it != subs_dict.end()) { coef = zero; coef_dict_add_term(outArg(coef), d, one, it->second); } else { coef = coef_; } for (const auto &p: dict_) { auto it = subs_dict.find(Add::from_dict(zero, {{p.first, p.second}})); if (it != subs_dict.end()) { coef_dict_add_term(outArg(coef), d, one, it->second); } else { it = subs_dict.find(p.second); if (it != subs_dict.end()) { coef_dict_add_term(outArg(coef), d, one, mul(it->second, p.first->subs(subs_dict))); } else { coef_dict_add_term(outArg(coef), d, p.second, p.first->subs(subs_dict)); } } } return Add::from_dict(coef, std::move(d)); }
// Mul (t^exp) to the dict "d" void Mul::dict_add_term_new(const Ptr<RCP<const Number>> &coef, map_basic_basic &d, const RCP<const Basic> &exp, const RCP<const Basic> &t) { auto it = d.find(t); if (it == d.end()) { // Don't check for `exp = 0` here // `pow` for Complex is not expanded by default if (is_a<Integer>(*exp) && (is_a<Integer>(*t) || is_a<Rational>(*t))) { imulnum(outArg(*coef), pownum(rcp_static_cast<const Number>(t), rcp_static_cast<const Number>(exp))); } else if (is_a<Integer>(*exp) && is_a<Complex>(*t)) { if (rcp_static_cast<const Integer>(exp)->is_one()) { imulnum(outArg(*coef), rcp_static_cast<const Number>(t)); } else if (rcp_static_cast<const Integer>(exp)->is_minus_one()) { idivnum(outArg(*coef), rcp_static_cast<const Number>(t)); } else { insert(d, t, exp); } } else { insert(d, t, exp); } } else { // Very common case, needs to be fast: if (is_a_Number(*exp) && is_a_Number(*it->second)) { RCP<const Number> tmp = rcp_static_cast<const Number>(it->second); iaddnum(outArg(tmp), rcp_static_cast<const Number>(exp)); it->second = tmp; } else it->second = add(it->second, exp); if (is_a<Integer>(*it->second)) { // `pow` for Complex is not expanded by default if (is_a<Integer>(*t) || is_a<Rational>(*t)) { if (!rcp_static_cast<const Integer>(it->second)->is_zero()) { imulnum(outArg(*coef), pownum(rcp_static_cast<const Number>(t), rcp_static_cast<const Number>(it->second))); } d.erase(it); } else if (rcp_static_cast<const Integer>(it->second)->is_zero()) { d.erase(it); } else if (is_a<Complex>(*t)) { if (rcp_static_cast<const Integer>(it->second)->is_one()) { imulnum(outArg(*coef), rcp_static_cast<const Number>(t)); d.erase(it); } else if (rcp_static_cast<const Integer>(it->second)->is_minus_one()) { idivnum(outArg(*coef), rcp_static_cast<const Number>(t)); d.erase(it); } } } } }
// Mul (t**exp) to the dict "d" void Mul::dict_add_term_new(const Ptr<RCP<const Number>> &coef, map_basic_basic &d, const RCP<const Basic> &exp, const RCP<const Basic> &t) { auto it = d.find(t); if (it == d.end()) { // Don't check for `exp = 0` here // `pow` for Complex is not expanded by default if (is_a<Integer>(*t) || is_a<Rational>(*t)) { if (is_a<Integer>(*exp)) { imulnum(outArg(*coef), pownum(rcp_static_cast<const Number>(t), rcp_static_cast<const Number>(exp))); } else if (is_a<Rational>(*exp)) { // Here we make the exponent postive and a fraction between // 0 and 1. mpz_class q, r, num, den; num = rcp_static_cast<const Rational>(exp)->i.get_num(); den = rcp_static_cast<const Rational>(exp)->i.get_den(); mpz_fdiv_qr(q.get_mpz_t(), r.get_mpz_t(), num.get_mpz_t(), den.get_mpz_t()); insert(d, t, Rational::from_mpq(mpq_class(r, den))); imulnum(outArg(*coef), pownum(rcp_static_cast<const Number>(t), rcp_static_cast<const Number>(integer(q)))); } else { insert(d, t, exp); } } else if (is_a<Integer>(*exp) && is_a<Complex>(*t)) { if (rcp_static_cast<const Integer>(exp)->is_one()) { imulnum(outArg(*coef), rcp_static_cast<const Number>(t)); } else if (rcp_static_cast<const Integer>(exp)->is_minus_one()) { idivnum(outArg(*coef), rcp_static_cast<const Number>(t)); } else { insert(d, t, exp); } } else { insert(d, t, exp); } } else { // Very common case, needs to be fast: if (is_a_Number(*exp) && is_a_Number(*it->second)) { RCP<const Number> tmp = rcp_static_cast<const Number>(it->second); iaddnum(outArg(tmp), rcp_static_cast<const Number>(exp)); it->second = tmp; } else it->second = add(it->second, exp); if (is_a<Integer>(*it->second)) { // `pow` for Complex is not expanded by default if (is_a<Integer>(*t) || is_a<Rational>(*t)) { if (!rcp_static_cast<const Integer>(it->second)->is_zero()) { imulnum(outArg(*coef), pownum(rcp_static_cast<const Number>(t), rcp_static_cast<const Number>(it->second))); } d.erase(it); } else if (rcp_static_cast<const Integer>(it->second)->is_zero()) { d.erase(it); } else if (is_a<Complex>(*t)) { if (rcp_static_cast<const Integer>(it->second)->is_one()) { imulnum(outArg(*coef), rcp_static_cast<const Number>(t)); d.erase(it); } else if (rcp_static_cast<const Integer>(it->second)->is_minus_one()) { idivnum(outArg(*coef), rcp_static_cast<const Number>(t)); d.erase(it); } } } else if (is_a<Rational>(*it->second)) { if (is_a_Number(*t)) { mpz_class q, r, num, den; num = rcp_static_cast<const Rational>(it->second)->i.get_num(); den = rcp_static_cast<const Rational>(it->second)->i.get_den(); // Here we make the exponent postive and a fraction between // 0 and 1. if (num > den || num < 0) { mpz_fdiv_qr(q.get_mpz_t(), r.get_mpz_t(), num.get_mpz_t(), den.get_mpz_t()); it->second = Rational::from_mpq(mpq_class(r, den)); imulnum(outArg(*coef), pownum(rcp_static_cast<const Number>(t), rcp_static_cast<const Number>(integer(q)))); } } } } }