From: Christian Bauer Date: Sun, 27 May 2001 19:53:13 +0000 (+0000) Subject: - added symmetrize() and antisymmetrize() functions X-Git-Tag: release_0-9-0~32 X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=commitdiff_plain;h=0117bd6ef4af029934703940d59e1c70866937b0 - added symmetrize() and antisymmetrize() functions - generalized permutation_sign() template - moved shaker_sort() template to utils.h --- diff --git a/NEWS b/NEWS index d08e730e..ec456f49 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,7 @@ This file records noteworthy changes. optionally containing wildcard objects. These are constructed with the call "wild()" and are denoted as "$0", "$1" etc. in the output and in ginsh. +* Added symmetrize() and antisymmetrize() functions. * Fixed possible crash when calling subs() on expressions with non-commutative products. diff --git a/check/exam_indexed.cpp b/check/exam_indexed.cpp index 10eb3d01..75a99e51 100644 --- a/check/exam_indexed.cpp +++ b/check/exam_indexed.cpp @@ -161,6 +161,15 @@ static unsigned symmetry_check(void) indexed(B, indexed::antisymmetric, k, l); // GiNaC 0.8.0 had a bug here result += check_equal_simplify(e, e); + e = indexed(A, i, j); + result += check_equal(symmetrize(e) + antisymmetrize(e), e); + e = indexed(A, indexed::symmetric, i, j, k, l); + result += check_equal(symmetrize(e), e); + result += check_equal(antisymmetrize(e), 0); + e = indexed(A, indexed::antisymmetric, i, j, k, l); + result += check_equal(symmetrize(e), 0); + result += check_equal(antisymmetrize(e), e); + return result; } diff --git a/ginac/clifford.cpp b/ginac/clifford.cpp index e9b50e9a..b5dff072 100644 --- a/ginac/clifford.cpp +++ b/ginac/clifford.cpp @@ -446,7 +446,7 @@ ex dirac_trace(const ex & e, unsigned char rl, const ex & trONE) iv.push_back(n); v.push_back(e.op(n)); } - int sign = permutation_sign(iv); + int sign = permutation_sign(iv.begin(), iv.end()); result += sign * eps0123(idx1, idx2, idx3, idx4) * dirac_trace(ncmul(v, true), rl, trONE); } diff --git a/ginac/idx.cpp b/ginac/idx.cpp index 7088c5bd..c72e478e 100644 --- a/ginac/idx.cpp +++ b/ginac/idx.cpp @@ -472,36 +472,6 @@ bool is_dummy_pair(const ex & e1, const ex & e2) return is_dummy_pair(ex_to_idx(e1), ex_to_idx(e2)); } -// Shaker sort is sufficient for the expected small number of indices -template -inline void shaker_sort(It first, It last, Cmp comp) -{ - if (first == last) - return; - --last; - if (first == last) - return; - It flag = first; - do { - It i; - for (i=last; i>first; --i) { - if (comp(*i, i[-1])) { - iter_swap(i-1, i); - flag = i - 1; - } - } - ++flag; - first = flag; - for (i=first; i pre_sort; for (std::vector::iterator i=c_zeros.begin(); i!=c_zeros.end(); ++i) pre_sort.push_back(i->second); - int sign = permutation_sign(pre_sort); + int sign = permutation_sign(pre_sort.begin(), pre_sort.end()); exvector result(row*col); // represents sorted matrix unsigned c = 0; for (std::vector::iterator i=pre_sort.begin(); diff --git a/ginac/tensor.cpp b/ginac/tensor.cpp index 23be5b0b..f4e49451 100644 --- a/ginac/tensor.cpp +++ b/ginac/tensor.cpp @@ -305,7 +305,7 @@ ex tensepsilon::eval_indexed(const basic & i) const v.reserve(i.nops() - 1); for (unsigned j=1; j -int permutation_sign(std::vector s) +/* Compute the sign of a permutation of a container, with and without an + explicitly supplied comparison function. The containers gets modified + during the operation. */ +template +int permutation_sign(It first, It last) { - if (s.size() < 2) + if (first == last) return 0; - int sigma = 1; - for (typename std::vector::iterator i=s.begin(); i!=s.end()-1; ++i) { - for (typename std::vector::iterator j=i+1; j!=s.end(); ++j) { - if (*i == *j) - return 0; - if (*i > *j) { - iter_swap(i,j); - sigma = -sigma; + It i = first; + ++i; + if (i == last) + return 0; + i = first; + It next_to_last = last; + --next_to_last; + + int sign = 1; + while (i != next_to_last) { + It j = i; + ++j; + while (j != last) { + if (!(*i < *j)) { + if (!(*j < *i)) + return 0; + iter_swap(i, j); + sign = -sign; + } + ++j; + } + ++i; + } + return sign; +} + +/** Compute the sign of a permutation of a container */ +template +int permutation_sign(It first, It last, Cmp comp) +{ + if (first == last) + return 0; + It i = first; + ++i; + if (i == last) + return 0; + i = first; + It next_to_last = last; + --next_to_last; + + int sign = 1; + while (i != next_to_last) { + It j = i; + ++j; + while (j != last) { + if (!comp(*i, *j)) { + if (!comp(*j, *i)) + return 0; + iter_swap(i, j); + sign = -sign; } + ++j; } + ++i; } - return sigma; + return sign; +} + +/* Implementation of shaker sort, only compares adjacent elements. */ +template +inline void shaker_sort(It first, It last, Cmp comp) +{ + if (first == last) + return; + --last; + if (first == last) + return; + It flag = first; + do { + It i = last, other = last; + --other; + while (i > first) { + if (comp(*i, *other)) { + iter_swap(other, i); + flag = other; + } + --i; --other; + } + ++flag; + first = flag; + i = first; other = first; + ++other; + while (i < last) { + if (comp(*other, *i)) { + iter_swap(i, other); + flag = other; + } + ++i; ++other; + } + last = flag; + --last; + } while (first <= last); } /* Function objects for STL sort() etc. */