[GiNaC-devel] [PATCH 2/4] Tell mul::expand() to not rename_indices_... if object has no indices at all.

Alexei Sheplyakov varg at theor.jinr.ru
Mon Sep 17 15:19:40 CEST 2007


Patially solves performance regression in expand(), gcd(), etc.

---
 ginac/mul.cpp |   56 ++++++++++++++++++++++++++++++++++----------------------
 1 files changed, 34 insertions(+), 22 deletions(-)

diff --git a/ginac/mul.cpp b/ginac/mul.cpp
index 9ed27c6..db8b9f1 100644
--- a/ginac/mul.cpp
+++ b/ginac/mul.cpp
@@ -992,6 +992,7 @@ bool mul::can_be_further_expanded(const ex & e)
 
 ex mul::expand(unsigned options) const
 {
+	const bool skip_idx_rename = ! info(info_flags::has_indices);
 	// First, expand the children
 	std::auto_ptr<epvector> expanded_seqp = expandchildren(options);
 	const epvector & expanded_seq = (expanded_seqp.get() ? *expanded_seqp : seq);
@@ -1047,28 +1048,34 @@ ex mul::expand(unsigned options) const
 				ex tmp_accu = (new add(distrseq, add1.overall_coeff*add2.overall_coeff))->setflag(status_flags::dynallocated);
 
 				exvector add1_dummy_indices, add2_dummy_indices, add_indices;
+				lst dummy_subs;
 
-				for (epvector::const_iterator i=add1begin; i!=add1end; ++i) {
-					add_indices = get_all_dummy_indices_safely(i->rest);
-					add1_dummy_indices.insert(add1_dummy_indices.end(), add_indices.begin(), add_indices.end());
-				}
-				for (epvector::const_iterator i=add2begin; i!=add2end; ++i) {
-					add_indices = get_all_dummy_indices_safely(i->rest);
-					add2_dummy_indices.insert(add2_dummy_indices.end(), add_indices.begin(), add_indices.end());
-				}
+				if (!skip_idx_rename) {
+					for (epvector::const_iterator i=add1begin; i!=add1end; ++i) {
+						add_indices = get_all_dummy_indices_safely(i->rest);
+						add1_dummy_indices.insert(add1_dummy_indices.end(), add_indices.begin(), add_indices.end());
+					}
+					for (epvector::const_iterator i=add2begin; i!=add2end; ++i) {
+						add_indices = get_all_dummy_indices_safely(i->rest);
+						add2_dummy_indices.insert(add2_dummy_indices.end(), add_indices.begin(), add_indices.end());
+					}
 
-				sort(add1_dummy_indices.begin(), add1_dummy_indices.end(), ex_is_less());
-				sort(add2_dummy_indices.begin(), add2_dummy_indices.end(), ex_is_less());
-				lst dummy_subs = rename_dummy_indices_uniquely(add1_dummy_indices, add2_dummy_indices);
+					sort(add1_dummy_indices.begin(), add1_dummy_indices.end(), ex_is_less());
+					sort(add2_dummy_indices.begin(), add2_dummy_indices.end(), ex_is_less());
+					dummy_subs = rename_dummy_indices_uniquely(add1_dummy_indices, add2_dummy_indices);
+				}
 
 				// Multiply explicitly all non-numeric terms of add1 and add2:
 				for (epvector::const_iterator i2=add2begin; i2!=add2end; ++i2) {
 					// We really have to combine terms here in order to compactify
 					// the result.  Otherwise it would become waayy tooo bigg.
-					numeric oc;
-					distrseq.clear();
-					ex i2_new = (dummy_subs.op(0).nops()>0? 
-								 i2->rest.subs((lst)dummy_subs.op(0), (lst)dummy_subs.op(1), subs_options::no_pattern) : i2->rest);
+					numeric oc(*_num0_p);
+					epvector distrseq2;
+					distrseq2.reserve(add1.seq.size());
+					const ex i2_new = (skip_idx_rename || (dummy_subs.op(0).nops() == 0) ?
+							i2->rest :
+							i2->rest.subs(ex_to<lst>(dummy_subs.op(0)), 
+								ex_to<lst>(dummy_subs.op(1)), subs_options::no_pattern));
 					for (epvector::const_iterator i1=add1begin; i1!=add1end; ++i1) {
 						// Don't push_back expairs which might have a rest that evaluates to a numeric,
 						// since that would violate an invariant of expairseq:
@@ -1076,13 +1083,12 @@ ex mul::expand(unsigned options) const
 						if (is_exactly_a<numeric>(rest)) {
 							oc += ex_to<numeric>(rest).mul(ex_to<numeric>(i1->coeff).mul(ex_to<numeric>(i2->coeff)));
 						} else {
-							distrseq.push_back(expair(rest, ex_to<numeric>(i1->coeff).mul_dyn(ex_to<numeric>(i2->coeff))));
+							distrseq2.push_back(expair(rest, ex_to<numeric>(i1->coeff).mul_dyn(ex_to<numeric>(i2->coeff))));
 						}
 					}
-					tmp_accu += (new add(distrseq, oc))->setflag(status_flags::dynallocated);
-				}
+					tmp_accu += (new add(distrseq2, oc))->setflag(status_flags::dynallocated);
+				} 
 				last_expanded = tmp_accu;
-
 			} else {
 				if (!last_expanded.is_equal(_ex1))
 					non_adds.push_back(split_ex_to_pair(last_expanded));
@@ -1100,12 +1106,18 @@ ex mul::expand(unsigned options) const
 		size_t n = last_expanded.nops();
 		exvector distrseq;
 		distrseq.reserve(n);
-		exvector va = get_all_dummy_indices_safely(mul(non_adds));
-		sort(va.begin(), va.end(), ex_is_less());
+		exvector va;
+		if (! skip_idx_rename) {
+			va = get_all_dummy_indices_safely(mul(non_adds));
+			sort(va.begin(), va.end(), ex_is_less());
+		}
 
 		for (size_t i=0; i<n; ++i) {
 			epvector factors = non_adds;
-			factors.push_back(split_ex_to_pair(rename_dummy_indices_uniquely(va, last_expanded.op(i))));
+			if (skip_idx_rename)
+				factors.push_back(split_ex_to_pair(last_expanded.op(i)));
+			else
+				factors.push_back(split_ex_to_pair(rename_dummy_indices_uniquely(va, last_expanded.op(i))));
 			ex term = (new mul(factors, overall_coeff))->setflag(status_flags::dynallocated);
 			if (can_be_further_expanded(term)) {
 				distrseq.push_back(term.expand());
-- 
1.5.2.4

Best regards,
  Alexei

-- 
All science is either physics or stamp collecting.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 827 bytes
Desc: Digital signature
Url : http://www.cebix.net/pipermail/ginac-devel/attachments/20070917/82baf266/attachment.pgp


More information about the GiNaC-devel mailing list