* Implementation of GiNaC's products of expressions. */
/*
- * GiNaC Copyright (C) 1999-2005 Johannes Gutenberg University Mainz, Germany
+ * GiNaC Copyright (C) 1999-2006 Johannes Gutenberg University Mainz, Germany
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
mul::mul()
{
- tinfo_key = TINFO_mul;
+ tinfo_key = &mul::tinfo_static;
}
//////////
mul::mul(const ex & lh, const ex & rh)
{
- tinfo_key = TINFO_mul;
+ tinfo_key = &mul::tinfo_static;
overall_coeff = _ex1;
construct_from_2_ex(lh,rh);
GINAC_ASSERT(is_canonical());
mul::mul(const exvector & v)
{
- tinfo_key = TINFO_mul;
+ tinfo_key = &mul::tinfo_static;
overall_coeff = _ex1;
construct_from_exvector(v);
GINAC_ASSERT(is_canonical());
mul::mul(const epvector & v)
{
- tinfo_key = TINFO_mul;
+ tinfo_key = &mul::tinfo_static;
overall_coeff = _ex1;
construct_from_epvector(v);
GINAC_ASSERT(is_canonical());
mul::mul(const epvector & v, const ex & oc)
{
- tinfo_key = TINFO_mul;
+ tinfo_key = &mul::tinfo_static;
overall_coeff = oc;
construct_from_epvector(v);
GINAC_ASSERT(is_canonical());
mul::mul(std::auto_ptr<epvector> vp, const ex & oc)
{
- tinfo_key = TINFO_mul;
+ tinfo_key = &mul::tinfo_static;
GINAC_ASSERT(vp.get()!=0);
overall_coeff = oc;
construct_from_epvector(*vp);
mul::mul(const ex & lh, const ex & mh, const ex & rh)
{
- tinfo_key = TINFO_mul;
+ tinfo_key = &mul::tinfo_static;
exvector factors;
factors.reserve(3);
factors.push_back(lh);
return true;
}
+/** Checks wheter e matches to the pattern pat and the (possibly to be updated
+ * list of replacements repls. This matching is in the sense of algebraic
+ * substitutions. Matching starts with pat.op(factor) of the pattern because
+ * the factors before this one have already been matched. The (possibly
+ * updated) number of matches is in nummatches. subsed[i] is true for factors
+ * that already have been replaced by previous substitutions and matched[i]
+ * is true for factors that have been matched by the current match.
+ */
+bool algebraic_match_mul_with_mul(const mul &e, const ex &pat, lst &repls,
+ int factor, int &nummatches, const std::vector<bool> &subsed,
+ std::vector<bool> &matched)
+{
+ if (factor == pat.nops())
+ return true;
+
+ for (size_t i=0; i<e.nops(); ++i) {
+ if(subsed[i] || matched[i])
+ continue;
+ lst newrepls = repls;
+ int newnummatches = nummatches;
+ if (tryfactsubs(e.op(i), pat.op(factor), newnummatches, newrepls)) {
+ matched[i] = true;
+ if (algebraic_match_mul_with_mul(e, pat, newrepls, factor+1,
+ newnummatches, subsed, matched)) {
+ repls = newrepls;
+ nummatches = newnummatches;
+ return true;
+ }
+ else
+ matched[i] = false;
+ }
+ }
+
+ return false;
+}
+
+bool mul::has(const ex & pattern, unsigned options) const
+{
+ if(!(options&has_options::algebraic))
+ return basic::has(pattern,options);
+ if(is_a<mul>(pattern)) {
+ lst repls;
+ int nummatches = std::numeric_limits<int>::max();
+ std::vector<bool> subsed(seq.size(), false);
+ std::vector<bool> matched(seq.size(), false);
+ if(algebraic_match_mul_with_mul(*this, pattern, repls, 0, nummatches,
+ subsed, matched))
+ return true;
+ }
+ return basic::has(pattern, options);
+}
+
ex mul::algebraic_subs_mul(const exmap & m, unsigned options) const
{
std::vector<bool> subsed(seq.size(), false);
for (exmap::const_iterator it = m.begin(); it != m.end(); ++it) {
if (is_exactly_a<mul>(it->first)) {
-
+retry1:
int nummatches = std::numeric_limits<int>::max();
std::vector<bool> currsubsed(seq.size(), false);
bool succeed = true;
lst repls;
-
- for (size_t j=0; j<it->first.nops(); j++) {
- bool found=false;
- for (size_t k=0; k<nops(); k++) {
- if (currsubsed[k] || subsed[k])
- continue;
- if (tryfactsubs(op(k), it->first.op(j), nummatches, repls)) {
- currsubsed[k] = true;
- found = true;
- break;
- }
- }
- if (!found) {
- succeed = false;
- break;
- }
- }
- if (!succeed)
+
+ if(!algebraic_match_mul_with_mul(*this, it->first, repls, 0, nummatches, subsed, currsubsed))
continue;
bool foundfirstsubsedfactor = false;
subsed[j] = true;
}
}
+ goto retry1;
} else {
-
+retry2:
int nummatches = std::numeric_limits<int>::max();
lst repls;
if (!subsed[j] && tryfactsubs(op(j), it->first, nummatches, repls)) {
subsed[j] = true;
subsresult[j] = op(j) * power(it->second.subs(ex(repls), subs_options::no_pattern) / it->first.subs(ex(repls), subs_options::no_pattern), nummatches);
+ goto retry2;
}
}
}
if ((rt == return_types::noncommutative) && (!all_commutative)) {
// another nc element found, compare type_infos
if (noncommutative_element->rest.return_type_tinfo() != i->rest.return_type_tinfo()) {
- // diffent types -> mul is ncc
- return return_types::noncommutative_composite;
+ // different types -> mul is ncc
+ return return_types::noncommutative_composite;
}
}
++i;
return all_commutative ? return_types::commutative : return_types::noncommutative;
}
-unsigned mul::return_type_tinfo() const
+tinfo_t mul::return_type_tinfo() const
{
if (seq.empty())
- return tinfo_key; // mul without factors: should not happen
+ return this; // mul without factors: should not happen
// return type_info of first noncommutative element
epvector::const_iterator i = seq.begin(), end = seq.end();
++i;
}
// no noncommutative element found, should not happen
- return tinfo_key;
+ return this;
}
ex mul::thisexpairseq(const epvector & v, const ex & oc) const