Make .eval() evaluate top-level only.
authorRichard Kreckel <kreckel@ginac.de>
Wed, 16 Dec 2015 20:22:36 +0000 (21:22 +0100)
committerRichard Kreckel <kreckel@ginac.de>
Wed, 16 Dec 2015 20:22:36 +0000 (21:22 +0100)
With the previous patch, some old workarounds have become unnecessary:
If all expressions are evaluated, any object which is an aggregate of
expressions will only ever have to evaluate the top level. As such, it
has become pointless to evaluate child objects of an expression prior
to doing its own term-rewriting. This patch removes the evaluation of
children from all GiNaC objects. It also removes the now superfluous
parameter 'level' of the eval methods.

41 files changed:
check/exam_inifcns_nstdsums.cpp
check/exam_paranoia.cpp
check/exam_structure.cpp
doc/tutorial/ginac.texi
ginac/add.cpp
ginac/add.h
ginac/basic.cpp
ginac/basic.h
ginac/container.h
ginac/ex.cpp
ginac/ex.h
ginac/expairseq.cpp
ginac/expairseq.h
ginac/factor.cpp
ginac/fderivative.cpp
ginac/fderivative.h
ginac/function.cppy
ginac/function.hppy
ginac/indexed.cpp
ginac/indexed.h
ginac/inifcns_nstdsums.cpp
ginac/integral.cpp
ginac/integral.h
ginac/matrix.cpp
ginac/matrix.h
ginac/mul.cpp
ginac/mul.h
ginac/ncmul.cpp
ginac/ncmul.h
ginac/normal.cpp
ginac/numeric.cpp
ginac/numeric.h
ginac/power.cpp
ginac/power.h
ginac/pseries.cpp
ginac/pseries.h
ginac/relational.cpp
ginac/relational.h
ginac/structure.h
ginac/symbol.h
ginsh/ginsh_parser.ypp

index 6e4d846a1277bb31ab760da2d055691a68b6a36f..edba77698466a1f6cc3b743bbd1664362a8735d0 100644 (file)
@@ -146,7 +146,7 @@ static unsigned inifcns_test_HLi()
        res.append(H(lst{-2,1,3},numeric(1)/3).hold() - -Li(lst{2,1,3},lst{-numeric(1)/3,-1,1}).hold());
        res.append(H(lst{-2,1,3},numeric(98)/100).hold() - -Li(lst{2,1,3},lst{-numeric(98)/100,-1,1}).hold());
        res.append(H(lst{-2,1,3},numeric(245)/100).hold() - -Li(lst{2,1,3},lst{-numeric(245)/100,-1,1}).hold());
        res.append(H(lst{-2,1,3},numeric(1)/3).hold() - -Li(lst{2,1,3},lst{-numeric(1)/3,-1,1}).hold());
        res.append(H(lst{-2,1,3},numeric(98)/100).hold() - -Li(lst{2,1,3},lst{-numeric(98)/100,-1,1}).hold());
        res.append(H(lst{-2,1,3},numeric(245)/100).hold() - -Li(lst{2,1,3},lst{-numeric(245)/100,-1,1}).hold());
-       res.append(H(lst{-3,1,-2,0,0},numeric(3)/10).hold() - convert_H_to_Li(lst{-3,1,-2,0,0},numeric(3)/10).eval());
+       res.append(H(lst{-3,1,-2,0,0},numeric(3)/10).hold() - convert_H_to_Li(lst{-3,1,-2,0,0},numeric(3)/10));
        
        for (lst::const_iterator it = res.begin(); it != res.end(); it++) {
                ex diff = abs((*it).evalf());
        
        for (lst::const_iterator it = res.begin(); it != res.end(); it++) {
                ex diff = abs((*it).evalf());
index 6ab452baacea520b1ccf6be6f147b55665c97399..ad7ee8d25facc53da8d7022113da134c3f8cb986 100644 (file)
@@ -73,23 +73,10 @@ static unsigned exam_paranoia2()
        f = e*y;
        g = f - e*y;
 
        f = e*y;
        g = f - e*y;
 
-       // After .expand(), g should be zero:
-       if (!g.expand().is_zero()) {
-               clog << "e = (x + z*x); f = e*y; expand(f - e*y) erroneously returned "
-                    << g.expand() << endl;
-               ++result;
-       }
        // After .eval(), g should be zero:
        // After .eval(), g should be zero:
-       if (!g.eval().is_zero()) {
-               clog << "e = (x + z*x); f = e*y; eval(f - e*y) erroneously returned "
-                    << g.eval() << endl;
-               ++result;
-       }
-       // This actually worked already back in April 1999.
-       // But we are *very* paranoic!
-       if (!g.expand().eval().is_zero()) {
-               clog << "e = (x + z*x); f = e*y; eval(expand(f - e*y)) erroneously returned "
-                    << g.expand().eval() << endl;
+       if (!g.is_zero()) {
+               clog << "e = (x + z*x); f = e*y; g = (f - e*y) erroneously returned g == "
+                    << g << endl;
                ++result;
        }
 
                ++result;
        }
 
@@ -113,16 +100,6 @@ static unsigned exam_paranoia3()
                     << f << endl;
                ++result;
        }
                     << f << endl;
                ++result;
        }
-       if (!f.eval().is_equal(y)) {
-               clog << "e = x*y - y; eval(e.subs(x == 2)) erroneously returned "
-                    << f.eval() << endl;
-               ++result;
-       }
-       if (!f.expand().is_equal(y)) {
-               clog << "e = x*y - y; expand(e.subs(x == 2)) erroneously returned "
-                    << f.expand() << endl;
-               ++result;
-       }
 
        return result;
 }
 
        return result;
 }
@@ -143,11 +120,6 @@ static unsigned exam_paranoia4()
                     << g << endl;
                ++result;
        }
                     << g << endl;
                ++result;
        }
-       if (!g.is_zero()) {
-               clog << "e = pow(x,2) + x + 1; f = pow(x,2) + x + 1; g = e-f; g.eval() erroneously returned "
-                    << g.eval() << endl;
-               ++result;
-       }
 
        return result;
 }
 
        return result;
 }
