]> www.ginac.de Git - ginac.git/blobdiff - ginac/utils.h
- permutation_sign() and shaker_sort() are no longer inlined
[ginac.git] / ginac / utils.h
index 79719feb9e2131ae166f05ce810f38253b657c2d..ac7aecdfacf5a128fd1aa73f238f5d42cd065fa4 100644 (file)
 #ifndef __GINAC_UTILS_H__
 #define __GINAC_UTILS_H__
 
-#include <strstream>
+#include "config.h"
+
 #include <string>
 #include <stdexcept>
-#include "config.h"
+#include <functional>
+#if defined(HAVE_SSTREAM)
+#include <sstream>
+#elif defined(HAVE_STRSTREAM)
+#include <strstream>
+#else
+#error Need either sstream or strstream
+#endif
 #include "assertion.h"
 
 namespace GiNaC {
@@ -36,9 +44,15 @@ namespace GiNaC {
 template<class T>
 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 <typename T>
-int permutation_sign(std::vector<T> 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 <class It>
+int permutation_sign(It first, It last)
 {
-       if (s.size() < 2)
+       if (first == last)
                return 0;
-       int sigma = 1;
-       for (typename std::vector<T>::iterator i=s.begin(); i!=s.end()-1; ++i) {
-               for (typename std::vector<T>::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 <class It, class Cmp>
+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 <class It, class Cmp>
+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<ex, ex, bool> {
+       bool operator() (const ex &lh, const ex &rh) const { return lh.compare(rh) < 0; }
+};
+
+struct ex_is_equal : public binary_function<ex, ex, bool> {
+       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