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 6e4d846..edba776 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 6ab452b..ad7ee8d 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 56f205e..bc5bc83 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 0d86eee..fd5550f 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 ed58730..2a2e2f8 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 659692b..4276157 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 96cfd14..a2be1ca 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 a8062c1..0cec003 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 04ab31d..0881095 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 7bd8410..c403c7f 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 343fa36..6fd45c9 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 9ca4070..e99d21f 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 d33ff33..41b077d 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 e96dccf..30d7953 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 4229d0a..17817e1 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 a646eac..643fafa 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 789ca05..686a76e 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 b54f41f..0f35100 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 ca4beff..357528a 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 a04b742..1917de4 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 2a20792..82a0bbd 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 81e7ade..926125b 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 f76ac7f..b2be4b4 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 7d054cf..c842885 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 988e257..5c665dd 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 a83b771..0a6fca4 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 95eba3d..e689ddf 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 c287a02..b43ec95 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 2233b8d..0ed54f7 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 b2e8d10..7968b90 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 2bb9265..9b23214 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 4d3135d..a22209e 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 afe2f1e..c376009 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 1662ee0..ac85f72 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 08809fd..31a9200 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 3a36e6d..3670ff1 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 479522c..38d0baf 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 c8bf8b6..0c9d65a 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 1301ad2..657bf6b 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 84320f2..157e428 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 3a8f062..96a864a 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