@@ -264,7 +236,7 @@ static unsigned exam_paranoia10()
        ex r;
        
        try {
        ex r;
        
        try {
-               r = pow(b,e).eval();
+               r = pow(b, e);
                if (!(r-2*sqrt(ex(2))).is_zero()) {
                        clog << "2^(3/2) erroneously returned " << r << " instead of 2*sqrt(2)" << endl;
                        ++result;
                if (!(r-2*sqrt(ex(2))).is_zero()) {
                        clog << "2^(3/2) erroneously returned " << r << " instead of 2*sqrt(2)" << endl;
                        ++result;
index 56f205ec7867a5e078e193742bc0796d73d3754a..bc5bc837ce70d45ffd3974df2d84d8acc9dee6e5 100644 (file)
@@ -58,7 +58,7 @@ template <> void sprod::print(const print_context & c, unsigned level) const
        c.s << "<" << sp.left << "|" << sp.right << ">";
 }
 
        c.s << "<" << sp.left << "|" << sp.right << ">";
 }
 
-template <> ex sprod::eval(int level) const
+template <> ex sprod::eval() const
 {
        // symmetric scalar product
        const sprod_s & sp = get_struct();
 {
        // symmetric scalar product
        const sprod_s & sp = get_struct();
index 0d86eeee4d673b48d20c210989cb3a498165b802..fd5550fb60bcacbfa59b40fe32b7817f810efcfb 100644 (file)
@@ -838,8 +838,8 @@ some immediate simplifications.
 Internally, the anonymous evaluator in GiNaC is implemented by the methods
 
 @example
 Internally, the anonymous evaluator in GiNaC is implemented by the methods
 
 @example
-ex ex::eval(int level = 0) const;
-ex basic::eval(int level = 0) const;
+ex ex::eval() const;
+ex basic::eval() const;
 @end example
 
 but unless you are extending GiNaC with your own classes or functions, there
 @end example
 
 but unless you are extending GiNaC with your own classes or functions, there
@@ -8241,11 +8241,11 @@ class mystring : public basic
 @{
     ...
 public:
 @{
     ...
 public:
-    ex eval(int level = 0) const;
+    ex eval() const override;
     ...
 @};
 
     ...
 @};
 
-ex mystring::eval(int level) const
+ex mystring::eval() const
 @{
     string new_str;
     for (size_t i=0; i<str.length(); i++) @{
 @{
     string new_str;
     for (size_t i=0; i<str.length(); i++) @{
@@ -8258,19 +8258,19 @@ ex mystring::eval(int level) const
 
     if (new_str.length() == 0)
         return 0;
 
     if (new_str.length() == 0)
         return 0;
-    else
-        return mystring(new_str).hold();
+
+    return mystring(new_str).hold();
 @}
 @end example
 
 @}
 @end example
 
-The @code{level} argument is used to limit the recursion depth of the
-evaluation.  We don't have any subexpressions in the @code{mystring}
-class so we are not concerned with this.  If we had, we would call the
-@code{eval()} functions of the subexpressions with @code{level - 1} as
-the argument if @code{level != 1}.  The @code{hold()} member function
-sets a flag in the object that prevents further evaluation.  Otherwise
-we might end up in an endless loop.  When you want to return the object
-unmodified, use @code{return this->hold();}.
+The @code{hold()} member function sets a flag in the object that prevents
+further evaluation.  Otherwise we might end up in an endless loop.  When you
+want to return the object unmodified, use @code{return this->hold();}.
+
+If our class had subobjects, we would have to evaluate them first (unless
+they are all of type @code{ex}, which are automatically evaluated). We don't
+have any subexpressions in the @code{mystring} class, so we are not concerned
+with this.
 
 Let's confirm that it works:
 
 
 Let's confirm that it works:
 
@@ -8293,8 +8293,8 @@ required but will make operations with objects of the class more efficient:
 @cindex @code{calchash()}
 @cindex @code{is_equal_same_type()}
 @example
 @cindex @code{calchash()}
 @cindex @code{is_equal_same_type()}
 @example
-unsigned calchash() const;
-bool is_equal_same_type(const basic & other) const;
+unsigned calchash() const override;
+bool is_equal_same_type(const basic & other) const override;
 @end example
 
 The @code{calchash()} method returns an @code{unsigned} hash value for the
 @end example
 
 The @code{calchash()} method returns an @code{unsigned} hash value for the
@@ -8315,10 +8315,10 @@ For a real algebraic class, there are probably some more functions that you
 might want to provide:
 
 @example
 might want to provide:
 
 @example
-bool info(unsigned inf) const;
-ex evalf(int level = 0) const;
-ex series(const relational & r, int order, unsigned options = 0) const;
-ex derivative(const symbol & s) const;
+bool info(unsigned inf) const override;
+ex evalf(int level = 0) const override;
+ex series(const relational & r, int order, unsigned options = 0) const override;
+ex derivative(const symbol & s) const override;
 @end example
 
 If your class stores sub-expressions (see the scalar product example in the
 @end example
 
 If your class stores sub-expressions (see the scalar product example in the
@@ -8326,11 +8326,11 @@ previous section) you will probably want to override
 
 @cindex @code{let_op()}
 @example
 
 @cindex @code{let_op()}
 @example
-size_t nops() cont;
-ex op(size_t i) const;
-ex & let_op(size_t i);
-ex subs(const lst & ls, const lst & lr, unsigned options = 0) const;
-ex map(map_function & f) const;
+size_t nops() const override;
+ex op(size_t i) const override;
+ex & let_op(size_t i) override;
+ex subs(const lst & ls, const lst & lr, unsigned options = 0) const override;
+ex map(map_function & f) const override;
 @end example
 
 @code{let_op()} is a variant of @code{op()} that allows write access. The
 @end example
 
 @code{let_op()} is a variant of @code{op()} that allows write access. The
index ed58730941a3c9d062475ef175b44c023010187d..2a2e2f8310fa56217c4e52934f0399d76f7b3108 100644 (file)
@@ -326,17 +326,16 @@ ex add::coeff(const ex & s, int n) const
  *  an expression that contain a plain number.
  *  - +(;c) -> c
  *  - +(x;0) -> x
  *  an expression that contain a plain number.
  *  - +(;c) -> c
  *  - +(x;0) -> x
- *
- *  @param level cut-off in recursive evaluation */
-ex add::eval(int level) const
+ */
+ex add::eval() const
 {
 {
-       if ((level == 1) && (flags & status_flags::evaluated)) {
+       if (flags & status_flags::evaluated) {
                GINAC_ASSERT(seq.size()>0);
                GINAC_ASSERT(seq.size()>1 || !overall_coeff.is_zero());
                return *this;
        }
 
                GINAC_ASSERT(seq.size()>0);
                GINAC_ASSERT(seq.size()>1 || !overall_coeff.is_zero());
                return *this;
        }
 
-       const epvector evaled = evalchildren(level);
+       const epvector evaled = evalchildren();
        if (unlikely(!evaled.empty())) {
                // start over evaluating a new object
                return dynallocate<add>(std::move(evaled), overall_coeff);
        if (unlikely(!evaled.empty())) {
                // start over evaluating a new object
                return dynallocate<add>(std::move(evaled), overall_coeff);
index 659692b9c8402c092b00a1e5c411ac8ed1bbf4bd..427615769b3210bbb7d11d71b6dff41b754feb7c 100644 (file)
@@ -51,7 +51,7 @@ public:
        int degree(const ex & s) const override;
        int ldegree(const ex & s) const override;
        ex coeff(const ex & s, int n=1) const override;
        int degree(const ex & s) const override;
        int ldegree(const ex & s) const override;
        ex coeff(const ex & s, int n=1) const override;
-       ex eval(int level=0) const override;
+       ex eval() const override;
        ex evalm() const override;
        ex series(const relational & r, int order, unsigned options = 0) const override;
        ex normal(exmap & repl, exmap & rev_lookup, int level=0) const override;
        ex evalm() const override;
        ex series(const relational & r, int order, unsigned options = 0) const override;
        ex normal(exmap & repl, exmap & rev_lookup, int level=0) const override;
index 96cfd14c46fcd7458aff878993b7496f196950c3..a2be1ca51ce4c0922ef3a361bd5fdab0dcbbb360 100644 (file)
@@ -410,7 +410,7 @@ ex basic::collect(const ex & s, bool distributed) const
 }
 
 /** Perform automatic non-interruptive term rewriting rules. */
 }
 
 /** Perform automatic non-interruptive term rewriting rules. */
-ex basic::eval(int level) const
+ex basic::eval() const
 {
        // There is nothing to do for basic objects:
        return hold();
 {
        // There is nothing to do for basic objects:
        return hold();
index a8062c15c81d4460e86f571a4ecb636d3c9df5f0..0cec003add27a8851ba136d3f5f2dae464654c19 100644 (file)
@@ -135,7 +135,7 @@ public: // only const functions please (may break reference counting)
        }
 
        // evaluation
        }
 
        // evaluation
-       virtual ex eval(int level = 0) const;
+       virtual ex eval() const;
        virtual ex evalf(int level = 0) const;
        virtual ex evalm() const;
        virtual ex eval_integ() const;
        virtual ex evalf(int level = 0) const;
        virtual ex evalm() const;
        virtual ex eval_integ() const;
index 04ab31d1110ce64f1af2946c4e7ac4dc51215dce..0881095a1ebe5ebe05e59be0932e3f04bcf2b8d6 100644 (file)
@@ -205,7 +205,6 @@ public:
        size_t nops() const override { return this->seq.size(); }
        ex op(size_t i) const override;
        ex & let_op(size_t i) override;
        size_t nops() const override { return this->seq.size(); }
        ex op(size_t i) const override;
        ex & let_op(size_t i) override;
-       ex eval(int level = 0) const override;
        ex subs(const exmap & m, unsigned options = 0) const override;
 
        void read_archive(const archive_node &n, lst &sym_lst) override
        ex subs(const exmap & m, unsigned options = 0) const override;
 
        void read_archive(const archive_node &n, lst &sym_lst) override
@@ -336,7 +335,6 @@ protected:
        void do_print_tree(const print_tree & c, unsigned level) const;
        void do_print_python(const print_python & c, unsigned level) const;
        void do_print_python_repr(const print_python_repr & c, unsigned level) const;
        void do_print_tree(const print_tree & c, unsigned level) const;
        void do_print_python(const print_python & c, unsigned level) const;
        void do_print_python_repr(const print_python_repr & c, unsigned level) const;
-       STLT evalchildren(int level) const;
        STLT subschildren(const exmap & m, unsigned options = 0) const;
 };
 
        STLT subschildren(const exmap & m, unsigned options = 0) const;
 };
 
@@ -482,15 +480,6 @@ ex & container<C>::let_op(size_t i)
        return *it;
 }
 
        return *it;
 }
 
-template <template <class T, class = std::allocator<T>> class C>
-ex container<C>::eval(int level) const
-{
-       if (level == 1)
-               return hold();
-       else
-               return thiscontainer(evalchildren(level));
-}
-
 template <template <class T, class = std::allocator<T>> class C>
 ex container<C>::subs(const exmap & m, unsigned options) const
 {
 template <template <class T, class = std::allocator<T>> class C>
 ex container<C>::subs(const exmap & m, unsigned options) const
 {
@@ -649,27 +638,6 @@ void container<C>::printseq(const print_context & c, char openbracket, char deli
                c.s << closebracket;
 }
 
                c.s << closebracket;
 }
 
-template <template <class T, class = std::allocator<T>> class C>
-typename container<C>::STLT container<C>::evalchildren(int level) const
-{
-       if (level == 1)
-               return this->seq;
-       else if (level == -max_recursion_level)
-               throw std::runtime_error("max recursion level reached");
-
-       STLT s;
-       this->reserve(s, this->seq.size());
-
-       --level;
-       const_iterator it = this->seq.begin(), itend = this->seq.end();
-       while (it != itend) {
-               s.push_back(it->eval(level));
-               ++it;
-       }
-
-       return s;
-}
-
 template <template <class T, class = std::allocator<T>> class C>
 typename container<C>::STLT container<C>::subschildren(const exmap & m, unsigned options) const
 {
 template <template <class T, class = std::allocator<T>> class C>
 typename container<C>::STLT container<C>::subschildren(const exmap & m, unsigned options) const
 {
index 7bd8410b6d4f50dc2751557bb41dcb3471efa51c..c403c7f6899f191e6db24f3da83b2af60a5da981 100644 (file)
@@ -306,7 +306,7 @@ ptr<basic> ex::construct_from_basic(const basic & other)
                // apply eval() once more. The recursion stops when eval() calls
                // hold() or returns an object that already has its "evaluated"
                // flag set, such as a symbol or a numeric.
                // apply eval() once more. The recursion stops when eval() calls
                // hold() or returns an object that already has its "evaluated"
                // flag set, such as a symbol or a numeric.
-               const ex & tmpex = other.eval(1);
+               const ex & tmpex = other.eval();
 
                // Eventually, the eval() recursion goes through the "else" branch
                // below, which assures that the object pointed to by tmpex.bp is
 
                // Eventually, the eval() recursion goes through the "else" branch
                // below, which assures that the object pointed to by tmpex.bp is
index 343fa367c8614bba081b4535639b8652b953e322..6fd45c9d24356bc2af5a2b6458adb719a383c25c 100644 (file)
@@ -115,7 +115,7 @@ public:
        const_postorder_iterator postorder_end() const noexcept;
 
        // evaluation
        const_postorder_iterator postorder_end() const noexcept;
 
        // evaluation
-       ex eval(int level = 0) const { return bp->eval(level); }
+       ex eval() const { return bp->eval(); }
        ex evalf(int level = 0) const { return bp->evalf(level); }
        ex evalm() const { return bp->evalm(); }
        ex eval_ncmul(const exvector & v) const { return bp->eval_ncmul(v); }
        ex evalf(int level = 0) const { return bp->evalf(level); }
        ex evalm() const { return bp->evalm(); }
        ex eval_ncmul(const exvector & v) const { return bp->eval_ncmul(v); }
@@ -755,8 +755,8 @@ inline ex to_polynomial(const ex & thisex, lst & repl_lst)
 inline ex collect(const ex & thisex, const ex & s, bool distributed = false)
 { return thisex.collect(s, distributed); }
 
 inline ex collect(const ex & thisex, const ex & s, bool distributed = false)
 { return thisex.collect(s, distributed); }
 
-inline ex eval(const ex & thisex, int level = 0)
-{ return thisex.eval(level); }
+inline ex eval(const ex & thisex)
+{ return thisex.eval(); }
 
 inline ex evalf(const ex & thisex, int level = 0)
 { return thisex.evalf(level); }
 
 inline ex evalf(const ex & thisex, int level = 0)
 { return thisex.evalf(level); }
index 9ca4070934e41fd60ea9bc111153279c07fbe0d4..e99d21fe0061d64d2102c9dd1df966decc27bb2b 100644 (file)
@@ -239,12 +239,12 @@ ex expairseq::map(map_function &f) const
 }
 
 /** Perform coefficient-wise automatic term rewriting rules in this class. */
 }
 
 /** Perform coefficient-wise automatic term rewriting rules in this class. */
-ex expairseq::eval(int level) const
+ex expairseq::eval() const
 {
 {
-       if ((level==1) && (flags &status_flags::evaluated))
+       if (flags &status_flags::evaluated)
                return *this;
 
                return *this;
 
-       const epvector evaled = evalchildren(level);
+       const epvector evaled = evalchildren();
        if (!evaled.empty())
                return dynallocate<expairseq>(std::move(evaled), overall_coeff).setflag(status_flags::evaluated);
        else
        if (!evaled.empty())
                return dynallocate<expairseq>(std::move(evaled), overall_coeff).setflag(status_flags::evaluated);
        else
@@ -1048,15 +1048,11 @@ epvector expairseq::expandchildren(unsigned options) const
  *  @see expairseq::eval()
  *  @return epvector containing evaluated pairs, empty if no members
  *    had to be changed. */
  *  @see expairseq::eval()
  *  @return epvector containing evaluated pairs, empty if no members
  *    had to be changed. */
-epvector expairseq::evalchildren(int level) const
+epvector expairseq::evalchildren() const
 {
 {
-       if (level == -max_recursion_level)
-               throw(std::runtime_error("max recursion level reached"));
-
        auto cit = seq.begin(), last = seq.end();
        while (cit!=last) {
        auto cit = seq.begin(), last = seq.end();
        while (cit!=last) {
-               const ex evaled_rest = level==1 ? cit->rest : cit->rest.eval(level-1);
-               const expair evaled_pair = combine_ex_with_coeff_to_pair(evaled_rest, cit->coeff);
+               const expair evaled_pair = combine_ex_with_coeff_to_pair(cit->rest, cit->coeff);
                if (unlikely(!evaled_pair.is_equal(*cit))) {
 
                        // something changed: copy seq, eval and return it
                if (unlikely(!evaled_pair.is_equal(*cit))) {
 
                        // something changed: copy seq, eval and return it
@@ -1072,8 +1068,7 @@ epvector expairseq::evalchildren(int level) const
 
                        // copy rest
                        while (cit != last) {
 
                        // copy rest
                        while (cit != last) {
-                               const ex evaled_rest = level==1 ? cit->rest : cit->rest.eval(level-1);
-                               s.push_back(combine_ex_with_coeff_to_pair(evaled_rest, cit->coeff));
+                               s.push_back(combine_ex_with_coeff_to_pair(cit->rest, cit->coeff));
                                ++cit;
                        }
                        return s;
                                ++cit;
                        }
                        return s;
index d33ff332ef59f2a9bed880a90fa3d15b84454b1a..41b077d5097f11d968aaec72cc83974631ecec50 100644 (file)
@@ -64,7 +64,7 @@ public:
        size_t nops() const override;
        ex op(size_t i) const override;
        ex map(map_function & f) const override;
        size_t nops() const override;
        ex op(size_t i) const override;
        ex map(map_function & f) const override;
-       ex eval(int level=0) const override;
+       ex eval() const override;
        ex to_rational(exmap & repl) const override;
        ex to_polynomial(exmap & repl) const override;
        bool match(const ex & pattern, exmap& repl_lst) const override;
        ex to_rational(exmap & repl) const override;
        ex to_polynomial(exmap & repl) const override;
        bool match(const ex & pattern, exmap& repl_lst) const override;
@@ -119,7 +119,7 @@ protected:
        void combine_same_terms_sorted_seq();
        bool is_canonical() const;
        epvector expandchildren(unsigned options) const;
        void combine_same_terms_sorted_seq();
        bool is_canonical() const;
        epvector expandchildren(unsigned options) const;
-       epvector evalchildren(int level) const;
+       epvector evalchildren() const;
        epvector subschildren(const exmap & m, unsigned options = 0) const;
        
 // member variables
        epvector subschildren(const exmap & m, unsigned options = 0) const;
        
 // member variables
index e96dccfa81eded8468a390f455d0b2f9f54462da..30d7953be90c830baced6c4e92410cdab5e3f416 100644 (file)
@@ -2519,8 +2519,6 @@ struct apply_factor_map : public map_function {
                                        s2 += e.op(i);
                                }
                        }
                                        s2 += e.op(i);
                                }
                        }
-                       s1 = s1.eval();
-                       s2 = s2.eval();
                        return factor(s1, options) + s2.map(*this);
                }
                return e.map(*this);
                        return factor(s1, options) + s2.map(*this);
                }
                return e.map(*this);
index 4229d0ab4eff471739b6678132f254b7aaee3bc6..17817e108671ffd4bc612ee343d78937455e2c49 100644 (file)
@@ -139,13 +139,8 @@ void fderivative::do_print_tree(const print_tree & c, unsigned level) const
        c.s << std::string(level + c.delta_indent, ' ') << "=====" << std::endl;
 }
 
        c.s << std::string(level + c.delta_indent, ' ') << "=====" << std::endl;
 }
 
-ex fderivative::eval(int level) const
+ex fderivative::eval() const
 {
 {
-       if (level > 1) {
-               // first evaluate children, then we will end up here again
-               return fderivative(serial, parameter_set, evalchildren(level));
-       }
-
        // No parameters specified? Then return the function itself
        if (parameter_set.empty())
                return function(serial, seq);
        // No parameters specified? Then return the function itself
        if (parameter_set.empty())
                return function(serial, seq);
index a646eacfcb8d8b3753ac919ca66456c5cea22be2..643fafafd48322f0b85e34e70c5a865691dab30d 100644 (file)
@@ -60,7 +60,7 @@ public:
        // functions overriding virtual functions from base classes
 public:
        void print(const print_context & c, unsigned level = 0) const override;
        // functions overriding virtual functions from base classes
 public:
        void print(const print_context & c, unsigned level = 0) const override;
-       ex eval(int level = 0) const override;
+       ex eval() const override;
        ex evalf(int level = 0) const override;
        ex series(const relational & r, int order, unsigned options = 0) const override;
        ex thiscontainer(const exvector & v) const override;
        ex evalf(int level = 0) const override;
        ex series(const relational & r, int order, unsigned options = 0) const override;
        ex thiscontainer(const exvector & v) const override;
index 789ca056c2dfa9dcebd7e0d86801b7a59e518ee9..686a76e6386d610d4d2aa07493471b42054e2951 100644 (file)
@@ -362,17 +362,12 @@ next_context:
        }
 }
 
        }
 }
 
-ex function::eval(int level) const
+ex function::eval() const
 {
 {
-       if ((level == 1) && (flags & status_flags::evaluated)) {
+       if (flags & status_flags::evaluated) {
                return *this;
        }
 
                return *this;
        }
 
-       if (level>1) {
-               // first evaluate children, then we will end up here again
-               return function(serial,evalchildren(level));
-       }
-
        GINAC_ASSERT(serial<registered_functions().size());
        const function_options &opt = registered_functions()[serial];
 
        GINAC_ASSERT(serial<registered_functions().size());
        const function_options &opt = registered_functions()[serial];
 
index b54f41f3f4af2f8b56862b9faae172296ac26ac7..0f35100a4016e4347ae2421705c99cd1c0c9e4c5 100644 (file)
@@ -228,7 +228,7 @@ public:
        void print(const print_context & c, unsigned level = 0) const override;
        unsigned precedence() const override {return 70;}
        ex expand(unsigned options=0) const override;
        void print(const print_context & c, unsigned level = 0) const override;
        unsigned precedence() const override {return 70;}
        ex expand(unsigned options=0) const override;
-       ex eval(int level=0) const override;
+       ex eval() const override;
        ex evalf(int level=0) const override;
        ex eval_ncmul(const exvector & v) const override;
        unsigned calchash() const override;
        ex evalf(int level=0) const override;
        ex eval_ncmul(const exvector & v) const override;
        unsigned calchash() const override;
index ca4beff53f63d2b57761c4380ae68a9b89829b1c..357528a8b718223a0ca4d1824eb0d0a902bdee13 100644 (file)
@@ -260,12 +260,8 @@ int indexed::compare_same_type(const basic & other) const
        return inherited::compare_same_type(other);
 }
 
        return inherited::compare_same_type(other);
 }
 
-ex indexed::eval(int level) const
+ex indexed::eval() const
 {
 {
-       // First evaluate children, then we will end up here again
-       if (level > 1)
-               return indexed(ex_to<symmetry>(symtree), evalchildren(level));
-
        const ex &base = seq[0];
 
        // If the base object is 0, the whole object is 0
        const ex &base = seq[0];
 
        // If the base object is 0, the whole object is 0
index a04b74256dec063174d0988b0b21ac8ab61e5f8f..1917de43900b63cc6d91064f2f25fbc1e7628162 100644 (file)
@@ -145,7 +145,7 @@ public:
 public:
        unsigned precedence() const override {return 55;}
        bool info(unsigned inf) const override;
 public:
        unsigned precedence() const override {return 55;}
        bool info(unsigned inf) const override;
-       ex eval(int level = 0) const override;
+       ex eval() const override;
        ex real_part() const override;
        ex imag_part() const override;
        exvector get_free_indices() const override;
        ex real_part() const override;
        ex imag_part() const override;
        exvector get_free_indices() const override;
index 2a20792475724a9035d1036d7b2b8769090ae4db..82a0bbd87903b831d2f04ad3a8ccd5d8f6674261 100644 (file)
@@ -1136,7 +1136,7 @@ G_do_trafo(const std::vector<cln::cl_N>& x, const std::vector<int>& s,
        Gparameter pendint;
        ex result = G_transform(pendint, a, scale, gsyms, flag_trailing_zeros_only);
        // replace dummy symbols with their values
        Gparameter pendint;
        ex result = G_transform(pendint, a, scale, gsyms, flag_trailing_zeros_only);
        // replace dummy symbols with their values
-       result = result.eval().expand();
+       result = result.expand();
        result = result.subs(subslst).evalf();
        if (!is_a<numeric>(result))
                throw std::logic_error("G_do_trafo: G_transform returned non-numeric result");
        result = result.subs(subslst).evalf();
        if (!is_a<numeric>(result))
                throw std::logic_error("G_do_trafo: G_transform returned non-numeric result");
index 81e7adefcb3208f72af6e61746a1ec1ba239bd46..926125bbea4266b000ca4ce5849334e9ac9ae631 100644 (file)
@@ -140,28 +140,18 @@ int integral::compare_same_type(const basic & other) const
        return f.compare(o.f);
 }
 
        return f.compare(o.f);
 }
 
-ex integral::eval(int level) const
+ex integral::eval() const
 {
 {
-       if ((level==1) && (flags & status_flags::evaluated))
+       if (flags & status_flags::evaluated)
                return *this;
                return *this;
-       if (level == -max_recursion_level)
-               throw(std::runtime_error("max recursion level reached"));
 
 
-       ex eintvar = (level==1) ? x : x.eval(level-1);
-       ex ea      = (level==1) ? a : a.eval(level-1);
-       ex eb      = (level==1) ? b : b.eval(level-1);
-       ex ef      = (level==1) ? f : f.eval(level-1);
+       if (!f.has(x) && !haswild(f))
+               return b*f-a*f;
 
 
-       if (!ef.has(eintvar) && !haswild(ef))
-               return eb*ef-ea*ef;
-
-       if (ea==eb)
+       if (a==b)
                return _ex0;
 
                return _ex0;
 
-       if (are_ex_trivially_equal(eintvar,x) && are_ex_trivially_equal(ea,a) &&
-           are_ex_trivially_equal(eb,b) && are_ex_trivially_equal(ef,f))
-               return this->hold();
-       return dynallocate<integral>(eintvar, ea, eb, ef).setflag(status_flags::evaluated);
+       return this->hold();
 }
 
 ex integral::evalf(int level) const
 }
 
 ex integral::evalf(int level) const
index f76ac7fc35b893f2429e9bee57cf7e712d975f6a..b2be4b438bd419b9a282a64597cb06f9647056cc 100644 (file)
@@ -41,7 +41,7 @@ public:
        // functions overriding virtual functions from base classes
 public:
        unsigned precedence() const override {return 45;}
        // functions overriding virtual functions from base classes
 public:
        unsigned precedence() const override {return 45;}
-       ex eval(int level=0) const override;
+       ex eval() const override;
        ex evalf(int level=0) const override;
        int degree(const ex & s) const override;
        int ldegree(const ex & s) const override;
        ex evalf(int level=0) const override;
        int degree(const ex & s) const override;
        int ldegree(const ex & s) const override;
index 7d054cf1346c85b2346f1f9644ad9ae29bccd2c9..c842885f8103c0a2cc6530b6fc65b6b203197c56 100644 (file)
@@ -227,27 +227,6 @@ ex & matrix::let_op(size_t i)
        return m[i];
 }
 
        return m[i];
 }
 
-/** Evaluate matrix entry by entry. */
-ex matrix::eval(int level) const
-{
-       // check if we have to do anything at all
-       if ((level==1)&&(flags & status_flags::evaluated))
-               return *this;
-       
-       // emergency break
-       if (level == -max_recursion_level)
-               throw (std::runtime_error("matrix::eval(): recursion limit exceeded"));
-       
-       // eval() entry by entry
-       exvector m2(row*col);
-       --level;
-       for (unsigned r=0; r<row; ++r)
-               for (unsigned c=0; c<col; ++c)
-                       m2[r*col+c] = m[r*col+c].eval(level);
-       
-       return dynallocate<matrix>(row, col, std::move(m2)).setflag(status_flags::evaluated);
-}
-
 ex matrix::subs(const exmap & mp, unsigned options) const
 {
        exvector m2(row * col);
 ex matrix::subs(const exmap & mp, unsigned options) const
 {
        exvector m2(row * col);
index 988e257b0ddce7726e325038fd1ede00366917d9..5c665dd6fc8e7713a6e5cb49a9c90f12a489cc18 100644 (file)
@@ -111,7 +111,6 @@ public:
        size_t nops() const override;
        ex op(size_t i) const override;
        ex & let_op(size_t i) override;
        size_t nops() const override;
        ex op(size_t i) const override;
        ex & let_op(size_t i) override;
-       ex eval(int level=0) const override;
        ex evalm() const override {return *this;}
        ex subs(const exmap & m, unsigned options = 0) const override;
        ex eval_indexed(const basic & i) const override;
        ex evalm() const override {return *this;}
        ex subs(const exmap & m, unsigned options = 0) const override;
        ex eval_indexed(const basic & i) const override;
@@ -190,9 +189,6 @@ inline size_t nops(const matrix & m)
 inline ex expand(const matrix & m, unsigned options = 0)
 { return m.expand(options); }
 
 inline ex expand(const matrix & m, unsigned options = 0)
 { return m.expand(options); }
 
-inline ex eval(const matrix & m, int level = 0)
-{ return m.eval(level); }
-
 inline ex evalf(const matrix & m, int level = 0)
 { return m.evalf(level); }
 
 inline ex evalf(const matrix & m, int level = 0)
 { return m.evalf(level); }
 
index a83b771d91d8f40f842b67a7528e931037caf4e3..0a6fca40b7a06cb25749f80cae700c9bf5fb1b63 100644 (file)
@@ -464,17 +464,16 @@ ex mul::coeff(const ex & s, int n) const
  *  - *(+(x1,x2,...);c) -> *(+(*(x1,c),*(x2,c),...))
  *  - *(x;1) -> x
  *  - *(;c) -> c
  *  - *(+(x1,x2,...);c) -> *(+(*(x1,c),*(x2,c),...))
  *  - *(x;1) -> x
  *  - *(;c) -> c
- *
- *  @param level cut-off in recursive evaluation */
-ex mul::eval(int level) const
+ */
+ex mul::eval() const
 {
 {
-       if ((level == 1) && (flags & status_flags::evaluated)) {
+       if (flags & status_flags::evaluated) {
                GINAC_ASSERT(seq.size()>0);
                GINAC_ASSERT(seq.size()>1 || !overall_coeff.is_equal(_ex1));
                return *this;
        }
 
                GINAC_ASSERT(seq.size()>0);
                GINAC_ASSERT(seq.size()>1 || !overall_coeff.is_equal(_ex1));
                return *this;
        }
 
-       const epvector evaled = evalchildren(level);
+       const epvector evaled = evalchildren();
        if (unlikely(!evaled.empty())) {
                // start over evaluating a new object
                return dynallocate<mul>(std::move(evaled), overall_coeff);
        if (unlikely(!evaled.empty())) {
                // start over evaluating a new object
                return dynallocate<mul>(std::move(evaled), overall_coeff);
index 95eba3dc1bf9b8d7b1c2f17c3c9f48d18262ef8f..e689ddf14a53ee346b02d3851e7cce449e0213dc 100644 (file)
@@ -54,7 +54,7 @@ public:
        int ldegree(const ex & s) const override;
        ex coeff(const ex & s, int n = 1) const override;
        bool has(const ex & other, unsigned options = 0) const override;
        int ldegree(const ex & s) const override;
        ex coeff(const ex & s, int n = 1) const override;
        bool has(const ex & other, unsigned options = 0) const override;
-       ex eval(int level=0) const override;
+       ex eval() const override;
        ex evalf(int level=0) const override;
        ex real_part() const override;
        ex imag_part() const override;
        ex evalf(int level=0) const override;
        ex real_part() const override;
        ex imag_part() const override;
index c287a023248192da06a6a828cd072f00f4142459..b43ec9505c656e1be4e89dc232ddaa72d10f0ec2 100644 (file)
@@ -285,9 +285,8 @@ typedef std::vector<exvector> exvectorvector;
  *  - ncmul(...,c1,...,c2,...) -> *(c1,c2,ncmul(...))  (pull out commutative elements)
  *  - ncmul(x1,y1,x2,y2) -> *(ncmul(x1,x2),ncmul(y1,y2))  (collect elements of same type)
  *  - ncmul(x1,x2,x3,...) -> x::eval_ncmul(x1,x2,x3,...)
  *  - ncmul(...,c1,...,c2,...) -> *(c1,c2,ncmul(...))  (pull out commutative elements)
  *  - ncmul(x1,y1,x2,y2) -> *(ncmul(x1,x2),ncmul(y1,y2))  (collect elements of same type)
  *  - ncmul(x1,x2,x3,...) -> x::eval_ncmul(x1,x2,x3,...)
- *
- *  @param level cut-off in recursive evaluation */
-ex ncmul::eval(int level) const
+ */
+ex ncmul::eval() const
 {
        // The following additional rule would be nice, but produces a recursion,
        // which must be trapped by introducing a flag that the sub-ncmuls()
 {
        // The following additional rule would be nice, but produces a recursion,
        // which must be trapped by introducing a flag that the sub-ncmuls()
@@ -296,22 +295,20 @@ ex ncmul::eval(int level) const
        //                      ncmul(ncmul(x1,x2,...),X,ncmul(y1,y2,...)
        //                      (X noncommutative_composite)
 
        //                      ncmul(ncmul(x1,x2,...),X,ncmul(y1,y2,...)
        //                      (X noncommutative_composite)
 
-       if ((level==1) && (flags & status_flags::evaluated)) {
+       if (flags & status_flags::evaluated) {
                return *this;
        }
 
                return *this;
        }
 
-       exvector evaledseq=evalchildren(level);
-
        // ncmul(...,*(x1,x2),...,ncmul(x3,x4),...) ->
        //     ncmul(...,x1,x2,...,x3,x4,...)  (associativity)
        size_t factors = 0;
        // ncmul(...,*(x1,x2),...,ncmul(x3,x4),...) ->
        //     ncmul(...,x1,x2,...,x3,x4,...)  (associativity)
        size_t factors = 0;
-       for (auto & it : evaledseq)
+       for (auto & it : seq)
                factors += count_factors(it);
        
        exvector assocseq;
        assocseq.reserve(factors);
                factors += count_factors(it);
        
        exvector assocseq;
        assocseq.reserve(factors);
-       make_flat_inserter mf(evaledseq, true);
-       for (auto & it : evaledseq) {
+       make_flat_inserter mf(seq, true);
+       for (auto & it : seq) {
                ex factor = mf.handle_factor(it, 1);
                append_factors(assocseq, factor);
        }
                ex factor = mf.handle_factor(it, 1);
                append_factors(assocseq, factor);
        }
@@ -476,7 +473,7 @@ ex ncmul::conjugate() const
                --i;
                ev.push_back(i->conjugate());
        }
                --i;
                ev.push_back(i->conjugate());
        }
-       return dynallocate<ncmul>(std::move(ev)).eval();
+       return dynallocate<ncmul>(std::move(ev));
 }
 
 ex ncmul::real_part() const
 }
 
 ex ncmul::real_part() const
index 2233b8d7b3905aa1d998f3a365c1192bb2d9f30d..0ed54f797be5190fb83d0a1c8d3155fa6f1f27c4 100644 (file)
@@ -60,7 +60,7 @@ public:
        int ldegree(const ex & s) const override;
        ex expand(unsigned options=0) const override;
        ex coeff(const ex & s, int n=1) const override;
        int ldegree(const ex & s) const override;
        ex expand(unsigned options=0) const override;
        ex coeff(const ex & s, int n=1) const override;
-       ex eval(int level=0) const override;
+       ex eval() const override;
        ex evalm() const override;
        exvector get_free_indices() const override;
        ex thiscontainer(const exvector & v) const override;
        ex evalm() const override;
        exvector get_free_indices() const override;
        ex thiscontainer(const exvector & v) const override;
index b2e8d109013951385b17e551d31d405542282679..7968b9083b0b37fab38ff5da3f88b6350c16199c 100644 (file)
@@ -196,8 +196,8 @@ static void collect_symbols(const ex &e, sym_desc_vec &v)
  *  @param v  vector of sym_desc structs (filled in) */
 static void get_symbol_stats(const ex &a, const ex &b, sym_desc_vec &v)
 {
  *  @param v  vector of sym_desc structs (filled in) */
 static void get_symbol_stats(const ex &a, const ex &b, sym_desc_vec &v)
 {
-       collect_symbols(a.eval(), v);   // eval() to expand assigned symbols
-       collect_symbols(b.eval(), v);
+       collect_symbols(a, v);
+       collect_symbols(b, v);
        for (auto & it : v) {
                int deg_a = a.degree(it.sym);
                int deg_b = b.degree(it.sym);
        for (auto & it : v) {
                int deg_a = a.degree(it.sym);
                int deg_b = b.degree(it.sym);
index 2bb92653fd2fc079098e6af8c08b05bc61ae6c74..9b23214b05e4b0a0e8e9b6dd28fb819349d8f4b6 100644 (file)
@@ -775,10 +775,8 @@ bool numeric::has(const ex &other, unsigned options) const
 
 
 /** Evaluation of numbers doesn't do anything at all. */
 
 
 /** Evaluation of numbers doesn't do anything at all. */
-ex numeric::eval(int level) const
+ex numeric::eval() const
 {
 {
-       // Warning: if this is ever gonna do something, the ex ctors from all kinds
-       // of numbers should be checking for status_flags::evaluated.
        return this->hold();
 }
 
        return this->hold();
 }
 
index 4d3135d51ccd1eb355b06e0e39aa8570c4d58384..a22209ed71546672fdf65a657731673f8e25eca6 100644 (file)
@@ -103,7 +103,7 @@ public:
        int ldegree(const ex & s) const override;
        ex coeff(const ex & s, int n = 1) const override;
        bool has(const ex &other, unsigned options = 0) const override;
        int ldegree(const ex & s) const override;
        ex coeff(const ex & s, int n = 1) const override;
        bool has(const ex &other, unsigned options = 0) const override;
-       ex eval(int level = 0) const override;
+       ex eval() const override;
        ex evalf(int level = 0) const override;
        ex subs(const exmap & m, unsigned options = 0) const override { return subs_one_level(m, options); } // overwrites basic::subs() for performance reasons
        ex normal(exmap & repl, exmap & rev_lookup, int level = 0) const override;
        ex evalf(int level = 0) const override;
        ex subs(const exmap & m, unsigned options = 0) const override { return subs_one_level(m, options); } // overwrites basic::subs() for performance reasons
        ex normal(exmap & repl, exmap & rev_lookup, int level = 0) const override;
index afe2f1ef08fb5b34b79f3365d01bffe372ff9d73..c376009b5c416f5c2ec3d68e35e6c869b440602e 100644 (file)
@@ -373,42 +373,36 @@ ex power::coeff(const ex & s, int n) const
  *  - ^(*(x,y,z),c) -> *(x^c,y^c,z^c)  (if c integer)
  *  - ^(*(x,c1),c2) -> ^(x,c2)*c1^c2  (c1>0)
  *  - ^(*(x,c1),c2) -> ^(-x,c2)*c1^c2  (c1<0)
  *  - ^(*(x,y,z),c) -> *(x^c,y^c,z^c)  (if c integer)
  *  - ^(*(x,c1),c2) -> ^(x,c2)*c1^c2  (c1>0)
  *  - ^(*(x,c1),c2) -> ^(-x,c2)*c1^c2  (c1<0)
- *
- *  @param level cut-off in recursive evaluation */
-ex power::eval(int level) const
+ */
+ex power::eval() const
 {
 {
-       if ((level==1) && (flags & status_flags::evaluated))
+       if (flags & status_flags::evaluated)
                return *this;
                return *this;
-       else if (level == -max_recursion_level)
-               throw(std::runtime_error("max recursion level reached"));
-       
-       const ex & ebasis    = level==1 ? basis    : basis.eval(level-1);
-       const ex & eexponent = level==1 ? exponent : exponent.eval(level-1);
-       
+
        const numeric *num_basis = nullptr;
        const numeric *num_exponent = nullptr;
        const numeric *num_basis = nullptr;
        const numeric *num_exponent = nullptr;
-       
-       if (is_exactly_a<numeric>(ebasis)) {
-               num_basis = &ex_to<numeric>(ebasis);
+
+       if (is_exactly_a<numeric>(basis)) {
+               num_basis = &ex_to<numeric>(basis);
        }
        }
-       if (is_exactly_a<numeric>(eexponent)) {
-               num_exponent = &ex_to<numeric>(eexponent);
+       if (is_exactly_a<numeric>(exponent)) {
+               num_exponent = &ex_to<numeric>(exponent);
        }
        
        // ^(x,0) -> 1  (0^0 also handled here)
        }
        
        // ^(x,0) -> 1  (0^0 also handled here)
-       if (eexponent.is_zero()) {
-               if (ebasis.is_zero())
+       if (exponent.is_zero()) {
+               if (basis.is_zero())
                        throw (std::domain_error("power::eval(): pow(0,0) is undefined"));
                else
                        return _ex1;
        }
        
        // ^(x,1) -> x
                        throw (std::domain_error("power::eval(): pow(0,0) is undefined"));
                else
                        return _ex1;
        }
        
        // ^(x,1) -> x
-       if (eexponent.is_equal(_ex1))
-               return ebasis;
+       if (exponent.is_equal(_ex1))
+               return basis;
 
        // ^(0,c1) -> 0 or exception  (depending on real value of c1)
 
        // ^(0,c1) -> 0 or exception  (depending on real value of c1)
-       if ( ebasis.is_zero() && num_exponent ) {
+       if (basis.is_zero() && num_exponent) {
                if ((num_exponent->real()).is_zero())
                        throw (std::domain_error("power::eval(): pow(0,I) is undefined"));
                else if ((num_exponent->real()).is_negative())
                if ((num_exponent->real()).is_zero())
                        throw (std::domain_error("power::eval(): pow(0,I) is undefined"));
                else if ((num_exponent->real()).is_negative())
@@ -418,16 +412,16 @@ ex power::eval(int level) const
        }
 
        // ^(1,x) -> 1
        }
 
        // ^(1,x) -> 1
-       if (ebasis.is_equal(_ex1))
+       if (basis.is_equal(_ex1))
                return _ex1;
 
        // power of a function calculated by separate rules defined for this function
                return _ex1;
 
        // power of a function calculated by separate rules defined for this function
-       if (is_exactly_a<function>(ebasis))
-               return ex_to<function>(ebasis).power(eexponent);
+       if (is_exactly_a<function>(basis))
+               return ex_to<function>(basis).power(exponent);
 
        // Turn (x^c)^d into x^(c*d) in the case that x is positive and c is real.
 
        // Turn (x^c)^d into x^(c*d) in the case that x is positive and c is real.
-       if (is_exactly_a<power>(ebasis) && ebasis.op(0).info(info_flags::positive) && ebasis.op(1).info(info_flags::real))
-               return power(ebasis.op(0), ebasis.op(1) * eexponent);
+       if (is_exactly_a<power>(basis) && basis.op(0).info(info_flags::positive) && basis.op(1).info(info_flags::real))
+               return power(basis.op(0), basis.op(1) * exponent);
 
        if ( num_exponent ) {
 
 
        if ( num_exponent ) {
 
@@ -487,8 +481,8 @@ ex power::eval(int level) const
                // ^(^(x,c1),c2) -> ^(x,c1*c2)
                // (c1, c2 numeric(), c2 integer or -1 < c1 <= 1 or (c1=-1 and c2>0),
                // case c1==1 should not happen, see below!)
                // ^(^(x,c1),c2) -> ^(x,c1*c2)
                // (c1, c2 numeric(), c2 integer or -1 < c1 <= 1 or (c1=-1 and c2>0),
                // case c1==1 should not happen, see below!)
-               if (is_exactly_a<power>(ebasis)) {
-                       const power & sub_power = ex_to<power>(ebasis);
+               if (is_exactly_a<power>(basis)) {
+                       const power & sub_power = ex_to<power>(basis);
                        const ex & sub_basis = sub_power.basis;
                        const ex & sub_exponent = sub_power.exponent;
                        if (is_exactly_a<numeric>(sub_exponent)) {
                        const ex & sub_basis = sub_power.basis;
                        const ex & sub_exponent = sub_power.exponent;
                        if (is_exactly_a<numeric>(sub_exponent)) {
@@ -502,15 +496,15 @@ ex power::eval(int level) const
                }
        
                // ^(*(x,y,z),c1) -> *(x^c1,y^c1,z^c1) (c1 integer)
                }
        
                // ^(*(x,y,z),c1) -> *(x^c1,y^c1,z^c1) (c1 integer)
-               if (num_exponent->is_integer() && is_exactly_a<mul>(ebasis)) {
-                       return expand_mul(ex_to<mul>(ebasis), *num_exponent, 0);
+               if (num_exponent->is_integer() && is_exactly_a<mul>(basis)) {
+                       return expand_mul(ex_to<mul>(basis), *num_exponent, 0);
                }
 
                // (2*x + 6*y)^(-4) -> 1/16*(x + 3*y)^(-4)
                }
 
                // (2*x + 6*y)^(-4) -> 1/16*(x + 3*y)^(-4)
-               if (num_exponent->is_integer() && is_exactly_a<add>(ebasis)) {
-                       numeric icont = ebasis.integer_content();
+               if (num_exponent->is_integer() && is_exactly_a<add>(basis)) {
+                       numeric icont = basis.integer_content();
                        const numeric lead_coeff = 
                        const numeric lead_coeff = 
-                               ex_to<numeric>(ex_to<add>(ebasis).seq.begin()->coeff).div(icont);
+                               ex_to<numeric>(ex_to<add>(basis).seq.begin()->coeff).div(icont);
 
                        const bool canonicalizable = lead_coeff.is_integer();
                        const bool unit_normal = lead_coeff.is_pos_integer();
 
                        const bool canonicalizable = lead_coeff.is_integer();
                        const bool unit_normal = lead_coeff.is_pos_integer();
@@ -518,7 +512,7 @@ ex power::eval(int level) const
                                icont = icont.mul(*_num_1_p);
                        
                        if (canonicalizable && (icont != *_num1_p)) {
                                icont = icont.mul(*_num_1_p);
                        
                        if (canonicalizable && (icont != *_num1_p)) {
-                               const add& addref = ex_to<add>(ebasis);
+                               const add& addref = ex_to<add>(basis);
                                add & addp = dynallocate<add>(addref);
                                addp.clearflag(status_flags::hash_calculated);
                                addp.overall_coeff = ex_to<numeric>(addp.overall_coeff).div_dyn(icont);
                                add & addp = dynallocate<add>(addref);
                                addp.clearflag(status_flags::hash_calculated);
                                addp.overall_coeff = ex_to<numeric>(addp.overall_coeff).div_dyn(icont);
@@ -535,9 +529,9 @@ ex power::eval(int level) const
 
                // ^(*(...,x;c1),c2) -> *(^(*(...,x;1),c2),c1^c2)  (c1, c2 numeric(), c1>0)
                // ^(*(...,x;c1),c2) -> *(^(*(...,x;-1),c2),(-c1)^c2)  (c1, c2 numeric(), c1<0)
 
                // ^(*(...,x;c1),c2) -> *(^(*(...,x;1),c2),c1^c2)  (c1, c2 numeric(), c1>0)
                // ^(*(...,x;c1),c2) -> *(^(*(...,x;-1),c2),(-c1)^c2)  (c1, c2 numeric(), c1<0)
-               if (is_exactly_a<mul>(ebasis)) {
+               if (is_exactly_a<mul>(basis)) {
                        GINAC_ASSERT(!num_exponent->is_integer()); // should have been handled above
                        GINAC_ASSERT(!num_exponent->is_integer()); // should have been handled above
-                       const mul & mulref = ex_to<mul>(ebasis);
+                       const mul & mulref = ex_to<mul>(basis);
                        if (!mulref.overall_coeff.is_equal(_ex1)) {
                                const numeric & num_coeff = ex_to<numeric>(mulref.overall_coeff);
                                if (num_coeff.is_real()) {
                        if (!mulref.overall_coeff.is_equal(_ex1)) {
                                const numeric & num_coeff = ex_to<numeric>(mulref.overall_coeff);
                                if (num_coeff.is_real()) {
@@ -563,17 +557,13 @@ ex power::eval(int level) const
 
                // ^(nc,c1) -> ncmul(nc,nc,...) (c1 positive integer, unless nc is a matrix)
                if (num_exponent->is_pos_integer() &&
 
                // ^(nc,c1) -> ncmul(nc,nc,...) (c1 positive integer, unless nc is a matrix)
                if (num_exponent->is_pos_integer() &&
-                   ebasis.return_type() != return_types::commutative &&
-                   !is_a<matrix>(ebasis)) {
-                       return ncmul(exvector(num_exponent->to_int(), ebasis));
+                   basis.return_type() != return_types::commutative &&
+                   !is_a<matrix>(basis)) {
+                       return ncmul(exvector(num_exponent->to_int(), basis));
                }
        }
                }
        }
-       
-       if (are_ex_trivially_equal(ebasis,basis) &&
-           are_ex_trivially_equal(eexponent,exponent)) {
-               return this->hold();
-       }
-       return dynallocate<power>(ebasis, eexponent).setflag(status_flags::evaluated);
+
+       return this->hold();
 }
 
 ex power::evalf(int level) const
 }
 
 ex power::evalf(int level) const
index 1662ee0382065dc4312adc7879de8957f775aaf8..ac85f722e84021092b633c057c7c726ec5e5ffe4 100644 (file)
@@ -59,7 +59,7 @@ public:
        int degree(const ex & s) const override;
        int ldegree(const ex & s) const override;
        ex coeff(const ex & s, int n = 1) const override;
        int degree(const ex & s) const override;
        int ldegree(const ex & s) const override;
        ex coeff(const ex & s, int n = 1) const override;
-       ex eval(int level=0) const override;
+       ex eval() const override;
        ex evalf(int level=0) const override;
        ex evalm() const override;
        ex series(const relational & s, int order, unsigned options = 0) const override;
        ex evalf(int level=0) const override;
        ex evalm() const override;
        ex series(const relational & s, int order, unsigned options = 0) const override;
index 08809fd18c2af3e54806f1ac3febcb970fc8862e..31a92002958399818659b65e83094b498a66dbc4 100644 (file)
@@ -384,20 +384,18 @@ ex pseries::collect(const ex &s, bool distributed) const
 }
 
 /** Perform coefficient-wise automatic term rewriting rules in this class. */
 }
 
 /** Perform coefficient-wise automatic term rewriting rules in this class. */
-ex pseries::eval(int level) const
+ex pseries::eval() const
 {
 {
-       if (level == 1)
-               return this->hold();
-       
-       if (level == -max_recursion_level)
-               throw (std::runtime_error("pseries::eval(): recursion limit exceeded"));
+       if (flags & status_flags::evaluated) {
+               return *this;
+       }
        
        // Construct a new series with evaluated coefficients
        epvector new_seq;
        new_seq.reserve(seq.size());
        epvector::const_iterator it = seq.begin(), itend = seq.end();
        while (it != itend) {
        
        // Construct a new series with evaluated coefficients
        epvector new_seq;
        new_seq.reserve(seq.size());
        epvector::const_iterator it = seq.begin(), itend = seq.end();
        while (it != itend) {
-               new_seq.push_back(expair(it->rest.eval(level-1), it->coeff));
+               new_seq.push_back(expair(it->rest, it->coeff));
                ++it;
        }
        return dynallocate<pseries>(relational(var,point), std::move(new_seq)).setflag(status_flags::evaluated);
                ++it;
        }
        return dynallocate<pseries>(relational(var,point), std::move(new_seq)).setflag(status_flags::evaluated);
index 3a36e6d6cf05d457758caa2abe5a4b37dd56c77c..3670ff17371b00de0dce25eb347042c2a1f7ddfb 100644 (file)
@@ -50,7 +50,7 @@ public:
        int ldegree(const ex &s) const override;
        ex coeff(const ex &s, int n = 1) const override;
        ex collect(const ex &s, bool distributed = false) const override;
        int ldegree(const ex &s) const override;
        ex coeff(const ex &s, int n = 1) const override;
        ex collect(const ex &s, bool distributed = false) const override;
-       ex eval(int level=0) const override;
+       ex eval() const override;
        ex evalf(int level=0) const override;
        ex series(const relational & r, int order, unsigned options = 0) const override;
        ex subs(const exmap & m, unsigned options = 0) const override;
        ex evalf(int level=0) const override;
        ex series(const relational & r, int order, unsigned options = 0) const override;
        ex subs(const exmap & m, unsigned options = 0) const override;
index 479522cf0ce8d301aea4f8eaca13ecab6fab1334..38d0baf7c757230e1b586c09e716f9343202b185 100644 (file)
@@ -176,17 +176,6 @@ ex relational::map(map_function & f) const
                return *this;
 }
 
                return *this;
 }
 
-ex relational::eval(int level) const
-{
-       if (level==1)
-               return this->hold();
-       
-       if (level == -max_recursion_level)
-               throw(std::runtime_error("max recursion level reached"));
-       
-       return dynallocate<relational>(lh.eval(level-1), rh.eval(level-1), o).setflag(status_flags::evaluated);
-}
-
 ex relational::subs(const exmap & m, unsigned options) const
 {
        const ex & subsed_lh = lh.subs(m, options);
 ex relational::subs(const exmap & m, unsigned options) const
 {
        const ex & subsed_lh = lh.subs(m, options);
index c8bf8b6d44c306a2b2f88c3126a595270e278d63..0c9d65a1a6b713a2ef1f74f038a37e3e51d023ba 100644 (file)
@@ -58,7 +58,6 @@ public:
        ex op(size_t i) const override;
        ex map(map_function & f) const override;
        ex subs(const exmap & m, unsigned options = 0) const override;
        ex op(size_t i) const override;
        ex map(map_function & f) const override;
        ex subs(const exmap & m, unsigned options = 0) const override;
-       ex eval(int level=0) const override;
 
        /** Save (a.k.a. serialize) object into archive. */
        void archive(archive_node& n) const override;
 
        /** Save (a.k.a. serialize) object into archive. */
        void archive(archive_node& n) const override;
index 1301ad2b25b953a61ef292d6aa25e7152d2417a1..657bf6b98f8da34d82a782f72aa8a2dc4fe3bd68 100644 (file)
@@ -126,7 +126,7 @@ public:
        // All these are just defaults that can be specialized by the user
 public:
        // evaluation
        // All these are just defaults that can be specialized by the user
 public:
        // evaluation
-       ex eval(int level = 0) const override { return hold(); }
+       ex eval() const override { return hold(); }
        ex evalf(int level = 0) const override { return inherited::evalf(level); }
        ex evalm() const override { return inherited::evalm(); }
 protected:
        ex evalf(int level = 0) const override { return inherited::evalf(level); }
        ex evalm() const override { return inherited::evalm(); }
 protected:
index 84320f277ef796c400d95e94c7035b87dd0a3b5e..157e42843aa715ca2184347bb61696d05e414561 100644 (file)
@@ -46,7 +46,7 @@ public:
        // functions overriding virtual functions from base classes
 public:
        bool info(unsigned inf) const override;
        // functions overriding virtual functions from base classes
 public:
        bool info(unsigned inf) const override;
-       ex eval(int level = 0) const override { return *this; } // for performance reasons
+       ex eval() const override { return *this; } // for performance reasons
        ex evalf(int level = 0) const override { return *this; } // overwrites basic::evalf() for performance reasons
        ex series(const relational & s, int order, unsigned options = 0) const override;
        ex subs(const exmap & m, unsigned options = 0) const override { return subs_one_level(m, options); } // overwrites basic::subs() for performance reasons
        ex evalf(int level = 0) const override { return *this; } // overwrites basic::evalf() for performance reasons
        ex series(const relational & s, int order, unsigned options = 0) const override;
        ex subs(const exmap & m, unsigned options = 0) const override { return subs_one_level(m, options); } // overwrites basic::subs() for performance reasons
index 3a8f06211e7b523bf97d30319415acfb4aaf1903..96a864a82cbc40b8c7fcbcb2fc4970fafb2d17f0 100644 (file)
@@ -242,7 +242,7 @@ exp : T_NUMBER              {$$ = $1;}
                if (i == assigned_symbol_table.end())
                        $$ = $1;
                else
                if (i == assigned_symbol_table.end())
                        $$ = $1;
                else
-                       $$ = i->second.eval();
+                       $$ = i->second;
        }
        | '\'' T_SYMBOL '\''    {$$ = $2;}
        | T_LITERAL             {$$ = $1;}
        }
        | '\'' T_SYMBOL '\''    {$$ = $2;}
        | T_LITERAL             {$$ = $1;}
@@ -331,7 +331,6 @@ static ex f_collect_common_factors(const exprseq &e) {return collect_common_fact
 static ex f_convert_H_to_Li(const exprseq &e) {return convert_H_to_Li(e[0], e[1]);}
 static ex f_degree(const exprseq &e) {return e[0].degree(e[1]);}
 static ex f_denom(const exprseq &e) {return e[0].denom();}
 static ex f_convert_H_to_Li(const exprseq &e) {return convert_H_to_Li(e[0], e[1]);}
 static ex f_degree(const exprseq &e) {return e[0].degree(e[1]);}
 static ex f_denom(const exprseq &e) {return e[0].denom();}
-static ex f_eval1(const exprseq &e) {return e[0].eval();}
 static ex f_evalf1(const exprseq &e) {return e[0].evalf();}
 static ex f_evalm(const exprseq &e) {return e[0].evalm();}
 static ex f_eval_integ(const exprseq &e) {return e[0].eval_integ();}
 static ex f_evalf1(const exprseq &e) {return e[0].evalf();}
 static ex f_evalm(const exprseq &e) {return e[0].evalm();}
 static ex f_eval_integ(const exprseq &e) {return e[0].eval_integ();}
@@ -414,12 +413,6 @@ static ex f_divide(const exprseq &e)
                return fail();
 }
 
                return fail();
 }
 
-static ex f_eval2(const exprseq &e)
-{
-       CHECK_ARG(1, numeric, eval);
-       return e[0].eval(ex_to<numeric>(e[1]).to_int());
-}
-
 static ex f_evalf2(const exprseq &e)
 {
        CHECK_ARG(1, numeric, evalf);
 static ex f_evalf2(const exprseq &e)
 {
        CHECK_ARG(1, numeric, evalf);
@@ -618,8 +611,6 @@ static const fcn_init builtin_fcns[] = {
        {"diff", f_diff2, 2},
        {"diff", f_diff3, 3},
        {"divide", f_divide, 2},
        {"diff", f_diff2, 2},
        {"diff", f_diff3, 3},
        {"divide", f_divide, 2},
-       {"eval", f_eval1, 1},
-       {"eval", f_eval2, 2},
        {"evalf", f_evalf1, 1},
        {"evalf", f_evalf2, 2},
        {"evalm", f_evalm, 1},
        {"evalf", f_evalf1, 1},
        {"evalf", f_evalf2, 2},
        {"evalm", f_evalm, 1},
@@ -729,7 +720,7 @@ static void insert_fcns(const fcn_init *p)
 
 static ex f_ginac_function(const exprseq &es, int serial)
 {
 
 static ex f_ginac_function(const exprseq &es, int serial)
 {
-       return GiNaC::function(serial, es).eval(1);
+       return GiNaC::function(serial, es);
 }
 
 // All registered GiNaC functions
 }
 
 // All registered GiNaC functions