From: Christian Bauer Date: Fri, 11 Jul 2003 19:28:43 +0000 (+0000) Subject: subs() and normal() use maps instead of lists, resulting in a huge performance X-Git-Tag: release_1-0-15~27 X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=commitdiff_plain;h=5ef801553eb39aed7bd2df9dd1aff9d752c3ea9d subs() and normal() use maps instead of lists, resulting in a huge performance boost for subs() --- diff --git a/ginac/add.h b/ginac/add.h index f2a94ed4..20faea8b 100644 --- a/ginac/add.h +++ b/ginac/add.h @@ -54,7 +54,7 @@ public: ex eval(int level=0) const; ex evalm() const; ex series(const relational & r, int order, unsigned options = 0) const; - ex normal(lst &sym_lst, lst &repl_lst, int level=0) const; + ex normal(exmap & repl, int level=0) const; numeric integer_content() const; ex smod(const numeric &xi) const; numeric max_coefficient() const; diff --git a/ginac/basic.cpp b/ginac/basic.cpp index 595d6450..a296cf9a 100644 --- a/ginac/basic.cpp +++ b/ginac/basic.cpp @@ -524,22 +524,19 @@ bool basic::match(const ex & pattern, lst & repl_lst) const } /** Helper function for subs(). Does not recurse into subexpressions. */ -ex basic::subs_one_level(const lst & ls, const lst & lr, unsigned options) const +ex basic::subs_one_level(const exmap & m, unsigned options) const { - GINAC_ASSERT(ls.nops() == lr.nops()); - - lst::const_iterator its, itr; + exmap::const_iterator it; if (options & subs_options::subs_no_pattern) { - for (its = ls.begin(), itr = lr.begin(); its != ls.end(); ++its, ++itr) { - if (is_equal(ex_to(*its))) - return *itr; - } + it = m.find(*this); + if (it != m.end()) + return it->second; } else { - for (its = ls.begin(), itr = lr.begin(); its != ls.end(); ++its, ++itr) { + for (it = m.begin(); it != m.end(); ++it) { lst repl_lst; - if (match(ex_to(*its), repl_lst)) - return itr->subs(repl_lst, options | subs_options::subs_no_pattern); // avoid infinite recursion when re-substituting the wildcards + if (match(ex_to(it->first), repl_lst)) + return it->second.subs(repl_lst, options | subs_options::subs_no_pattern); // avoid infinite recursion when re-substituting the wildcards } } @@ -548,7 +545,7 @@ ex basic::subs_one_level(const lst & ls, const lst & lr, unsigned options) const /** Substitute a set of objects by arbitrary expressions. The ex returned * will already be evaluated. */ -ex basic::subs(const lst & ls, const lst & lr, unsigned options) const +ex basic::subs(const exmap & m, unsigned options) const { size_t num = nops(); if (num) { @@ -556,7 +553,7 @@ ex basic::subs(const lst & ls, const lst & lr, unsigned options) const // Substitute in subexpressions for (size_t i=0; ilet_op(i) = op(i).subs(ls, lr, options); + copy->let_op(i) = op(i).subs(m, options); // Perform substitutions on the new object as a whole - return copy->subs_one_level(ls, lr, options); + return copy->subs_one_level(m, options); } } } // Nothing changed or no subexpressions - return subs_one_level(ls, lr, options); + return subs_one_level(m, options); } /** Default interface of nth derivative ex::diff(s, n). It should be called @@ -737,35 +734,6 @@ ex basic::expand(unsigned options) const // public -/** Substitute objects in an expression (syntactic substitution) and return - * the result as a new expression. There are two valid types of - * replacement arguments: 1) a relational like object==ex and 2) a list of - * relationals lst(object1==ex1,object2==ex2,...), which is converted to - * subs(lst(object1,object2,...),lst(ex1,ex2,...)). */ -ex basic::subs(const ex & e, unsigned options) const -{ - if (e.info(info_flags::relation_equal)) { - return subs(lst(e.lhs()), lst(e.rhs()), options); - } - if (!e.info(info_flags::list)) { - throw(std::invalid_argument("basic::subs(ex): argument must be a list")); - } - - // Split list into two - lst ls; - lst lr; - GINAC_ASSERT(is_a(e)); - for (lst::const_iterator it = ex_to(e).begin(); it != ex_to(e).end(); ++it) { - ex r = *it; - 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)); - lr.append(r.op(1)); - } - return subs(ls, lr, options); -} - /** Compare objects syntactically to establish canonical ordering. * All compare functions return: -1 for *this less than other, 0 equal, * 1 greater. */ diff --git a/ginac/basic.h b/ginac/basic.h index a68c2eee..a5af3236 100644 --- a/ginac/basic.h +++ b/ginac/basic.h @@ -25,6 +25,7 @@ #include // for size_t #include +#include // CINT needs to work properly with #include @@ -45,6 +46,7 @@ class print_context; template class ptr; typedef std::vector exvector; +typedef std::map exmap; /** Function object for map(). */ @@ -135,7 +137,7 @@ protected: public: // substitutions - virtual ex subs(const lst & ls, const lst & lr, unsigned options = 0) const; + virtual ex subs(const exmap & m, unsigned options = 0) const; // function mapping virtual ex map(map_function & f) const; @@ -163,7 +165,7 @@ public: virtual ex series(const relational & r, int order, unsigned options = 0) const; // rational functions - virtual ex normal(lst &sym_lst, lst &repl_lst, int level = 0) const; + virtual ex normal(exmap & repl, int level = 0) const; virtual ex to_rational(lst &repl_lst) const; virtual ex to_polynomial(lst &repl_lst) const; @@ -190,8 +192,7 @@ protected: // functions that should be called from class ex only // non-virtual functions in this class public: - ex subs(const ex & e, unsigned options = 0) const; - ex subs_one_level(const lst & ls, const lst & lr, unsigned options) const; + ex subs_one_level(const exmap & m, unsigned options) const; ex diff(const symbol & s, unsigned nth = 1) const; int compare(const basic & other) const; bool is_equal(const basic & other) const; diff --git a/ginac/container.h b/ginac/container.h index 135adb96..9a40f2ed 100644 --- a/ginac/container.h +++ b/ginac/container.h @@ -275,7 +275,7 @@ public: ex op(size_t i) const; ex & let_op(size_t i); ex eval(int level = 0) const; - ex subs(const lst & ls, const lst & lr, unsigned options = 0) const; + ex subs(const exmap & m, unsigned options = 0) const; protected: bool is_equal_same_type(const basic & other) const; @@ -328,7 +328,7 @@ public: protected: STLT evalchildren(int level) const; - STLT *subschildren(const lst & ls, const lst & lr, unsigned options = 0) const; + STLT *subschildren(const exmap & m, unsigned options = 0) const; }; /** Default constructor */ @@ -424,13 +424,13 @@ ex container::eval(int level) const } template