#include "basic.h"
#include "ex.h"
#include "numeric.h"
+#include "mul.h"
#include "power.h"
#include "symbol.h"
#include "lst.h"
lst::const_iterator its, itr;
- if (options & subs_options::subs_no_pattern) {
+ if (options & subs_options::no_pattern) {
for (its = ls.begin(), itr = lr.begin(); its != ls.end(); ++its, ++itr) {
if (is_equal(ex_to<basic>(*its)))
return *itr;
for (its = ls.begin(), itr = lr.begin(); its != ls.end(); ++its, ++itr) {
lst repl_lst;
if (match(ex_to<basic>(*its), repl_lst))
- return itr->subs(repl_lst, options | subs_options::subs_no_pattern); // avoid infinite recursion when re-substituting the wildcards
+ return itr->subs(repl_lst, options | subs_options::no_pattern); // avoid infinite recursion when re-substituting the wildcards
}
}
if (!r.info(info_flags::relation_equal)) {
throw(std::invalid_argument("basic::subs(ex): argument must be a list of equations"));
}
- ls.append(r.op(0));
+ const ex & s = r.op(0);
+ ls.append(s);
lr.append(r.op(1));
+
+ // Search for products and powers in the expressions to be substituted
+ // (for an optimization in expairseq::subs())
+ if (is_exactly_a<mul>(s) || is_exactly_a<power>(s))
+ options |= subs_options::pattern_is_product;
}
+ if (!(options & subs_options::pattern_is_product))
+ options |= subs_options::pattern_is_not_product;
+
return subs(ls, lr, options);
}
epvector *vp = subschildren(ls, lr, options);
if (vp)
return ex_to<basic>(thisexpairseq(vp, overall_coeff));
- else if ((options & subs_options::subs_algebraic) && is_exactly_a<mul>(*this))
+ else if ((options & subs_options::algebraic) && is_exactly_a<mul>(*this))
return static_cast<const mul *>(this)->algebraic_subs_mul(ls, lr, options);
else
return basic::subs(ls, lr, options);
{
GINAC_ASSERT(ls.nops()==lr.nops());
- // The substitution is "complex" when any of the objects to be substituted
- // is a product or power. In this case we have to recombine the pairs
- // because the numeric coefficients may be part of the search pattern.
- bool complex_subs = false;
- for (lst::const_iterator it = ls.begin(); it != ls.end(); ++it) {
- if (is_exactly_a<mul>(*it) || is_exactly_a<power>(*it)) {
- complex_subs = true;
- break;
+ // When any of the objects to be substituted is a product or power
+ // we have to recombine the pairs because the numeric coefficients may
+ // be part of the search pattern.
+ if (!(options & (subs_options::pattern_is_product | subs_options::pattern_is_not_product))) {
+
+ // Search the list of substitutions and cache our findings
+ for (lst::const_iterator it = ls.begin(); it != ls.end(); ++it) {
+ if (is_exactly_a<mul>(*it) || is_exactly_a<power>(*it)) {
+ options |= subs_options::pattern_is_product;
+ break;
+ }
}
+ if (!(options & subs_options::pattern_is_product))
+ options |= subs_options::pattern_is_not_product;
}
- if (complex_subs) {
+ if (options & subs_options::pattern_is_product) {
// Substitute in the recombined pairs
epvector::const_iterator cit = seq.begin(), last = seq.end();
subsresult[j] = op(j);
else {
foundfirstsubsedfactor = true;
- subsresult[j] = op(j) * power(itr->subs(ex(repls), subs_options::subs_no_pattern) / its->subs(ex(repls), subs_options::subs_no_pattern), nummatches);
+ subsresult[j] = op(j) * power(itr->subs(ex(repls), subs_options::no_pattern) / its->subs(ex(repls), subs_options::no_pattern), nummatches);
}
subsed[j] = true;
}
for (size_t j=0; j<this->nops(); j++) {
if (!subsed[j] && tryfactsubs(op(j), *its, nummatches, repls)) {
subsed[j] = true;
- subsresult[j] = op(j) * power(itr->subs(ex(repls), subs_options::subs_no_pattern) / its->subs(ex(repls), subs_options::subs_no_pattern), nummatches);
+ subsresult[j] = op(j) * power(itr->subs(ex(repls), subs_options::no_pattern) / its->subs(ex(repls), subs_options::no_pattern), nummatches);
}
}
}
}
}
if (!subsfound)
- return basic::subs(ls, lr, options | subs_options::subs_algebraic);
+ return basic::subs(ls, lr, options | subs_options::algebraic);
exvector ev; ev.reserve(nops());
for (size_t i=0; i<nops(); i++) {
|| !are_ex_trivially_equal(exponent, subsed_exponent))
return power(subsed_basis, subsed_exponent).basic::subs(ls, lr, options);
- if(!(options & subs_options::subs_algebraic))
+ if(!(options & subs_options::algebraic))
return basic::subs(ls, lr, options);
lst::const_iterator its, itr;
int nummatches = std::numeric_limits<int>::max();
lst repls;
if (tryfactsubs(*this, *its, nummatches, repls))
- return (ex_to<basic>((*this) * power(itr->subs(ex(repls), subs_options::subs_no_pattern) / its->subs(ex(repls), subs_options::subs_no_pattern), nummatches))).basic::subs(ls, lr, options);
+ return (ex_to<basic>((*this) * power(itr->subs(ex(repls), subs_options::no_pattern) / its->subs(ex(repls), subs_options::no_pattern), nummatches))).basic::subs(ls, lr, options);
}
ex result=basic::subs(ls, lr, options);