From c5ca06e3a25226684028dec4bd8cba0833998be6 Mon Sep 17 00:00:00 2001 From: Christian Bauer Date: Sat, 9 Jun 2001 19:17:32 +0000 Subject: [PATCH] - added lst::remove_first() and lst::remove_last() - added symmetrize_cyclic() - antisymmetrize() is slightly faster - ensure_if_modifiable() clears the hash_calculated flag --- NEWS | 4 +++ doc/tutorial/ginac.texi | 35 ++++++++++++++++------- ginac/basic.cpp | 1 + ginac/container.pl | 15 ++++++++++ ginac/ex.h | 8 ++++++ ginac/indexed.cpp | 6 ++++ ginac/inifcns.cpp | 62 +++++++++++++++++++++++++++++++++++------ ginac/inifcns.h | 11 ++++++++ ginac/matrix.cpp | 1 - ginac/utils.h | 33 ++++++++++++++++++++++ 10 files changed, 157 insertions(+), 19 deletions(-) diff --git a/NEWS b/NEWS index 3788916d..b69ad3f6 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,9 @@ This file records noteworthy changes. +0.9.1 () +* Added remove_first() and remove_last() methods for lists. +* Added symmetrize_cyclic(). + 0.9.0 (7 June 2001) * In the output and in ginsh, lists are now delimited by { } braces, and matrices are delimited by single [ ] brackets. diff --git a/doc/tutorial/ginac.texi b/doc/tutorial/ginac.texi index 5511a2d1..9411950f 100644 --- a/doc/tutorial/ginac.texi +++ b/doc/tutorial/ginac.texi @@ -1135,6 +1135,8 @@ canonical form. @cindex @code{op()} @cindex @code{append()} @cindex @code{prepend()} +@cindex @code{remove_first()} +@cindex @code{remove_last()} The GiNaC class @code{lst} serves for holding a @dfn{list} of arbitrary expressions. These are sometimes used to supply a variable number of @@ -1162,13 +1164,23 @@ a list and the @code{op()} method to access individual elements: // ... @end example -Finally you can append or prepend an expression to a list with the -@code{append()} and @code{prepend()} methods: +You can append or prepend an expression to a list with the @code{append()} +and @code{prepend()} methods: @example // ... l.append(4*x); // l is now @{x, 2, y, x+y, 4*x@} l.prepend(0); // l is now @{0, x, 2, y, x+y, 4*x@} + // ... +@end example + +Finally you can remove the first or last element of a list with +@code{remove_first()} and @code{remove_last()}: + +@example + // ... + l.remove_first(); // l is now @{x, 2, y, x+y, 4*x@} + l.remove_last(); // l is now @{x, 2, y, x+y@} @} @end example @@ -3541,23 +3553,26 @@ program, it will type out: @section Symmetrization @cindex @code{symmetrize()} @cindex @code{antisymmetrize()} +@cindex @code{symmetrize_cyclic()} -The two methods +The three methods @example ex ex::symmetrize(const lst & l); ex ex::antisymmetrize(const lst & l); +ex ex::symmetrize_cyclic(const lst & l); @end example -symmetrize an expression by returning the symmetric or antisymmetric sum -over all permutations of the specified list of objects, weighted by the -number of permutations. +symmetrize an expression by returning the sum over all symmetric, +antisymmetric or cyclic permutations of the specified list of objects, +weighted by the number of permutations. -The two additional methods +The three additional methods @example ex ex::symmetrize(); ex ex::antisymmetrize(); +ex ex::symmetrize_cyclic(); @end example symmetrize or antisymmetrize an expression over its free indices. @@ -3574,8 +3589,8 @@ almost any kind of object (anything that is @code{subs()}able): // -> 1/2*A.j.i+1/2*A.i.j cout << indexed(A, i, j, k).antisymmetrize(lst(i, j)) << endl; // -> -1/2*A.j.i.k+1/2*A.i.j.k - cout << lst(a, b, c).symmetrize(lst(a, b, c)) << endl; - // -> 1/6*@{a,b,c@}+1/6*@{c,a,b@}+1/6*@{b,a,c@}+1/6*@{c,b,a@}+1/6*@{b,c,a@}+1/6*@{a,c,b@} + cout << lst(a, b, c).symmetrize_cyclic(lst(a, b, c)) << endl; + // -> 1/3*@{a,b,c@}+1/3*@{b,c,a@}+1/3*@{c,a,b@} @} @end example @@ -4588,7 +4603,7 @@ cout << e << endl; // -> "GiNaC rulez"+"Hello, world!" @end example -(note that GiNaC's automatic term reordering is in effect here), or even +(GiNaC's automatic term reordering is in effect here), or even @example e = pow(mystring("One string"), 2*sin(Pi-mystring("Another string"))); diff --git a/ginac/basic.cpp b/ginac/basic.cpp index 2b1b68b0..a2e10f71 100644 --- a/ginac/basic.cpp +++ b/ginac/basic.cpp @@ -732,6 +732,7 @@ void basic::ensure_if_modifiable(void) const { if (this->refcount>1) throw(std::runtime_error("cannot modify multiply referenced object")); + clearflag(status_flags::hash_calculated); } ////////// diff --git a/ginac/container.pl b/ginac/container.pl index 480d5a56..27546155 100755 --- a/ginac/container.pl +++ b/ginac/container.pl @@ -54,6 +54,7 @@ if ($reserve) { if ($prepend) { $PREPEND_INTERFACE=<simplify_ncmul(v); } ex operator[](const ex & index) const; ex operator[](int i) const; @@ -412,6 +414,12 @@ inline ex antisymmetrize(const ex & thisex) inline ex antisymmetrize(const ex & thisex, const lst & l) { return thisex.antisymmetrize(l); } +inline ex symmetrize_cyclic(const ex & thisex) +{ return thisex.symmetrize_cyclic(); } + +inline ex symmetrize_cyclic(const ex & thisex, const lst & l) +{ return thisex.symmetrize_cyclic(l); } + inline ex op(const ex & thisex, int i) { return thisex.op(i); } diff --git a/ginac/indexed.cpp b/ginac/indexed.cpp index 90e3d4c3..3f2cb717 100644 --- a/ginac/indexed.cpp +++ b/ginac/indexed.cpp @@ -852,6 +852,12 @@ ex ex::antisymmetrize(void) const return GiNaC::antisymmetrize(*this, get_free_indices()); } +/** Symmetrize expression by cyclic permutation over its free indices. */ +ex ex::symmetrize_cyclic(void) const +{ + return GiNaC::symmetrize_cyclic(*this, get_free_indices()); +} + ////////// // helper classes ////////// diff --git a/ginac/inifcns.cpp b/ginac/inifcns.cpp index 4d1c978b..0ee9b273 100644 --- a/ginac/inifcns.cpp +++ b/ginac/inifcns.cpp @@ -517,24 +517,35 @@ static ex symm(const ex & e, exvector::const_iterator first, exvector::const_ite if (num < 2) return e; - // Sort object vector, transform it into a list, and make a copy so we - // will know which objects get substituted for which + // Transform object vector to a list exlist iv_lst; iv_lst.insert(iv_lst.begin(), first, last); - shaker_sort(iv_lst.begin(), iv_lst.end(), ex_is_less()); - lst orig_lst(iv_lst); + lst orig_lst(iv_lst, true); + + // Create index vectors for permutation + unsigned *iv = new unsigned[num], *iv2; + for (unsigned i=0; i +void cyclic_permutation(It first, It last, It new_first) +{ + unsigned num = last - first; +again: + if (first == new_first || num < 2) + return; + + unsigned num1 = new_first - first, num2 = last - new_first; + if (num1 >= num2) { + It a = first, b = new_first; + while (b != last) { + std::iter_swap(a, b); + ++a; ++b; + } + if (num1 > num2) { + first += num2; + num = num1; + goto again; + } + } else { + It a = new_first, b = last; + do { + --a; --b; + std::iter_swap(a, b); + } while (a != first); + last -= num1; + num = num2; + goto again; + } +} + /* Function objects for STL sort() etc. */ struct ex_is_less : public std::binary_function { bool operator() (const ex &lh, const ex &rh) const { return lh.compare(rh) < 0; } -- 2.44.0