X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Futils.h;h=ac7aecdfacf5a128fd1aa73f238f5d42cd065fa4;hp=79719feb9e2131ae166f05ce810f38253b657c2d;hb=2700b3fa9c3a81236e8ceccb6aa9d5ea5848a1a0;hpb=f7a07ae7330a3543bb00aa7b659e2624d6c440c7 diff --git a/ginac/utils.h b/ginac/utils.h index 79719feb..ac7aecdf 100644 --- a/ginac/utils.h +++ b/ginac/utils.h @@ -24,10 +24,18 @@ #ifndef __GINAC_UTILS_H__ #define __GINAC_UTILS_H__ -#include +#include "config.h" + #include #include -#include "config.h" +#include +#if defined(HAVE_SSTREAM) +#include +#elif defined(HAVE_STRSTREAM) +#include +#else +#error Need either sstream or strstream +#endif #include "assertion.h" namespace GiNaC { @@ -36,9 +44,15 @@ namespace GiNaC { template std::string ToString(const T & t) { +#if defined(HAVE_SSTREAM) + std::ostringstream buf; + buf << t << std::ends; + return buf.str(); +#else char buf[256]; std::ostrstream(buf,sizeof(buf)) << t << std::ends; return buf; +#endif } /** Exception class thrown by classes which provide their own series expansion @@ -113,27 +127,170 @@ inline unsigned golden_ratio_hash(unsigned n) #endif } -// Compute the sign of a permutation of a vector of things. -template -int permutation_sign(std::vector s) +/* Compute the sign of a permutation of a container, with and without an + explicitly supplied comparison function. If the sign returned is 1 or -1, + the container is sorted after 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) + --last; + if (first == last) + return 0; + It flag = first; + int sign = 1; + + do { + It i = last, other = last; + --other; + bool swapped = false; + while (i != first) { + if (*i < *other) { + iter_swap(other, i); + flag = other; + swapped = true; + sign = -sign; + } else if (!(*other < *i)) return 0; - if (*i > *j) { - iter_swap(i,j); - sigma = -sigma; + --i; --other; + } + if (!swapped) + return sign; + ++flag; + if (flag == last) + return sign; + first = flag; + i = first; other = first; + ++other; + swapped = false; + while (i != last) { + if (*other < *i) { + iter_swap(i, other); + flag = other; + swapped = true; + sign = -sign; + } else if (!(*i < *other)) + return 0; + ++i; ++other; + } + if (!swapped) + return sign; + last = flag; + --last; + } while (first != last); + + return sign; +} + +template +int permutation_sign(It first, It last, Cmp comp) +{ + if (first == last) + return 0; + --last; + if (first == last) + return 0; + It flag = first; + int sign = 1; + + do { + It i = last, other = last; + --other; + bool swapped = false; + while (i != first) { + if (comp(*i, *other)) { + iter_swap(other, i); + flag = other; + swapped = true; + sign = -sign; + } else if (!comp(*other, *i)) + return 0; + --i; --other; + } + if (!swapped) + return sign; + ++flag; + if (flag == last) + return sign; + first = flag; + i = first; other = first; + ++other; + swapped = false; + while (i != last) { + if (comp(*other, *i)) { + iter_swap(i, other); + flag = other; + swapped = true; + sign = -sign; + } else if (!comp(*i, *other)) + return 0; + ++i; ++other; + } + if (!swapped) + return sign; + last = flag; + --last; + } while (first != last); + + return sign; +} + +/* Implementation of shaker sort, only compares adjacent elements. */ +template +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; + bool swapped = false; + while (i != first) { + if (comp(*i, *other)) { + iter_swap(other, i); + flag = other; + swapped = true; + } + --i; --other; + } + if (!swapped) + return; + ++flag; + if (flag == last) + return; + first = flag; + i = first; other = first; + ++other; + swapped = false; + while (i != last) { + if (comp(*other, *i)) { + iter_swap(i, other); + flag = other; + swapped = true; } + ++i; ++other; } - } - return sigma; + if (!swapped) + return; + last = flag; + --last; + } while (first != last); } -void append_exvector_to_exvector(exvector & dest, const exvector & source); +/* Function objects for STL sort() etc. */ +struct ex_is_less : public binary_function { + bool operator() (const ex &lh, const ex &rh) const { return lh.compare(rh) < 0; } +}; + +struct ex_is_equal : public binary_function { + bool operator() (const ex &lh, const ex &rh) const { return lh.is_equal(rh); } +}; // Collection of `construct on first use' wrappers for safely avoiding // internal object replication without running into the `static