- epvector::const_iterator cit = expanded_seq.begin();
- epvector::const_iterator last = expanded_seq.end();
- ex last_expanded = _ex1();
- while (cit!=last) {
- if (is_ex_exactly_of_type((*cit).rest,add) &&
- ((*cit).coeff.is_equal(_ex1()))) {
- ++number_of_adds;
- if (is_ex_exactly_of_type(last_expanded,add)) {
- // expand adds
- const add & add1 = ex_to_add(last_expanded);
- const add & add2 = ex_to_add((*cit).rest);
- int n1 = add1.nops();
- int n2 = add2.nops();
- exvector distrseq;
- distrseq.reserve(n1*n2);
- for (int i1=0; i1<n1; ++i1) {
- for (int i2=0; i2<n2; ++i2) {
- distrseq.push_back(add1.op(i1)*add2.op(i2));
+
+ for (epvector::const_iterator cit = expanded_seq.begin(); cit != expanded_seq.end(); ++cit) {
+ if (is_exactly_a<add>(cit->rest) &&
+ (cit->coeff.is_equal(_ex1))) {
+ if (is_exactly_a<add>(last_expanded)) {
+
+ // Expand a product of two sums, aggressive version.
+ // Caring for the overall coefficients in separate loops can
+ // sometimes give a performance gain of up to 15%!
+
+ const int sizedifference = ex_to<add>(last_expanded).seq.size()-ex_to<add>(cit->rest).seq.size();
+ // add2 is for the inner loop and should be the bigger of the two sums
+ // in the presence of asymptotically good sorting:
+ const add& add1 = (sizedifference<0 ? ex_to<add>(last_expanded) : ex_to<add>(cit->rest));
+ const add& add2 = (sizedifference<0 ? ex_to<add>(cit->rest) : ex_to<add>(last_expanded));
+ const epvector::const_iterator add1begin = add1.seq.begin();
+ const epvector::const_iterator add1end = add1.seq.end();
+ const epvector::const_iterator add2begin = add2.seq.begin();
+ const epvector::const_iterator add2end = add2.seq.end();
+ epvector distrseq;
+ distrseq.reserve(add1.seq.size()+add2.seq.size());
+
+ // Multiply add2 with the overall coefficient of add1 and append it to distrseq:
+ if (!add1.overall_coeff.is_zero()) {
+ if (add1.overall_coeff.is_equal(_ex1))
+ distrseq.insert(distrseq.end(),add2begin,add2end);
+ else
+ for (epvector::const_iterator i=add2begin; i!=add2end; ++i)
+ distrseq.push_back(expair(i->rest, ex_to<numeric>(i->coeff).mul_dyn(ex_to<numeric>(add1.overall_coeff))));
+ }
+
+ // Multiply add1 with the overall coefficient of add2 and append it to distrseq:
+ if (!add2.overall_coeff.is_zero()) {
+ if (add2.overall_coeff.is_equal(_ex1))
+ distrseq.insert(distrseq.end(),add1begin,add1end);
+ else
+ for (epvector::const_iterator i=add1begin; i!=add1end; ++i)
+ distrseq.push_back(expair(i->rest, ex_to<numeric>(i->coeff).mul_dyn(ex_to<numeric>(add2.overall_coeff))));
+ }
+
+ // Compute the new overall coefficient and put it together:
+ 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;
+
+ 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());