# [GiNaC-devel] Function and ncmul

Vladimir V. Kisil kisilv at maths.leeds.ac.uk
Sat Apr 26 20:53:45 CEST 2008

Dear All,

Consider the following program:

#include <ginac/ginac.h>
#include <fstream>
using namespace std;
using namespace GiNaC;

int main(){

realsymbol a("a");

varidx mu(symbol("mu", "\\mu"), 1);
ex e = clifford_unit(mu, diag_matrix(lst(-1))),
e0=e.subs(mu==0),
p1=e0*exp(a*e0),
p2=exp(a*e0)*e0;

cout << e0*p1 << endl;
// -> exp(e0*a)
cout << p2*e0 << endl;
// -> exp(e0*a)*e0*e0
}

The expression in the second output is not simplified for the
following reason. When the method ncmul::eval() collects non-commuting
the terms exp(e0*a) gets the type of its first noncommuting element,
i.e. e0 (this is defined by function::return_type()). So all three
factors are in the same type group.

However when later ncmul::eval() calls the method eval_ncmul() for the first
term in the product, e.i.  exp(e0*a), it falls back to
basic::eval_ncmul() not clifford::eval_ncmul() as one may expect.

I provide below a small patch which makes the behaviour of class function
more consistent in this respect.

Best wishes,
--
Vladimir V. Kisil     email: kisilv at maths.leeds.ac.uk
--                      www: http://maths.leeds.ac.uk/~kisilv/

Parent: 6850c16435de33396ccd505ff26b4d4574fa74cf (Fixed bug in mLi summation causing premature drop-out and made Nielsen polylog)
Branch: master
Follows: release_1-4-0
Precedes:

Method function::eval_ncmul() is defined to match the behaviour of function::return_type()

------------------------------ ginac/function.pl ------------------------------
index e91278c..3b22143 100644
@@ -507,6 +507,7 @@ public:
ex expand(unsigned options=0) const;
ex eval(int level=0) const;
ex evalf(int level=0) const;
+	ex eval_ncmul(const exvector & v) const;
unsigned calchash() const;
ex series(const relational & r, int order, unsigned options = 0) const;
ex thiscontainer(const exvector & v) const;
@@ -1053,6 +1054,16 @@ \${evalf_switch_statement}
throw(std::logic_error("function::evalf(): invalid nparams"));
}

+/*
+* This method is defined to be in line with behaviour of function::return_type()
+*/
+ex function::eval_ncmul(const exvector & v) const
+{
+	// If this function is called then the list of arguments is non-empty
+	// and the first argument is non-commutative, see  function::return_type()
+	return seq.begin()->eval_ncmul(v);
+}
+
unsigned function::calchash() const
{
unsigned v = golden_ratio_hash(golden_ratio_hash((p_int)tinfo()) ^ serial);