+ // If the sum turns out to be zero, we are finished
+ if (sum.is_zero()) {
+ free_indices.clear();
+ return sum;
+ }
+
+ // Symmetrizing over the dummy indices may cancel terms
+ int num_terms_orig = (is_exactly_a<add>(sum) ? sum.nops() : 1);
+ if (num_terms_orig > 1 && dummy_indices.size() >= 2) {
+
+ // Construct list of all dummy index symbols
+ lst dummy_syms;
+ for (int i=0; i<dummy_indices.size(); i++)
+ dummy_syms.append(dummy_indices[i].op(0));
+
+ // Symmetrize each term separately and store the resulting
+ // terms in a list of symminfo structures
+ std::vector<symminfo> v;
+ for (int i=0; i<sum.nops(); i++) {
+ ex sum_symm = sum.op(i).symmetrize(dummy_syms);
+ if (sum_symm.is_zero())
+ continue;
+ if (is_exactly_a<add>(sum_symm))
+ for (int j=0; j<sum_symm.nops(); j++)
+ v.push_back(symminfo(sum_symm.op(j), sum.op(i), sum_symm.nops()));
+ else
+ v.push_back(symminfo(sum_symm, sum.op(i), 1));
+ }
+
+ // Now add up all the unsymmetrized versions of the terms that
+ // did not cancel out in the symmetrization
+ exvector result;
+ std::sort(v.begin(), v.end(), symminfo_is_less_by_symmterm());
+
+ std::vector<symminfo> v_pass2;
+ for (std::vector<symminfo>::const_iterator i=v.begin(); i!=v.end(); ) {
+
+ // Combine equal terms
+ std::vector<symminfo>::const_iterator j = i + 1;
+ if (j != v.end() && j->symmterm == i->symmterm) {
+
+ // More than one term, collect the coefficients
+ ex coeff = i->coeff;
+ while (j != v.end() && j->symmterm == i->symmterm) {
+ coeff += j->coeff;
+ j++;
+ }
+
+ // Add combined term to result
+ if (!coeff.is_zero())
+ result.push_back(coeff * i->symmterm);
+
+ } else {
+
+ // Single term, store for second pass
+ v_pass2.push_back(*i);
+ }
+
+ i = j;
+ }
+
+ // Were there any remaining terms that didn't get combined?
+ if (v_pass2.size() > 0) {
+
+ // Yes, sort them by their original term
+ std::sort(v_pass2.begin(), v_pass2.end(), symminfo_is_less_by_orig());
+
+ for (std::vector<symminfo>::const_iterator i=v_pass2.begin(); i!=v_pass2.end(); ) {
+
+ // How many symmetrized terms of this original term are left?
+ unsigned num = 1;
+ std::vector<symminfo>::const_iterator j = i + 1;
+ while (j != v_pass2.end() && j->orig == i->orig) {
+ num++;
+ j++;
+ }
+
+ if (num == i->num) {
+
+ // All terms left, then add the original term to the result
+ result.push_back(i->orig);
+
+ } else {
+
+ // Some terms were combined with others, add up the remaining symmetrized terms
+ std::vector<symminfo>::const_iterator k;
+ for (k=i; k!=j; k++)
+ result.push_back(k->coeff * k->symmterm);
+ }
+
+ i = j;
+ }
+ }
+
+ // Add all resulting terms
+ ex sum_symm = (new add(result))->setflag(status_flags::dynallocated);
+ if (sum_symm.is_zero())
+ free_indices.clear();
+ return sum_symm;
+ }
+