Index: expairseq.cpp
===================================================================
RCS file: /home/cvs/GiNaC/ginac/expairseq.cpp,v
retrieving revision 1.77
diff -c -r1.77 expairseq.cpp
*** expairseq.cpp	1 May 2005 18:23:26 -0000	1.77
--- expairseq.cpp	4 Oct 2005 15:42:16 -0000
***************
*** 34,39 ****
--- 34,40 ----
  #include "archive.h"
  #include "operators.h"
  #include "utils.h"
+ #include "indexed.h"
  
  #if EXPAIRSEQ_USE_HASHTAB
  #include <cmath>
***************
*** 757,764 ****
  				construct_from_2_ex_via_exvector(lh,rh);
  			} else {
  #endif // EXPAIRSEQ_USE_HASHTAB
! 				construct_from_2_expairseq(ex_to<expairseq>(lh),
! 				                           ex_to<expairseq>(rh));
  #if EXPAIRSEQ_USE_HASHTAB
  			}
  #endif // EXPAIRSEQ_USE_HASHTAB
--- 758,772 ----
  				construct_from_2_ex_via_exvector(lh,rh);
  			} else {
  #endif // EXPAIRSEQ_USE_HASHTAB
! 				if(is_a<mul>(lh))
! 				{	
! 					ex newrh=rename_dummy_indices_uniquely(lh, rh);
! 					construct_from_2_expairseq(ex_to<expairseq>(lh),
! 					                           ex_to<expairseq>(newrh));
! 				}
! 				else
! 					construct_from_2_expairseq(ex_to<expairseq>(lh),
! 					                           ex_to<expairseq>(rh));
  #if EXPAIRSEQ_USE_HASHTAB
  			}
  #endif // EXPAIRSEQ_USE_HASHTAB
