* Implementation of GiNaC's non-commutative products of expressions. */
/*
- * GiNaC Copyright (C) 1999-2001 Johannes Gutenberg University Mainz, Germany
+ * GiNaC Copyright (C) 1999-2003 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 "debugmsg.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>(&basic::do_print_tree).
+ print_func<print_csrc>(&ncmul::do_print_csrc).
+ print_func<print_python_repr>(&ncmul::do_print_csrc))
+
//////////
-// default constructor, destructor, copy constructor assignment operator and helpers
+// default constructor
//////////
ncmul::ncmul()
{
- debugmsg("ncmul default constructor",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_ncmul;
}
-DEFAULT_COPY(ncmul)
-DEFAULT_DESTROY(ncmul)
-
//////////
// other constructors
//////////
ncmul::ncmul(const ex & lh, const ex & rh) : inherited(lh,rh)
{
- debugmsg("ncmul constructor from ex,ex",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_ncmul;
}
ncmul::ncmul(const ex & f1, const ex & f2, const ex & f3) : inherited(f1,f2,f3)
{
- debugmsg("ncmul constructor from 3 ex",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_ncmul;
}
ncmul::ncmul(const ex & f1, const ex & f2, const ex & f3,
const ex & f4) : inherited(f1,f2,f3,f4)
{
- debugmsg("ncmul constructor from 4 ex",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_ncmul;
}
ncmul::ncmul(const ex & f1, const ex & f2, const ex & f3,
const ex & f4, const ex & f5) : inherited(f1,f2,f3,f4,f5)
{
- debugmsg("ncmul constructor from 5 ex",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_ncmul;
}
ncmul::ncmul(const ex & f1, const ex & f2, const ex & f3,
const ex & f4, const ex & f5, const ex & f6) : inherited(f1,f2,f3,f4,f5,f6)
{
- debugmsg("ncmul constructor from 6 ex",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_ncmul;
}
ncmul::ncmul(const exvector & v, bool discardable) : inherited(v,discardable)
{
- debugmsg("ncmul constructor from exvector,bool",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_ncmul;
}
ncmul::ncmul(exvector * vp) : inherited(vp)
{
- debugmsg("ncmul constructor from exvector *",LOGLEVEL_CONSTRUCT);
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
{
- debugmsg("ncmul print", LOGLEVEL_PRINT);
-
- if (is_of_type(c, print_tree)) {
-
- inherited::print(c, level);
-
- } else if (is_of_type(c, print_csrc)) {
-
- c.s << "ncmul(";
- 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
intvector positions_of_adds(expanded_seq.size());
intvector number_of_add_operands(expanded_seq.size());
- int number_of_adds = 0;
- int number_of_expanded_terms = 1;
+ size_t number_of_adds = 0;
+ size_t number_of_expanded_terms = 1;
- unsigned current_position = 0;
+ size_t current_position = 0;
exvector::const_iterator last = expanded_seq.end();
for (exvector::const_iterator cit=expanded_seq.begin(); cit!=last; ++cit) {
if (is_exactly_a<add>(*cit)) {
positions_of_adds[number_of_adds] = current_position;
- unsigned num_ops = cit->nops();
+ size_t num_ops = cit->nops();
number_of_add_operands[number_of_adds] = num_ops;
number_of_expanded_terms *= num_ops;
number_of_adds++;
while (true) {
exvector term = expanded_seq;
- for (int i=0; i<number_of_adds; i++)
+ for (size_t i=0; i<number_of_adds; i++)
term[positions_of_adds[i]] = expanded_seq[positions_of_adds[i]].op(k[i]);
distrseq.push_back((new ncmul(term, true))->
setflag(status_flags::dynallocated | (options == 0 ? status_flags::expanded : 0)));
if (coeff_found) return (new ncmul(coeffseq,1))->setflag(status_flags::dynallocated);
- return _ex0();
+ return _ex0;
}
-unsigned ncmul::count_factors(const ex & e) const
+size_t ncmul::count_factors(const ex & e) const
{
- if ((is_ex_exactly_of_type(e,mul)&&(e.return_type()!=return_types::commutative))||
- (is_ex_exactly_of_type(e,ncmul))) {
- unsigned factors=0;
- for (unsigned i=0; i<e.nops(); i++)
+ if ((is_exactly_a<mul>(e)&&(e.return_type()!=return_types::commutative))||
+ (is_exactly_a<ncmul>(e))) {
+ size_t factors=0;
+ for (size_t i=0; i<e.nops(); i++)
factors += count_factors(e.op(i));
return factors;
void ncmul::append_factors(exvector & v, const ex & e) const
{
- if ((is_ex_exactly_of_type(e,mul)&&(e.return_type()!=return_types::commutative))||
- (is_ex_exactly_of_type(e,ncmul))) {
- for (unsigned i=0; i<e.nops(); i++)
- append_factors(v,e.op(i));
+ if ((is_exactly_a<mul>(e)&&(e.return_type()!=return_types::commutative))||
+ (is_exactly_a<ncmul>(e))) {
+ for (size_t i=0; i<e.nops(); i++)
+ append_factors(v, e.op(i));
} else
v.push_back(e);
}
typedef std::vector<unsigned> unsignedvector;
typedef std::vector<exvector> exvectorvector;
+/** Perform automatic term rewriting rules in this class. In the following
+ * x, x1, x2,... stand for a symbolic variables of type ex and c, c1, c2...
+ * stand for such expressions that contain a plain number.
+ * - ncmul(...,*(x1,x2),...,ncmul(x3,x4),...) -> ncmul(...,x1,x2,...,x3,x4,...) (associativity)
+ * - ncmul(x) -> x
+ * - ncmul() -> 1
+ * - 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
{
- // simplifications: ncmul(...,*(x1,x2),...,ncmul(x3,x4),...) ->
- // ncmul(...,x1,x2,...,x3,x4,...) (associativity)
- // ncmul(x) -> x
- // ncmul() -> 1
- // 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::simplify_ncmul(x1,x2,x3,...)
- // the following rule would be nice, but produces a recursion,
+ // The following additional rule would be nice, but produces a recursion,
// which must be trapped by introducing a flag that the sub-ncmuls()
// are already evaluated (maybe later...)
// ncmul(x1,x2,...,X,y1,y2,...) ->
exvector evaledseq=evalchildren(level);
// ncmul(...,*(x1,x2),...,ncmul(x3,x4),...) ->
- // ncmul(...,x1,x2,...,x3,x4,...) (associativity)
- unsigned factors = 0;
+ // ncmul(...,x1,x2,...,x3,x4,...) (associativity)
+ size_t factors = 0;
exvector::const_iterator cit = evaledseq.begin(), citend = evaledseq.end();
while (cit != citend)
factors += count_factors(*cit++);
if (assocseq.size()==1) return *(seq.begin());
// ncmul() -> 1
- if (assocseq.empty()) return _ex1();
+ if (assocseq.empty()) return _ex1;
// determine return types
unsignedvector rettypes;
rettypes.reserve(assocseq.size());
- unsigned i = 0;
- unsigned count_commutative=0;
- unsigned count_noncommutative=0;
- unsigned count_noncommutative_composite=0;
+ size_t i = 0;
+ size_t count_commutative=0;
+ size_t count_noncommutative=0;
+ size_t count_noncommutative_composite=0;
cit = assocseq.begin(); citend = assocseq.end();
while (cit != citend) {
switch (rettypes[i] = cit->return_type()) {
commutativeseq.reserve(count_commutative+1);
exvector noncommutativeseq;
noncommutativeseq.reserve(assocseq.size()-count_commutative);
- unsigned num = assocseq.size();
- for (unsigned i=0; i<num; ++i) {
+ size_t num = assocseq.size();
+ for (size_t i=0; i<num; ++i) {
if (rettypes[i]==return_types::commutative)
commutativeseq.push_back(assocseq[i]);
else
// elements in assocseq
GINAC_ASSERT(count_commutative==0);
- unsigned assoc_num = assocseq.size();
+ size_t assoc_num = assocseq.size();
exvectorvector evv;
unsignedvector rttinfos;
evv.reserve(assoc_num);
cit = assocseq.begin(), citend = assocseq.end();
while (cit != citend) {
unsigned ti = cit->return_type_tinfo();
- unsigned rtt_num = rttinfos.size();
+ size_t rtt_num = rttinfos.size();
// search type in vector of known types
for (i=0; i<rtt_num; ++i) {
if (ti == rttinfos[i]) {
++cit;
}
- unsigned evv_num = evv.size();
+ size_t evv_num = evv.size();
#ifdef DO_GINAC_ASSERT
GINAC_ASSERT(evv_num == rttinfos.size());
GINAC_ASSERT(evv_num > 0);
- unsigned s=0;
+ size_t s=0;
for (i=0; i<evv_num; ++i)
s += evv[i].size();
GINAC_ASSERT(s == assoc_num);
// if all elements are of same type, simplify the string
if (evv_num == 1)
- return evv[0][0].simplify_ncmul(evv[0]);
+ return evv[0][0].eval_ncmul(evv[0]);
exvector splitseq;
splitseq.reserve(evv_num);
status_flags::evaluated);
}
-ex ncmul::evalm(void) const
+ex ncmul::evalm() const
{
// Evaluate children first
exvector *s = new exvector;
// If there are only matrices, simply multiply them
it = s->begin(); itend = s->end();
- if (is_ex_of_type(*it, matrix)) {
+ if (is_a<matrix>(*it)) {
matrix prod(ex_to<matrix>(*it));
it++;
while (it != itend) {
- if (!is_ex_of_type(*it, matrix))
+ if (!is_a<matrix>(*it))
goto no_matrix;
prod = prod.mul(ex_to<matrix>(*it));
it++;
return (new ncmul(s))->setflag(status_flags::dynallocated);
}
-ex ncmul::thisexprseq(const exvector & v) const
+ex ncmul::thiscontainer(const exvector & v) const
{
return (new ncmul(v))->setflag(status_flags::dynallocated);
}
-ex ncmul::thisexprseq(exvector * vp) const
+ex ncmul::thiscontainer(exvector * vp) const
{
return (new ncmul(vp))->setflag(status_flags::dynallocated);
}
* @see ex::diff */
ex ncmul::derivative(const symbol & s) const
{
- unsigned num = seq.size();
+ size_t num = seq.size();
exvector addseq;
addseq.reserve(num);
// D(a*b*c) = D(a)*b*c + a*D(b)*c + a*b*D(c)
exvector ncmulseq = seq;
- for (unsigned i=0; i<num; ++i) {
+ for (size_t i=0; i<num; ++i) {
ex e = seq[i].diff(s);
e.swap(ncmulseq[i]);
addseq.push_back((new ncmul(ncmulseq))->setflag(status_flags::dynallocated));
return inherited::compare_same_type(other);
}
-unsigned ncmul::return_type(void) const
+unsigned ncmul::return_type() const
{
if (seq.empty())
return return_types::commutative;
return all_commutative ? return_types::commutative : return_types::noncommutative;
}
-unsigned ncmul::return_type_tinfo(void) const
+unsigned ncmul::return_type_tinfo() const
{
if (seq.empty())
return tinfo_key;
return s;
}
-const exvector & ncmul::get_factors(void) const
+const exvector & ncmul::get_factors() const
{
return seq;
}
// friend functions
//////////
-ex nonsimplified_ncmul(const exvector & v)
+ex reeval_ncmul(const exvector & v)
{
return (new ncmul(v))->setflag(status_flags::dynallocated);
}
-ex simplified_ncmul(const exvector & v)
+ex hold_ncmul(const exvector & v)
{
if (v.empty())
- return _ex1();
+ return _ex1;
else if (v.size() == 1)
return v[0];
else