- // 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::eval_ncmul(x1,x2,x3,...)
- // the following 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,...) ->
- // ncmul(ncmul(x1,x2,...),X,ncmul(y1,y2,...)
- // (X noncommutative_composite)
-
- if ((level==1)&&(flags & status_flags::evaluated)) {
- return *this;
- }
-
- exvector evaledseq=evalchildren(level);
-
- // ncmul(...,*(x1,x2),...,ncmul(x3,x4),...) ->
- // ncmul(...,x1,x2,...,x3,x4,...) (associativity)
- unsigned factors=0;
- for (exvector::const_iterator cit=evaledseq.begin(); cit!=evaledseq.end(); ++cit) {
- factors += count_factors(*cit);
- }
-
- exvector assocseq;
- assocseq.reserve(factors);
- for (exvector::const_iterator cit=evaledseq.begin(); cit!=evaledseq.end(); ++cit) {
- append_factors(assocseq,*cit);
- }
-
- // ncmul(x) -> x
- if (assocseq.size()==1) return *(seq.begin());
-
- // ncmul() -> 1
- if (assocseq.size()==0) return exONE();
-
- // 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;
- for (exvector::const_iterator cit=assocseq.begin(); cit!=assocseq.end(); ++cit) {
- switch (rettypes[i]=(*cit).return_type()) {
- case return_types::commutative:
- count_commutative++;
- break;
- case return_types::noncommutative:
- count_noncommutative++;
- break;
- case return_types::noncommutative_composite:
- count_noncommutative_composite++;
- break;
- default:
- throw(std::logic_error("ncmul::eval(): invalid return type"));
- }
- ++i;
- }
- GINAC_ASSERT(count_commutative+count_noncommutative+count_noncommutative_composite==assocseq.size());
-
- // ncmul(...,c1,...,c2,...) ->
- // *(c1,c2,ncmul(...)) (pull out commutative elements)
- if (count_commutative!=0) {
- exvector commutativeseq;
- commutativeseq.reserve(count_commutative+1);
- exvector noncommutativeseq;
- noncommutativeseq.reserve(assocseq.size()-count_commutative);
- for (i=0; i<assocseq.size(); ++i) {
- if (rettypes[i]==return_types::commutative) {
- commutativeseq.push_back(assocseq[i]);
- } else {
- noncommutativeseq.push_back(assocseq[i]);
- }
- }
- commutativeseq.push_back((new ncmul(noncommutativeseq,1))->
- setflag(status_flags::dynallocated));
- return (new mul(commutativeseq))->setflag(status_flags::dynallocated);
- }
-
- // ncmul(x1,y1,x2,y2) -> *(ncmul(x1,x2),ncmul(y1,y2))
- // (collect elements of same type)
-
- if (count_noncommutative_composite==0) {
- // there are neither commutative nor noncommutative_composite
- // elements in assocseq
- GINAC_ASSERT(count_commutative==0);
-
- exvectorvector evv;
- unsignedvector rttinfos;
- evv.reserve(assocseq.size());
- rttinfos.reserve(assocseq.size());
-
- for (exvector::const_iterator cit=assocseq.begin(); cit!=assocseq.end(); ++cit) {
- unsigned ti=(*cit).return_type_tinfo();
- // search type in vector of known types
- for (i=0; i<rttinfos.size(); ++i) {
- if (ti==rttinfos[i]) {
- evv[i].push_back(*cit);
- break;
- }
- }
- if (i>=rttinfos.size()) {
- // new type
- rttinfos.push_back(ti);
- evv.push_back(exvector());
- (*(evv.end()-1)).reserve(assocseq.size());
- (*(evv.end()-1)).push_back(*cit);
- }
- }
-
+ // 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,...) ->
+ // ncmul(ncmul(x1,x2,...),X,ncmul(y1,y2,...)
+ // (X noncommutative_composite)
+
+ if ((level==1) && (flags & status_flags::evaluated)) {
+ return *this;
+ }
+
+ exvector evaledseq=evalchildren(level);
+
+ // ncmul(...,*(x1,x2),...,ncmul(x3,x4),...) ->
+ // ncmul(...,x1,x2,...,x3,x4,...) (associativity)
+ unsigned factors = 0;
+ exvector::const_iterator cit = evaledseq.begin(), citend = evaledseq.end();
+ while (cit != citend)
+ factors += count_factors(*cit++);
+
+ exvector assocseq;
+ assocseq.reserve(factors);
+ cit = evaledseq.begin();
+ while (cit != citend)
+ append_factors(assocseq, *cit++);
+
+ // ncmul(x) -> x
+ if (assocseq.size()==1) return *(seq.begin());
+
+ // ncmul() -> 1
+ 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;
+ cit = assocseq.begin(); citend = assocseq.end();
+ while (cit != citend) {
+ switch (rettypes[i] = cit->return_type()) {
+ case return_types::commutative:
+ count_commutative++;
+ break;
+ case return_types::noncommutative:
+ count_noncommutative++;
+ break;
+ case return_types::noncommutative_composite:
+ count_noncommutative_composite++;
+ break;
+ default:
+ throw(std::logic_error("ncmul::eval(): invalid return type"));
+ }
+ ++i; ++cit;
+ }
+ GINAC_ASSERT(count_commutative+count_noncommutative+count_noncommutative_composite==assocseq.size());
+
+ // ncmul(...,c1,...,c2,...) ->
+ // *(c1,c2,ncmul(...)) (pull out commutative elements)
+ if (count_commutative!=0) {
+ exvector commutativeseq;
+ commutativeseq.reserve(count_commutative+1);
+ exvector noncommutativeseq;
+ noncommutativeseq.reserve(assocseq.size()-count_commutative);
+ unsigned num = assocseq.size();
+ for (unsigned i=0; i<num; ++i) {
+ if (rettypes[i]==return_types::commutative)
+ commutativeseq.push_back(assocseq[i]);
+ else
+ noncommutativeseq.push_back(assocseq[i]);
+ }
+ commutativeseq.push_back((new ncmul(noncommutativeseq,1))->setflag(status_flags::dynallocated));
+ return (new mul(commutativeseq))->setflag(status_flags::dynallocated);
+ }
+
+ // ncmul(x1,y1,x2,y2) -> *(ncmul(x1,x2),ncmul(y1,y2))
+ // (collect elements of same type)
+
+ if (count_noncommutative_composite==0) {
+ // there are neither commutative nor noncommutative_composite
+ // elements in assocseq
+ GINAC_ASSERT(count_commutative==0);
+
+ unsigned assoc_num = assocseq.size();
+ exvectorvector evv;
+ unsignedvector rttinfos;
+ evv.reserve(assoc_num);
+ rttinfos.reserve(assoc_num);
+
+ cit = assocseq.begin(), citend = assocseq.end();
+ while (cit != citend) {
+ unsigned ti = cit->return_type_tinfo();
+ unsigned rtt_num = rttinfos.size();
+ // search type in vector of known types
+ for (i=0; i<rtt_num; ++i) {
+ if (ti == rttinfos[i]) {
+ evv[i].push_back(*cit);
+ break;
+ }
+ }
+ if (i >= rtt_num) {
+ // new type
+ rttinfos.push_back(ti);
+ evv.push_back(exvector());
+ (evv.end()-1)->reserve(assoc_num);
+ (evv.end()-1)->push_back(*cit);
+ }
+ ++cit;
+ }
+
+ unsigned evv_num = evv.size();