X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Fbasic.cpp;h=e8c893ba26dd59a963e00fd1056daf34f4f47bf8;hp=38219dcd029274b1d82ad733bccb13f4ffa339ba;hb=a377cee53b71348235ec36f83afeced7e10288a8;hpb=5a8b8e3c4d882249db35b679ce3144a59a7012e8 diff --git a/ginac/basic.cpp b/ginac/basic.cpp index 38219dcd..e8c893ba 100644 --- a/ginac/basic.cpp +++ b/ginac/basic.cpp @@ -3,7 +3,7 @@ * Implementation of GiNaC's ABC. */ /* - * GiNaC Copyright (C) 1999-2006 Johannes Gutenberg University Mainz, Germany + * GiNaC Copyright (C) 1999-2008 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 @@ -30,6 +30,7 @@ #include "ex.h" #include "numeric.h" #include "power.h" +#include "add.h" #include "symbol.h" #include "lst.h" #include "ncmul.h" @@ -38,6 +39,7 @@ #include "wildcard.h" #include "archive.h" #include "utils.h" +#include "inifcns.h" namespace GiNaC { @@ -288,7 +290,7 @@ ex & basic::operator[](size_t i) * but e.has(x+y) is false. */ bool basic::has(const ex & pattern, unsigned options) const { - lst repl_lst; + exmap repl_lst; if (match(pattern, repl_lst)) return true; for (size_t i=0; i(var)); +} + /** Return degree of highest power in object s. */ int basic::degree(const ex & s) const { @@ -362,56 +370,32 @@ ex basic::collect(const ex & s, bool distributed) const else if (distributed) { - // Get lower/upper degree of all symbols in list - size_t num = s.nops(); - struct sym_info { - ex sym; - int ldeg, deg; - int cnt; // current degree, 'counter' - ex coeff; // coefficient for degree 'cnt' - }; - sym_info *si = new sym_info[num]; - ex c = *this; - for (size_t i=0; ildegree(si[i].sym); - si[i].deg = this->degree(si[i].sym); - c = si[i].coeff = c.coeff(si[i].sym, si[i].cnt); - } - - while (true) { - - // Calculate coeff*x1^c1*...*xn^cn - ex y = _ex1; - for (size_t i=0; iexpand(); + if (! is_a(x)) + return x; + const lst& l(ex_to(s)); + + exmap cmap; + cmap[_ex1] = _ex0; + for (const_iterator xi=x.begin(); xi!=x.end(); ++xi) { + ex key = _ex1; + ex pre_coeff = *xi; + for (lst::const_iterator li=l.begin(); li!=l.end(); ++li) { + int cexp = pre_coeff.degree(*li); + pre_coeff = pre_coeff.coeff(*li, cexp); + key *= pow(*li, cexp); } + exmap::iterator ci = cmap.find(key); + if (ci != cmap.end()) + ci->second += pre_coeff; + else + cmap.insert(exmap::value_type(key, pre_coeff)); } -done: delete[] si; + exvector resv; + for (exmap::const_iterator mi=cmap.begin(); mi != cmap.end(); ++mi) + resv.push_back((mi->first)*(mi->second)); + return (new add(resv))->setflag(status_flags::dynallocated); } else { @@ -550,9 +534,9 @@ bool basic::contract_with(exvector::iterator self, exvector::iterator other, exv } /** Check whether the expression matches a given pattern. For every wildcard - * object in the pattern, an expression of the form "wildcard == matching_expression" - * is added to repl_lst. */ -bool basic::match(const ex & pattern, lst & repl_lst) const + * object in the pattern, a pair with the wildcard as a key and matching + * expression as a value is added to repl_lst. */ +bool basic::match(const ex & pattern, exmap& repl_lst) const { /* Sweet sweet shapes, sweet sweet shapes, @@ -575,11 +559,11 @@ bool basic::match(const ex & pattern, lst & repl_lst) const // Wildcard matches anything, but check whether we already have found // a match for that wildcard first (if so, the earlier match must be // the same expression) - for (lst::const_iterator it = repl_lst.begin(); it != repl_lst.end(); ++it) { - if (it->op(0).is_equal(pattern)) - return is_equal(ex_to(it->op(1))); + for (exmap::const_iterator it = repl_lst.begin(); it != repl_lst.end(); ++it) { + if (it->first.is_equal(pattern)) + return is_equal(ex_to(it->second)); } - repl_lst.append(pattern == *this); + repl_lst[pattern] = *this; return true; } else { @@ -601,12 +585,18 @@ bool basic::match(const ex & pattern, lst & repl_lst) const if (!match_same_type(ex_to(pattern))) return false; + // Even if the expression does not match the pattern, some of + // its subexpressions could match it. For example, x^5*y^(-1) + // does not match the pattern $0^5, but its subexpression x^5 + // does. So, save repl_lst in order to not add bogus entries. + exmap tmp_repl = repl_lst; // Otherwise the subexpressions must match one-to-one for (size_t i=0; i(it->first), repl_lst)) - return it->second.subs(repl_lst, options | subs_options::no_pattern); // avoid infinite recursion when re-substituting the wildcards + return it->second.subs(repl_lst, options | subs_options::no_pattern); + // avoid infinite recursion when re-substituting the wildcards } } @@ -705,6 +696,16 @@ ex basic::conjugate() const return *this; } +ex basic::real_part() const +{ + return real_part_function(*this).hold(); +} + +ex basic::imag_part() const +{ + return imag_part_function(*this).hold(); +} + ex basic::eval_ncmul(const exvector & v) const { return hold_ncmul(v); @@ -775,9 +776,9 @@ unsigned basic::return_type() const return return_types::commutative; } -const basic* basic::return_type_tinfo() const +tinfo_t basic::return_type_tinfo() const { - return this; + return tinfo_key; } /** Compute the hash value of an object and if it makes sense to store it in