[Lemon-commits] Alpar Juttner: Merge

Lemon HG hg at lemon.cs.elte.hu
Thu Jan 8 18:32:50 CET 2009


details:   http://lemon.cs.elte.hu/hg/lemon/rev/75a5df083951
changeset: 468:75a5df083951
user:      Alpar Juttner <alpar [at] cs.elte.hu>
date:      Thu Jan 08 17:19:26 2009 +0000
description:
	Merge

diffstat:

5 files changed, 638 insertions(+)
lemon/Makefile.am       |    1 
lemon/radix_sort.h      |  487 +++++++++++++++++++++++++++++++++++++++++++++++
test/CMakeLists.txt     |    1 
test/Makefile.am        |    2 
test/radix_sort_test.cc |  147 ++++++++++++++

diffs (truncated from 685 to 300 lines):

diff --git a/lemon/Makefile.am b/lemon/Makefile.am
--- a/lemon/Makefile.am
+++ b/lemon/Makefile.am
@@ -47,6 +47,7 @@
 	lemon/nauty_reader.h \
 	lemon/path.h \
 	lemon/preflow.h \
+	lemon/radix_sort.h \
 	lemon/random.h \
 	lemon/smart_graph.h \
 	lemon/suurballe.h \
diff --git a/lemon/radix_sort.h b/lemon/radix_sort.h
new file mode 100644
--- /dev/null
+++ b/lemon/radix_sort.h
@@ -0,0 +1,487 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2009
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef RADIX_SORT_H
+#define RADIX_SORT_H
+
+/// \ingroup auxalg
+/// \file
+/// \brief Radix sort
+///
+/// Linear time sorting algorithms
+
+#include <vector>
+#include <limits>
+#include <iterator>
+#include <algorithm>
+
+namespace lemon {
+
+  namespace _radix_sort_bits {
+
+    template <typename Value>
+    struct Identity {
+      const Value& operator()(const Value& val) {
+        return val;
+      }
+    };
+
+
+    template <typename Value, typename Iterator, typename Functor>
+    Iterator radixSortPartition(Iterator first, Iterator last,
+                                Functor functor, Value mask) {
+      while (first != last && !(functor(*first) & mask)) {
+        ++first;
+      }
+      if (first == last) {
+        return first;
+      }
+      --last;
+      while (first != last && (functor(*last) & mask)) {
+        --last;
+      }
+      if (first == last) {
+        return first;
+      }
+      std::iter_swap(first, last);
+      ++first;
+      if (!(first < last)) {
+        return first;
+      }
+      while (true) {
+        while (!(functor(*first) & mask)) {
+          ++first;
+        }
+        --last;
+        while (functor(*last) & mask) {
+          --last;
+        }
+        if (!(first < last)) {
+          return first;
+        }
+        std::iter_swap(first, last);
+        ++first;
+      }
+    }
+
+    template <typename Iterator, typename Functor>
+    Iterator radixSortSignPartition(Iterator first, Iterator last,
+                                    Functor functor) {
+      while (first != last && functor(*first) < 0) {
+        ++first;
+      }
+      if (first == last) {
+        return first;
+      }
+      --last;
+      while (first != last && functor(*last) >= 0) {
+        --last;
+      }
+      if (first == last) {
+        return first;
+      }
+      std::iter_swap(first, last);
+      ++first;
+      if (!(first < last)) {
+        return first;
+      }
+      while (true) {
+        while (functor(*first) < 0) {
+          ++first;
+        }
+        --last;
+        while (functor(*last) >= 0) {
+          --last;
+        }
+        if (!(first < last)) {
+          return first;
+        }
+        std::iter_swap(first, last);
+        ++first;
+      }
+    }
+
+    template <typename Value, typename Iterator, typename Functor>
+    void radixIntroSort(Iterator first, Iterator last,
+                        Functor functor, Value mask) {
+      while (mask != 0 && last - first > 1) {
+        Iterator cut = radixSortPartition(first, last, functor, mask);
+        mask >>= 1;
+        radixIntroSort(first, cut, functor, mask);
+        first = cut;
+      }
+    }
+
+    template <typename Value, typename Iterator, typename Functor>
+    void radixSignedSort(Iterator first, Iterator last, Functor functor) {
+
+      Iterator cut = radixSortSignPartition(first, last, functor);
+
+      Value mask;
+      int max_digit;
+      Iterator it;
+
+      mask = ~0; max_digit = 0;
+      for (it = first; it != cut; ++it) {
+        while ((mask & functor(*it)) != mask) {
+          ++max_digit;
+          mask <<= 1;
+        }
+      }
+      radixIntroSort(first, cut, functor, 1 << max_digit);
+
+      mask = 0; max_digit = 0;
+      for (it = cut; it != last; ++it) {
+        while ((mask | functor(*it)) != mask) {
+          ++max_digit;
+          mask <<= 1; mask |= 1;
+        }
+      }
+      radixIntroSort(cut, last, functor, 1 << max_digit);
+    }
+
+    template <typename Value, typename Iterator, typename Functor>
+    void radixUnsignedSort(Iterator first, Iterator last, Functor functor) {
+
+      Value mask = 0;
+      int max_digit = 0;
+
+      Iterator it;
+      for (it = first; it != last; ++it) {
+        while ((mask | functor(*it)) != mask) {
+          ++max_digit;
+          mask <<= 1; mask |= 1;
+        }
+      }
+      radixIntroSort(first, last, functor, 1 << max_digit);
+    }
+
+
+    template <typename Value,
+              bool sign = std::numeric_limits<Value>::is_signed >
+    struct RadixSortSelector {
+      template <typename Iterator, typename Functor>
+      static void sort(Iterator first, Iterator last, Functor functor) {
+        radixSignedSort<Value>(first, last, functor);
+      }
+    };
+
+    template <typename Value>
+    struct RadixSortSelector<Value, false> {
+      template <typename Iterator, typename Functor>
+      static void sort(Iterator first, Iterator last, Functor functor) {
+        radixUnsignedSort<Value>(first, last, functor);
+      }
+    };
+
+  }
+
+  /// \ingroup auxalg
+  ///
+  /// \brief Sorts the STL compatible range into ascending order.
+  ///
+  /// The \c radixSort sorts an STL compatible range into ascending
+  /// order.  The radix sort algorithm can sort items which are mapped
+  /// to integers with an adaptable unary function \c functor and the
+  /// order will be ascending according to these mapped values.
+  ///
+  /// It is also possible to use a normal function instead
+  /// of the functor object. If the functor is not given it will use
+  /// the identity function instead.
+  ///
+  /// This is a special quick sort algorithm where the pivot
+  /// values to split the items are choosen to be \f$ 2^k \f$ for each \c k.
+  /// Therefore, the time complexity of the
+  /// algorithm is \f$ O(\log(c)n) \f$ and it uses \f$ O(\log(c)) \f$,
+  /// additional space, where \c c is the maximal value and \c n is the
+  /// number of the items in the container.
+  ///
+  /// \param first The begin of the given range.
+  /// \param last The end of the given range.
+  /// \param functor An adaptible unary function or a normal function
+  /// which maps the items to any integer type which can be either
+  /// signed or unsigned.
+  ///
+  /// \sa stableRadixSort()
+  template <typename Iterator, typename Functor>
+  void radixSort(Iterator first, Iterator last, Functor functor) {
+    using namespace _radix_sort_bits;
+    typedef typename Functor::result_type Value;
+    RadixSortSelector<Value>::sort(first, last, functor);
+  }
+
+  template <typename Iterator, typename Value, typename Key>
+  void radixSort(Iterator first, Iterator last, Value (*functor)(Key)) {
+    using namespace _radix_sort_bits;
+    RadixSortSelector<Value>::sort(first, last, functor);
+  }
+
+  template <typename Iterator, typename Value, typename Key>
+  void radixSort(Iterator first, Iterator last, Value& (*functor)(Key)) {
+    using namespace _radix_sort_bits;
+    RadixSortSelector<Value>::sort(first, last, functor);
+  }
+
+  template <typename Iterator, typename Value, typename Key>
+  void radixSort(Iterator first, Iterator last, Value (*functor)(Key&)) {
+    using namespace _radix_sort_bits;
+    RadixSortSelector<Value>::sort(first, last, functor);
+  }
+
+  template <typename Iterator, typename Value, typename Key>
+  void radixSort(Iterator first, Iterator last, Value& (*functor)(Key&)) {
+    using namespace _radix_sort_bits;
+    RadixSortSelector<Value>::sort(first, last, functor);
+  }
+
+  template <typename Iterator>
+  void radixSort(Iterator first, Iterator last) {
+    using namespace _radix_sort_bits;
+    typedef typename std::iterator_traits<Iterator>::value_type Value;
+    RadixSortSelector<Value>::sort(first, last, Identity<Value>());
+  }
+
+  namespace _radix_sort_bits {
+
+    template <typename Value>
+    unsigned char valueByte(Value value, int byte) {
+      return value >> (std::numeric_limits<unsigned char>::digits * byte);
+    }
+
+    template <typename Functor, typename Key>
+    void stableRadixIntroSort(Key *first, Key *last, Key *target,
+                              int byte, Functor functor) {
+      const int size =
+        unsigned(std::numeric_limits<unsigned char>::max()) + 1;
+      std::vector<int> counter(size);
+      for (int i = 0; i < size; ++i) {
+        counter[i] = 0;
+      }
+      Key *it = first;
+      while (first != last) {
+        ++counter[valueByte(functor(*first), byte)];
+        ++first;
+      }
+      int prev, num = 0;
+      for (int i = 0; i < size; ++i) {
+        prev = num;
+        num += counter[i];
+        counter[i] = prev;



More information about the Lemon-commits mailing list