]> www.ginac.de Git - ginac.git/blobdiff - ginac/ncmul.cpp
synced to 1.2 (typos, better ncmul::degree() and ::coeff())
[ginac.git] / ginac / ncmul.cpp
index a00bff1e385f2016228f4dd850ce55757a93263f..abad2d1616c910a180c5cfa9c7b42260d6839aaf 100644 (file)
@@ -36,7 +36,7 @@ namespace GiNaC {
 
 GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(ncmul, exprseq,
   print_func<print_context>(&ncmul::do_print).
-  print_func<print_tree>(&basic::do_print_tree).
+  print_func<print_tree>(&ncmul::do_print_tree).
   print_func<print_csrc>(&ncmul::do_print_csrc).
   print_func<print_python_repr>(&ncmul::do_print_csrc))
 
@@ -127,7 +127,8 @@ typedef std::vector<int> intvector;
 ex ncmul::expand(unsigned options) const
 {
        // First, expand the children
-       exvector expanded_seq = expandchildren(options);
+       std::auto_ptr<exvector> vp = expandchildren(options);
+       const exvector &expanded_seq = vp.get() ? *vp : this->seq;
        
        // Now, look for all the factors that are sums and remember their
        // position and number of terms.
@@ -151,9 +152,13 @@ ex ncmul::expand(unsigned options) const
        }
 
        // If there are no sums, we are done
-       if (number_of_adds == 0)
-               return (new ncmul(expanded_seq, true))->
-                       setflag(status_flags::dynallocated | (options == 0 ? status_flags::expanded : 0));
+       if (number_of_adds == 0) {
+               if (vp.get())
+                       return (new ncmul(vp))->
+                               setflag(status_flags::dynallocated | (options == 0 ? status_flags::expanded : 0));
+               else
+                       return *this;
+       }
 
        // Now, form all possible products of the terms of the sums with the
        // remaining factors, and add them together
@@ -185,6 +190,9 @@ ex ncmul::expand(unsigned options) const
 
 int ncmul::degree(const ex & s) const
 {
+       if (is_equal(ex_to<basic>(s)))
+               return 1;
+
        // Sum up degrees of factors
        int deg_sum = 0;
        exvector::const_iterator i = seq.begin(), end = seq.end();
@@ -197,6 +205,9 @@ int ncmul::degree(const ex & s) const
 
 int ncmul::ldegree(const ex & s) const
 {
+       if (is_equal(ex_to<basic>(s)))
+               return 1;
+
        // Sum up degrees of factors
        int deg_sum = 0;
        exvector::const_iterator i = seq.begin(), end = seq.end();
@@ -209,6 +220,9 @@ int ncmul::ldegree(const ex & s) const
 
 ex ncmul::coeff(const ex & s, int n) const
 {
+       if (is_equal(ex_to<basic>(s)))
+               return n==1 ? _ex1 : _ex0;
+
        exvector coeffseq;
        coeffseq.reserve(seq.size());
 
@@ -462,7 +476,7 @@ ex ncmul::conjugate() const
                return exprseq::conjugate();
        }
 
-       if (return_type_tinfo() & 0xffffff00U != TINFO_clifford) {
+       if ((return_type_tinfo() & 0xffffff00U) != TINFO_clifford) {
                return exprseq::conjugate();
        }
 
@@ -530,7 +544,7 @@ unsigned ncmul::return_type() const
                ++i;
        }
        // all factors checked
-       GINAC_ASSERT(!all_commutative); // not all factors should commute, because this is a ncmul();
+       GINAC_ASSERT(!all_commutative); // not all factors should commutate, because this is a ncmul();
        return all_commutative ? return_types::commutative : return_types::noncommutative;
 }
    
@@ -561,16 +575,34 @@ unsigned ncmul::return_type_tinfo() const
 // non-virtual functions in this class
 //////////
 
-exvector ncmul::expandchildren(unsigned options) const
+std::auto_ptr<exvector> ncmul::expandchildren(unsigned options) const
 {
-       exvector s;
-       s.reserve(seq.size());
-       exvector::const_iterator it = seq.begin(), itend = seq.end();
-       while (it != itend) {
-               s.push_back(it->expand(options));
-               it++;
+       const_iterator cit = this->seq.begin(), end = this->seq.end();
+       while (cit != end) {
+               const ex & expanded_ex = cit->expand(options);
+               if (!are_ex_trivially_equal(*cit, expanded_ex)) {
+
+                       // copy first part of seq which hasn't changed
+                       std::auto_ptr<exvector> s(new exvector(this->seq.begin(), cit));
+                       reserve(*s, this->seq.size());
+
+                       // insert changed element
+                       s->push_back(expanded_ex);
+                       ++cit;
+
+                       // copy rest
+                       while (cit != end) {
+                               s->push_back(cit->expand(options));
+                               ++cit;
+                       }
+
+                       return s;
+               }
+
+               ++cit;
        }
-       return s;
+
+       return std::auto_ptr<exvector>(0); // nothing has changed
 }
 
 const exvector & ncmul::get_factors() const