***************
*** 1008,1020 ****
  	seq.reserve(v.size()+noperands-nexpairseqs);
  	
  	// copy elements and split off numerical part
  	cit = v.begin();
  	while (cit!=v.end()) {
  		if (ex_to<basic>(*cit).tinfo()==this->tinfo()) {
! 			const expairseq &subseqref = ex_to<expairseq>(*cit);
! 			combine_overall_coeff(subseqref.overall_coeff);
! 			epvector::const_iterator cit_s = subseqref.seq.begin();
! 			while (cit_s!=subseqref.seq.end()) {
  				seq.push_back(*cit_s);
  				++cit_s;
  			}
--- 1016,1041 ----
  	seq.reserve(v.size()+noperands-nexpairseqs);
  	
  	// copy elements and split off numerical part
+ 	exvector dummy_indices;
  	cit = v.begin();
  	while (cit!=v.end()) {
  		if (ex_to<basic>(*cit).tinfo()==this->tinfo()) {
! 			const expairseq *subseqref;
! 			ex newfactor;
! 			if(is_a<mul>(*cit))
! 			{
! 				exvector dummies_of_factor = get_all_dummy_indices(*cit);
! 				newfactor = rename_dummy_indices_uniquely(dummy_indices, dummies_of_factor, *cit);
! 				subseqref = &(ex_to<expairseq>(newfactor));
! 				exvector new_dummy_indices;
! 				set_union(dummy_indices.begin(), dummy_indices.end(), dummies_of_factor.begin(), dummies_of_factor.end(), std::back_insert_iterator<exvector>(new_dummy_indices), ex_is_less());
! 				dummy_indices.swap(new_dummy_indices);
! 			}
! 			else
! 				subseqref = &ex_to<expairseq>(*cit);
! 			combine_overall_coeff(subseqref->overall_coeff);
! 			epvector::const_iterator cit_s = subseqref->seq.begin();
! 			while (cit_s!=subseqref->seq.end()) {
  				seq.push_back(*cit_s);
  				++cit_s;
  			}
***************
*** 1579,1584 ****
--- 1600,1675 ----
  	return std::auto_ptr<epvector>(0); // signalling nothing has changed
  }
  
+ class safe_inserter
+ {
+ 	public:
+ 		safe_inserter(const ex&);
+ 		std::auto_ptr<epvector> getseq(){return epv;}
+ 		void insert_old_factor(const ex &e)
+ 		{
+ 			epv->push_back(expair(e,_ex1));
+ 		}
+ 		void insert_new_factor(const ex &e);
+ 		void insert_old_pair(const expair &p)
+ 		{
+ 			epv->push_back(p);
+ 		}
+ 		void insert_new_pair(const expair &p);
+ 	private:
+ 		std::auto_ptr<epvector> epv;
+ 		bool dodummies;
+ 		exvector dummy_indices;
+ 		void update_dummy_indices(const exvector&);
+ };
+ 
+ safe_inserter::safe_inserter(const ex&e):epv(new epvector)
+ {
+ 	epv->reserve(e.nops());
+ 	bool dodummies=is_a<mul>(e);
+ 	if(dodummies)
+ 		dummy_indices = get_all_dummy_indices(e);
+ }
+ 
+ void safe_inserter::update_dummy_indices(const exvector &v)
+ {
+ 	exvector new_dummy_indices;
+ 	set_union(dummy_indices.begin(), dummy_indices.end(), v.begin(), v.end(),
+ 		std::back_insert_iterator<exvector>(new_dummy_indices), ex_is_less());
+ 	dummy_indices.swap(new_dummy_indices);
+ }
+ 
+ void safe_inserter::insert_new_factor(const ex&e)
+ {
+ 	if(!dodummies)
+ 	{	epv -> push_back(expair(e, _ex1));
+ 		return;
+ 	}
+ 	exvector dummies_of_factor = get_all_dummy_indices(e);
+ 	if(dummies_of_factor.size() == 0)
+ 	{	epv -> push_back(expair(e, _ex1));
+ 		return;
+ 	}
+ 	ex newfactor = rename_dummy_indices_uniquely(dummy_indices, dummies_of_factor, e);
+ 	update_dummy_indices(dummies_of_factor);
+ 	epv -> push_back(expair(newfactor, _ex1));
+ }
+ 
+ void safe_inserter::insert_new_pair(const expair &p)
+ {
+ 	if(!dodummies)
+ 	{
+ 		epv->push_back(p);
+ 		return;
+ 	}
+ 	exvector dummies_of_factor = get_all_dummy_indices(p.rest);
+ 	if(dummies_of_factor.size() == 0)
+ 	{	epv->push_back(p);
+ 		return;
+ 	}
+ 	ex newfactor = rename_dummy_indices_uniquely(dummy_indices, dummies_of_factor, p.rest);
+ 	update_dummy_indices(dummies_of_factor);
+ 	epv -> push_back(expair(newfactor, p.coeff));
+ }
  
  /** Member-wise substitute in this sequence.
   *
***************
*** 1614,1635 ****
  			if (!are_ex_trivially_equal(orig_ex, subsed_ex)) {
  
  				// Something changed, copy seq, subs and return it
! 				std::auto_ptr<epvector> s(new epvector);
! 				s->reserve(seq.size());
  
  				// Copy parts of seq which are known not to have changed
! 				s->insert(s->begin(), seq.begin(), cit);
  
  				// Copy first changed element
! 				s->push_back(split_ex_to_pair(subsed_ex));
  				++cit;
  
  				// Copy rest
  				while (cit != last) {
! 					s->push_back(split_ex_to_pair(recombine_pair_to_ex(*cit).subs(m, options)));
  					++cit;
  				}
! 				return s;
  			}
  
  			++cit;
--- 1705,1731 ----
  			if (!are_ex_trivially_equal(orig_ex, subsed_ex)) {
  
  				// Something changed, copy seq, subs and return it
! 				safe_inserter s(*this);
  
  				// Copy parts of seq which are known not to have changed
! 				for(epvector::const_iterator i=seq.begin(); i!=cit; ++i)
! 					s.insert_old_pair(*i);
  
  				// Copy first changed element
! 				s.insert_new_factor(subsed_ex);
  				++cit;
  
  				// Copy rest
  				while (cit != last) {
! 					ex orig_ex = recombine_pair_to_ex(*cit);
! 					ex subsed_ex = orig_ex.subs(m, options);
! 					if(are_ex_trivially_equal(orig_ex, subsed_ex))
! 						s.insert_old_factor(subsed_ex);
! 					else
! 						s.insert_new_factor(subsed_ex);
  					++cit;
  				}
! 				return s.getseq();
  			}
  
  			++cit;
***************
*** 1645,1667 ****
  			if (!are_ex_trivially_equal(cit->rest, subsed_ex)) {
  			
  				// Something changed, copy seq, subs and return it
! 				std::auto_ptr<epvector> s(new epvector);
! 				s->reserve(seq.size());
  
  				// Copy parts of seq which are known not to have changed
! 				s->insert(s->begin(), seq.begin(), cit);
  			
  				// Copy first changed element
! 				s->push_back(combine_ex_with_coeff_to_pair(subsed_ex, cit->coeff));
  				++cit;
  
  				// Copy rest
  				while (cit != last) {
! 					s->push_back(combine_ex_with_coeff_to_pair(cit->rest.subs(m, options),
! 					                                           cit->coeff));
  					++cit;
  				}
! 				return s;
  			}
  
  			++cit;
--- 1741,1767 ----
  			if (!are_ex_trivially_equal(cit->rest, subsed_ex)) {
  			
  				// Something changed, copy seq, subs and return it
! 				safe_inserter s(*this);
  
  				// Copy parts of seq which are known not to have changed
! 				for(epvector::const_iterator i=seq.begin(); i!=cit; ++i)
! 					s.insert_old_pair(*i);
  			
  				// Copy first changed element
! 				s.insert_new_pair(combine_ex_with_coeff_to_pair(subsed_ex, cit->coeff));
  				++cit;
  
  				// Copy rest
  				while (cit != last) {
! 					ex orig_ex = cit->rest;
! 					ex subsed_ex = orig_ex.subs(m, options);
! 					if(are_ex_trivially_equal(orig_ex, subsed_ex))
! 						s.insert_old_pair(*cit);
! 					else
! 						s.insert_new_pair(combine_ex_with_coeff_to_pair(subsed_ex, cit->coeff));
  					++cit;
  				}
! 				return s.getseq();
  			}
  
  			++cit;
