]> www.ginac.de Git - ginac.git/blobdiff - ginac/utils.h
- adjust for 0.9.2, close open bugreports.
[ginac.git] / ginac / utils.h
index c0bc2efecf49c00ec10328bc5b51674b00341acb..78334b17d25ac4047b5a7d35eef4e83841b0edb1 100644 (file)
 
 #include <string>
 #include <stdexcept>
-#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 {
 
-// This should be obsoleted once <sstream> is widely deployed.
-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
  *  to signal that ordinary Taylor expansion is safe. */
 class do_taylor {};
 
+/** Exception class thrown by functions to signal unimplemented functionality
+ *  so the expression may just be .hold() */
+class dunno {};
+
 /** Exception class thrown when a singularity is encountered. */
 class pole_error : public std::domain_error {
 public:
@@ -131,7 +112,7 @@ inline unsigned golden_ratio_hash(unsigned n)
    explicitly supplied comparison function. If the sign returned is 1 or -1,
    the container is sorted after the operation. */
 template <class It>
-inline int permutation_sign(It first, It last)
+int permutation_sign(It first, It last)
 {
        if (first == last)
                return 0;
@@ -147,7 +128,7 @@ inline int permutation_sign(It first, It last)
                bool swapped = false;
                while (i != first) {
                        if (*i < *other) {
-                               iter_swap(other, i);
+                               std::iter_swap(other, i);
                                flag = other;
                                swapped = true;
                                sign = -sign;
@@ -166,7 +147,7 @@ inline int permutation_sign(It first, It last)
                swapped = false;
                while (i != last) {
                        if (*other < *i) {
-                               iter_swap(i, other);
+                               std::iter_swap(i, other);
                                flag = other;
                                swapped = true;
                                sign = -sign;
@@ -183,8 +164,8 @@ inline int permutation_sign(It first, It last)
        return sign;
 }
 
-template <class It, class Cmp>
-inline int permutation_sign(It first, It last, Cmp comp)
+template <class It, class Cmp, class Swap>
+int permutation_sign(It first, It last, Cmp comp, Swap swapit)
 {
        if (first == last)
                return 0;
@@ -200,7 +181,7 @@ inline int permutation_sign(It first, It last, Cmp comp)
                bool swapped = false;
                while (i != first) {
                        if (comp(*i, *other)) {
-                               iter_swap(other, i);
+                               swapit(*other, *i);
                                flag = other;
                                swapped = true;
                                sign = -sign;
@@ -219,7 +200,7 @@ inline int permutation_sign(It first, It last, Cmp comp)
                swapped = false;
                while (i != last) {
                        if (comp(*other, *i)) {
-                               iter_swap(i, other);
+                               swapit(*i, *other);
                                flag = other;
                                swapped = true;
                                sign = -sign;
@@ -237,8 +218,8 @@ inline int permutation_sign(It first, It last, Cmp comp)
 }
 
 /* Implementation of shaker sort, only compares adjacent elements. */
-template <class It, class Cmp>
-inline void shaker_sort(It first, It last, Cmp comp)
+template <class It, class Cmp, class Swap>
+void shaker_sort(It first, It last, Cmp comp, Swap swapit)
 {
        if (first == last)
                return;
@@ -253,7 +234,7 @@ inline void shaker_sort(It first, It last, Cmp comp)
                bool swapped = false;
                while (i != first) {
                        if (comp(*i, *other)) {
-                               iter_swap(other, i);
+                               swapit(*other, *i);
                                flag = other;
                                swapped = true;
                        }
@@ -270,7 +251,7 @@ inline void shaker_sort(It first, It last, Cmp comp)
                swapped = false;
                while (i != last) {
                        if (comp(*other, *i)) {
-                               iter_swap(i, other);
+                               swapit(*i, *other);
                                flag = other;
                                swapped = true;
                        }
@@ -283,14 +264,39 @@ inline void shaker_sort(It first, It last, Cmp comp)
        } while (first != last);
 }
 
-/* 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; }
-};
+/* In-place cyclic permutation of a container (no copying, only swapping). */
+template <class It, class Swap>
+void cyclic_permutation(It first, It last, It new_first, Swap swapit)
+{
+       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) {
+                       swapit(*a, *b);
+                       ++a; ++b;
+               }
+               if (num1 > num2) {
+                       first += num2;
+                       num = num1;
+                       goto again;
+               }
+       } else {
+               It a = new_first, b = last;
+               do {
+                       --a; --b;
+                       swapit(*a, *b);
+               } while (a != first);
+               last -= num1;
+               num = num2;
+               goto again;
+       }
+}
 
-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
@@ -452,7 +458,7 @@ int classname::compare_same_type(const basic & other) const \
 void classname::print(const print_context & c, unsigned level) const \
 { \
        debugmsg(#classname " print", LOGLEVEL_PRINT); \
-       if (is_of_type(c, print_tree)) \
+       if (is_a<print_tree>(c)) \
                inherited::print(c, level); \
        else \
                c.s << text; \
@@ -462,14 +468,30 @@ void classname::print(const print_context & c, unsigned level) const \
 void classname::print(const print_context & c, unsigned level) const \
 { \
        debugmsg(#classname " print", LOGLEVEL_PRINT); \
-       if (is_of_type(c, print_tree)) \
+       if (is_a<print_tree>(c)) \
                inherited::print(c, level); \
-       else if (is_of_type(c, print_latex)) \
+       else if (is_a<print_latex>(c)) \
                c.s << latex; \
        else \
                c.s << text; \
 }
 
+// Obsolete convenience macros.  TO BE PHASED OUT SOON!
+// Use the inlined template functions in basic.h instead.  (FIXME: remove them)
+
+#define is_of_type(OBJ,TYPE) \
+       (dynamic_cast<const TYPE *>(&OBJ)!=0)
+
+#define is_exactly_of_type(OBJ,TYPE) \
+       ((OBJ).tinfo()==GiNaC::TINFO_##TYPE)
+
+#define is_ex_of_type(OBJ,TYPE) \
+       (dynamic_cast<const TYPE *>((OBJ).bp)!=0)
+
+#define is_ex_exactly_of_type(OBJ,TYPE) \
+       ((*(OBJ).bp).tinfo()==GiNaC::TINFO_##TYPE)
+
 } // namespace GiNaC
 
+
 #endif // ndef __GINAC_UTILS_H__