* Implementation of GiNaC's non-commutative products of expressions. */
/*
- * GiNaC Copyright (C) 1999-2003 Johannes Gutenberg University Mainz, Germany
+ * GiNaC Copyright (C) 1999-2004 Johannes Gutenberg University Mainz, Germany
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include "add.h"
#include "mul.h"
#include "matrix.h"
-#include "print.h"
#include "archive.h"
#include "utils.h"
namespace GiNaC {
-GINAC_IMPLEMENT_REGISTERED_CLASS(ncmul, exprseq)
+GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(ncmul, exprseq,
+ print_func<print_context>(&ncmul::do_print).
+ 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))
+
//////////
// default constructor
tinfo_key = TINFO_ncmul;
}
-ncmul::ncmul(exvector * vp) : inherited(vp)
+ncmul::ncmul(std::auto_ptr<exvector> vp) : inherited(vp)
{
tinfo_key = TINFO_ncmul;
}
// public
-void ncmul::print(const print_context & c, unsigned level) const
+void ncmul::do_print(const print_context & c, unsigned level) const
{
- if (is_a<print_tree>(c)) {
-
- inherited::print(c, level);
-
- } else if (is_a<print_csrc>(c) || is_a<print_python_repr>(c)) {
-
- c.s << class_name() << "(";
- exvector::const_iterator it = seq.begin(), itend = seq.end()-1;
- while (it != itend) {
- it->print(c, precedence());
- c.s << ",";
- it++;
- }
- it->print(c, precedence());
- c.s << ")";
+ printseq(c, '(', '*', ')', precedence(), level);
+}
- } else
- printseq(c, '(', '*', ')', precedence(), level);
+void ncmul::do_print_csrc(const print_context & c, unsigned level) const
+{
+ c.s << class_name();
+ printseq(c, '(', ',', ')', precedence(), precedence());
}
bool ncmul::info(unsigned inf) const
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.
}
// 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
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();
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();
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());
ex ncmul::evalm() const
{
// Evaluate children first
- exvector *s = new exvector;
+ std::auto_ptr<exvector> s(new exvector);
s->reserve(seq.size());
exvector::const_iterator it = seq.begin(), itend = seq.end();
while (it != itend) {
prod = prod.mul(ex_to<matrix>(*it));
it++;
}
- delete s;
return prod;
}
return (new ncmul(v))->setflag(status_flags::dynallocated);
}
-ex ncmul::thiscontainer(exvector * vp) const
+ex ncmul::thiscontainer(std::auto_ptr<exvector> vp) const
{
return (new ncmul(vp))->setflag(status_flags::dynallocated);
}
+ex ncmul::conjugate() const
+{
+ if (return_type() != return_types::noncommutative) {
+ return exprseq::conjugate();
+ }
+
+ if ((return_type_tinfo() & 0xffffff00U) != TINFO_clifford) {
+ return exprseq::conjugate();
+ }
+
+ exvector ev;
+ ev.reserve(nops());
+ for (const_iterator i=end(); i!=begin();) {
+ --i;
+ ev.push_back(i->conjugate());
+ }
+ return (new ncmul(ev, true))->setflag(status_flags::dynallocated).eval();
+}
+
// protected
/** Implementation of ex::diff() for a non-commutative product. It applies
++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;
}
// 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