Example #1
0
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));
}
Example #2
0
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));
}
Example #3
0
// 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);
            }
        }
    }
}
Example #4
0
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;
}
Example #5
0
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);
}
Example #6
0
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);
}
Example #7
0
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));
}
Example #8
0
// 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);
                }
            }
        }
    }
}
Example #9
0
// 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))));
                }
            }
        }
    }
}