-int canonicalize_indices(exvector & iv, bool antisymmetric)
-{
- if (iv.size()<2) {
- // nothing do to for 0 or 1 indices
- return INT_MAX;
- }
-
- bool something_changed=false;
- int sig=1;
- // simple bubble sort algorithm should be sufficient for the small number of indices needed
- exvector::const_iterator last_idx=iv.end();
- exvector::const_iterator next_to_last_idx=iv.end()-1;
- for (exvector::iterator it1=iv.begin(); it1!=next_to_last_idx; ++it1) {
- for (exvector::iterator it2=it1+1; it2!=last_idx; ++it2) {
- int cmpval=(*it1).compare(*it2);
- if (cmpval==1) {
- iter_swap(it1,it2);
- something_changed=true;
- if (antisymmetric) sig=-sig;
- } else if ((cmpval==0) && antisymmetric) {
- something_changed=true;
- sig=0;
- }
- }
- }
- return something_changed ? sig : INT_MAX;
-}
-
-exvector idx_intersect(exvector const & iv1, exvector const & iv2)
-{
- // build a vector of symbolic indices contained in iv1 and iv2 simultaneously
- // assumes (but does not test) that each index occurs at most twice
- exvector iv_intersect;
- for (exvector::const_iterator cit1=iv1.begin(); cit1!=iv1.end(); ++cit1) {
- GINAC_ASSERT(is_ex_of_type(*cit1,idx));
- if (ex_to_idx(*cit1).is_symbolic()) {
- for (exvector::const_iterator cit2=iv2.begin(); cit2!=iv2.end(); ++cit2) {
- GINAC_ASSERT(is_ex_of_type(*cit2,idx));
- if ((*cit1).is_equal(*cit2)) {
- iv_intersect.push_back(*cit1);
- break;
- }
- }
- }
- }
- return iv_intersect;
-}
-
-#define TEST_PERMUTATION(A,B,C,P) \
- if ((iv3[B].is_equal(iv2[0]))&&(iv3[C].is_equal(iv2[1]))) { \
- if (antisymmetric) *sig=P; \
- return iv3[A]; \
- }
-
-ex permute_free_index_to_front(exvector const & iv3, exvector const & iv2,
- bool antisymmetric, int * sig)
-{
- // match (return value,iv2) to iv3 by permuting indices
- // iv3 is always cyclic
-
- GINAC_ASSERT(iv3.size()==3);
- GINAC_ASSERT(iv2.size()==2);
-
- *sig=1;
-
- TEST_PERMUTATION(0,1,2, 1);
- TEST_PERMUTATION(0,2,1, -1);
- TEST_PERMUTATION(1,0,2, -1);
- TEST_PERMUTATION(1,2,0, 1);
- TEST_PERMUTATION(2,0,1, 1);
- TEST_PERMUTATION(2,1,0, -1);
- throw(std::logic_error("permute_free_index_to_front(): no valid permutation found"));
-}
-
-unsigned subs_index_in_exvector(exvector & v, ex const & is, ex const & ir)
-{
- exvector::iterator it;
- unsigned replacements=0;
- unsigned current_replacements;
-
- GINAC_ASSERT(is_ex_of_type(is,idx));
- GINAC_ASSERT(is_ex_of_type(ir,idx));
-
- for (it=v.begin(); it!=v.end(); ++it) {
- current_replacements=count_index(*it,is);
- if (current_replacements>0) {
- (*it)=(*it).subs(is==ir);
- }
- replacements += current_replacements;
- }
- return replacements;
-}
-
-unsigned count_index(ex const & e, ex const & i)
-{
- exvector idxv=e.get_indices();
- unsigned count=0;
- for (exvector::const_iterator cit=idxv.begin(); cit!=idxv.end(); ++cit) {
- if ((*cit).is_equal(i)) count++;
- }
- return count;
-}
-
-ex subs_indices(ex const & e, exvector const & idxv_subs,
- exvector const & idxv_repl)
-{
- GINAC_ASSERT(idxv_subs.size()==idxv_repl.size());
- ex res=e;
- for (unsigned i=0; i<idxv_subs.size(); ++i) {
- res=res.subs(idxv_subs[i]==idxv_repl[i]);
- }
- return res;
-}
-
-#ifndef NO_GINAC_NAMESPACE