[Lemon-commits] [lemon_svn] deba: r2384 - in hugo/trunk: benchmark lemon test
Lemon SVN
svn at lemon.cs.elte.hu
Mon Nov 6 20:52:15 CET 2006
Author: deba
Date: Mon Nov 28 12:14:01 2005
New Revision: 2384
Added:
hugo/trunk/benchmark/radix_sort-bench.cc
hugo/trunk/lemon/radix_sort.h
hugo/trunk/test/radix_sort_test.cc
Modified:
hugo/trunk/benchmark/Makefile.am
hugo/trunk/lemon/Makefile.am
hugo/trunk/test/Makefile.am
Log:
Radix sort algorithm
Modified: hugo/trunk/benchmark/Makefile.am
==============================================================================
--- hugo/trunk/benchmark/Makefile.am (original)
+++ hugo/trunk/benchmark/Makefile.am Mon Nov 28 12:14:01 2005
@@ -2,10 +2,12 @@
noinst_HEADERS = bench_tools.h
-noinst_PROGRAMS = graph-bench hcube bfs-bench
+noinst_PROGRAMS = graph-bench hcube bfs-bench radix_sort-bench
graph_bench_SOURCES = graph-bench.cc
hcube_SOURCES = hcube.cc
bfs_bench_SOURCES = bfs-bench.cc
+
+radix_sort_bench_SOURCES = radix_sort-bench.cc
Added: hugo/trunk/benchmark/radix_sort-bench.cc
==============================================================================
--- (empty file)
+++ hugo/trunk/benchmark/radix_sort-bench.cc Mon Nov 28 12:14:01 2005
@@ -0,0 +1,70 @@
+#define NDEBUG
+
+#include <lemon/time_measure.h>
+#include <lemon/smart_graph.h>
+#include <lemon/graph_utils.h>
+#include <lemon/maps.h>
+#include <lemon/error.h>
+
+#include <lemon/radix_sort.h>
+
+#include <vector>
+#include <algorithm>
+#include <cmath>
+
+using namespace std;
+using namespace lemon;
+
+void testRadixSort() {
+ int n = 10000000;
+ vector<int> data(n);
+ for (int i = 0; i < n; ++i) {
+ data[i] = (int)(1000 * (rand() / (RAND_MAX + 1.0))) - 500;
+ }
+ radixSort(data.begin(), data.end());
+}
+
+
+void testCounterSort() {
+ int n = 10000000;
+ vector<int> data(n);
+ for (int i = 0; i < n; ++i) {
+ data[i] = (int)(1000 * (rand() / (RAND_MAX + 1.0))) - 500;
+ }
+ counterSort(data.begin(), data.end());
+}
+
+void testSort() {
+ int n = 10000000;
+ vector<int> data(n);
+ for (int i = 0; i < n; ++i) {
+ data[i] = (int)(1000 * (rand() / (RAND_MAX + 1.0))) - 500;
+ }
+ sort(data.begin(), data.end());
+}
+
+void testStableSort() {
+ int n = 10000000;
+ vector<int> data(n);
+ for (int i = 0; i < n; ++i) {
+ data[i] = (int)(1000 * (rand() / (RAND_MAX + 1.0))) - 500;
+ }
+ stable_sort(data.begin(), data.end());
+}
+
+void testSorts() {
+ {
+ int n = 10000000;
+ vector<int> data(n);
+ }
+ cout << "Radix sort: " << runningTimeTest(testRadixSort, 60) << endl;
+ cout << "Counter sort: " << runningTimeTest(testCounterSort, 60) << endl;
+ cout << "Standard sort: " << runningTimeTest(testSort, 60) << endl;
+ cout << "Stable sort: " << runningTimeTest(testStableSort, 60) << endl;
+}
+
+
+int main() {
+ testSorts();
+ return 0;
+}
Modified: hugo/trunk/lemon/Makefile.am
==============================================================================
--- hugo/trunk/lemon/Makefile.am (original)
+++ hugo/trunk/lemon/Makefile.am Mon Nov 28 12:14:01 2005
@@ -57,6 +57,7 @@
preflow.h \
path.h \
radix_heap.h \
+ radix_sort.h \
smart_graph.h \
time_measure.h \
topology.h \
Added: hugo/trunk/lemon/radix_sort.h
==============================================================================
--- (empty file)
+++ hugo/trunk/lemon/radix_sort.h Mon Nov 28 12:14:01 2005
@@ -0,0 +1,483 @@
+/* -*- C++ -*-
+ * lemon/radix_sort.h - Part of LEMON, a generic C++ optimization library
+ *
+ * Copyright (C) 2005 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 auxdat
+/// \file
+/// \brief Radix sort
+///
+
+#include <vector>
+#include <limits>
+#include <iterator>
+#include <algorithm>
+
+#include <lemon/error.h>
+
+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) {
+ if ((mask | functor(*it)) != ~0) {
+ ++max_digit;
+ mask <<= 1;
+ mask |= 1;
+ }
+ }
+ radixIntroSort(first, cut, functor, 1 << max_digit);
+
+ mask = ~0; max_digit = 0;
+ for (it = cut; it != last; ++it) {
+ if (mask & functor(*it)) {
+ ++max_digit;
+ 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) {
+ if (mask & functor(*it)) {
+ ++max_digit;
+ mask <<= 1;
+ }
+ }
+ radixIntroSort(first, last, functor, 1 << max_digit);
+ }
+
+ namespace _radix_sort_bits {
+
+ 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 auxdat
+ ///
+ /// \brief Sorts the stl compatible range into ascending order.
+ ///
+ /// The \c radixSort sorts the stl compatible range into ascending order.
+ /// The radix sort algorithm can sort the items which mapped to an
+ /// integer by the adaptable unary function \c functor and the order
+ /// will be ascending by these mapped values. As function specialization
+ /// there is possible to use a normal function as the functor object
+ /// or if the functor is not given it will use an identity function instead.
+ ///
+ /// This implemented radix sort is a special quick sort which pivot value
+ /// is choosen to partite the items on the next bit. This way, let be
+ /// \c c the maximal capacity and \c n the number of the items in
+ /// the container, the time complexity of the algorithm \c O(log(c)*n)
+ /// and the additional space complexity is \c O(log(c)).
+ ///
+ /// \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 wheter signed or
+ /// unsigned.
+ 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>());
+ }
+
+ template <typename Value>
+ unsigned char valueByte(Value value, int byte) {
+ return *((unsigned char *)(&value) + byte);
+ }
+
+ template <typename Functor, typename Key>
+ void counterIntroSort(Key *first, Key *last, Key *target,
+ int byte, Functor functor) {
+ const int size =
+ (unsigned int)std::numeric_limits<unsigned char>::max() + 1;
+ 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;
+ }
+ while (it != last) {
+ target[counter[valueByte(functor(*it), byte)]++] = *it;
+ ++it;
+ }
+ }
+
+ template <typename Functor, typename Key>
+ void signedCounterIntroSort(Key *first, Key *last, Key *target,
+ int byte, Functor functor) {
+ const int size =
+ (unsigned int)std::numeric_limits<unsigned char>::max() + 1;
+ 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 = size / 2; i < size; ++i) {
+ prev = num;
+ num += counter[i];
+ counter[i] = prev;
+ }
+ for (int i = 0; i < size / 2; ++i) {
+ prev = num;
+ num += counter[i];
+ counter[i] = prev;
+ }
+ while (it != last) {
+ target[counter[valueByte(functor(*it), byte)]++] = *it;
+ ++it;
+ }
+ }
+
+
+ template <typename Value, typename Iterator, typename Functor>
+ void counterSignedSort(Iterator first, Iterator last, Functor functor) {
+ typedef typename std::iterator_traits<Iterator>::value_type Key;
+ typedef std::allocator<Key> Allocator;
+ Allocator allocator;
+
+ int length = std::distance(first, last);
+ Key* buffer;
+ buffer = allocator.allocate(2 * length);
+ try {
+ bool dir = true;
+ std::copy(first, last, buffer);
+ for (int i = 0; i < (int)sizeof(Value) - 1; ++i) {
+ if (dir) {
+ counterIntroSort(buffer, buffer + length, buffer + length,
+ i, functor);
+ } else {
+ counterIntroSort(buffer + length, buffer + 2 * length, buffer,
+ i, functor);
+ }
+ dir = !dir;
+ }
+ if (dir) {
+ signedCounterIntroSort(buffer, buffer + length, buffer + length,
+ sizeof(Value) - 1, functor);
+ std::copy(buffer + length, buffer + 2 * length, first);
+ } else {
+ signedCounterIntroSort(buffer + length, buffer + 2 * length, buffer,
+ sizeof(Value) - 1, functor);
+ std::copy(buffer, buffer + length, first);
+ }
+ } catch (...) {
+ allocator.deallocate(buffer, 2 * length);
+ throw;
+ }
+ allocator.deallocate(buffer, 2 * length);
+ }
+
+ template <typename Value, typename Iterator, typename Functor>
+ void counterUnsignedSort(Iterator first, Iterator last, Functor functor) {
+ typedef typename std::iterator_traits<Iterator>::value_type Key;
+ typedef std::allocator<Key> Allocator;
+ Allocator allocator;
+
+ int length = std::distance(first, last);
+ Key *buffer;
+ buffer = allocator.allocate(2 * length);
+ try {
+ bool dir = true;
+ std::copy(first, last, buffer);
+ for (int i = 0; i < sizeof(Value); ++i) {
+ if (dir) {
+ counterIntroSort(buffer, buffer + length, buffer + length,
+ i, functor);
+ } else {
+ counterIntroSort(buffer + length, buffer + 2 * length, buffer,
+ i, functor);
+ }
+ dir = !dir;
+ }
+ if (dir) {
+ std::copy(buffer, buffer + length, first);
+ } else {
+ std::copy(buffer + length, buffer + 2 * length, first);
+ }
+ } catch (...) {
+ allocator.deallocate(buffer, 2 * length);
+ throw;
+ }
+ allocator.deallocate(buffer, 2 * length);
+ }
+
+ namespace _radix_sort_bits {
+
+ template <typename Value,
+ bool sign = std::numeric_limits<Value>::is_signed >
+ struct CounterSortSelector {
+ template <typename Iterator, typename Functor>
+ static void sort(Iterator first, Iterator last, Functor functor) {
+ counterSignedSort<Value>(first, last, functor);
+ }
+ };
+
+ template <typename Value>
+ struct CounterSortSelector<Value, false> {
+ template <typename Iterator, typename Functor>
+ static void sort(Iterator first, Iterator last, Functor functor) {
+ counterUnsignedSort<Value>(first, last, functor);
+ }
+ };
+
+ }
+
+ /// \ingroup auxdat
+ ///
+ /// \brief Sorts stable the stl compatible range into ascending order.
+ ///
+ /// The \c counterSort sorts the stl compatible range into ascending order.
+ /// The counter sort algorithm can sort the items which mapped to an
+ /// integer by the adaptable unary function \c functor and the order
+ /// will be ascending by these mapped values. As function specialization
+ /// there is possible to use a normal function as the functor object
+ /// or if the functor is not given it will use an identity function instead.
+ ///
+ /// This implemented counter sort use a radix forward sort on the bytes of
+ /// the integer. The algorithm can sort the items on a given byte.
+ /// First time it counts how many times occurs a byte value in the container.
+ /// By the occurence number it is possible to copy the container
+ /// in the right order in \c O(n) time. The algorithm sorts the container
+ /// by each bytes in forward direction which sorts the container by the
+ /// whole value. This way, let be
+ /// \c c the maximal capacity and \c n the number of the items in
+ /// the container, the time complexity of the algorithm \c O(log(c)*n)
+ /// and the additional space complexity is \c O(n).
+ ///
+ /// This sorting algorithm is stable so the order of two equal element
+ /// stay in the same order.
+ ///
+ /// \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 wheter signed or
+ /// unsigned.
+ template <typename Iterator, typename Functor>
+ void counterSort(Iterator first, Iterator last, Functor functor) {
+ using namespace _radix_sort_bits;
+ typedef typename Functor::result_type Value;
+ CounterSortSelector<Value>::sort(first, last, functor);
+ }
+
+ template <typename Iterator, typename Value, typename Key>
+ void counterSort(Iterator first, Iterator last, Value (*functor)(Key)) {
+ using namespace _radix_sort_bits;
+ CounterSortSelector<Value>::sort(first, last, functor);
+ }
+
+ template <typename Iterator, typename Value, typename Key>
+ void counterSort(Iterator first, Iterator last, Value& (*functor)(Key)) {
+ using namespace _radix_sort_bits;
+ CounterSortSelector<Value>::sort(first, last, functor);
+ }
+
+ template <typename Iterator, typename Value, typename Key>
+ void counterSort(Iterator first, Iterator last, Value (*functor)(Key&)) {
+ using namespace _radix_sort_bits;
+ CounterSortSelector<Value>::sort(first, last, functor);
+ }
+
+ template <typename Iterator, typename Value, typename Key>
+ void counterSort(Iterator first, Iterator last, Value& (*functor)(Key&)) {
+ using namespace _radix_sort_bits;
+ CounterSortSelector<Value>::sort(first, last, functor);
+ }
+
+ template <typename Iterator>
+ void counterSort(Iterator first, Iterator last) {
+ using namespace _radix_sort_bits;
+ typedef typename std::iterator_traits<Iterator>::value_type Value;
+ CounterSortSelector<Value>::sort(first, last, Identity<Value>());
+ }
+
+}
+
+
+
+#endif
Modified: hugo/trunk/test/Makefile.am
==============================================================================
--- hugo/trunk/test/Makefile.am (original)
+++ hugo/trunk/test/Makefile.am Mon Nov 28 12:14:01 2005
@@ -26,6 +26,7 @@
suurballe_test \
path_test \
preflow_test \
+ radix_sort_test \
test_tools_fail \
test_tools_pass \
time_measure_test \
@@ -59,6 +60,7 @@
max_matching_test_SOURCES = max_matching_test.cc
suurballe_test_SOURCES = suurballe_test.cc
path_test_SOURCES = path_test.cc
+radix_sort_test_SOURCES = radix_sort_test.cc
preflow_test_SOURCES = preflow_test.cc
time_measure_test_SOURCES = time_measure_test.cc
test_tools_fail_SOURCES = test_tools_fail.cc
Added: hugo/trunk/test/radix_sort_test.cc
==============================================================================
--- (empty file)
+++ hugo/trunk/test/radix_sort_test.cc Mon Nov 28 12:14:01 2005
@@ -0,0 +1,144 @@
+#include <lemon/time_measure.h>
+#include <lemon/smart_graph.h>
+#include <lemon/graph_utils.h>
+#include <lemon/maps.h>
+#include <lemon/radix_sort.h>
+
+#include "test_tools.h"
+
+
+#include <vector>
+#include <algorithm>
+#include <cmath>
+
+using namespace std;
+using namespace lemon;
+
+void checkRadixSort() {
+ int n = 10000;
+ vector<int> data1(n), data2(n);
+ for (int i = 0; i < n; ++i) {
+ data1[i] = data2[i] = (int)(1000 * (rand() / (RAND_MAX + 1.0))) - 500;
+ }
+ radixSort(data1.begin(), data1.end());
+ sort(data2.begin(), data2.end());
+ for (int i = 0; i < n; ++i) {
+ check(data1[i] == data2[i], "Test failed");
+ }
+}
+
+
+void checkCounterSort() {
+ int n = 10000;
+ vector<int> data1(n), data2(n);
+ for (int i = 0; i < n; ++i) {
+ data1[i] = data2[i] = (int)(1000 * (rand() / (RAND_MAX + 1.0))) - 500;
+ }
+ counterSort(data1.begin(), data1.end());
+ sort(data2.begin(), data2.end());
+ for (int i = 0; i < n; ++i) {
+ check(data1[i] == data2[i], "Test failed");
+ }
+}
+
+void checkSorts() {
+ checkRadixSort();
+ checkCounterSort();
+}
+
+void checkGraphRadixSort() {
+ typedef SmartGraph Graph;
+ typedef Graph::Node Node;
+ typedef Graph::Edge Edge;
+
+ const int n = 100;
+ const int e = (int)(n * log((double)n));
+
+ Graph graph;
+ vector<Node> nodes;
+
+ for (int i = 0; i < n; ++i) {
+ nodes.push_back(graph.addNode());
+ }
+ vector<Edge> edges;
+ for (int i = 0; i < e; ++i) {
+ int s = (int)(n * (double)rand() / (RAND_MAX + 1.0));
+ int t = (int)(n * (double)rand() / (RAND_MAX + 1.0));
+ edges.push_back(graph.addEdge(nodes[s], nodes[t]));
+ }
+
+ radixSort(edges.begin(), edges.end(),
+ mapFunctor(composeMap(IdMap<Graph, Node>(graph),
+ sourceMap(graph))));
+
+ Graph::EdgeMap<bool> was(graph, false);
+
+ for (int i = 0; i < (int)edges.size(); ++i) {
+ check(!was[edges[i]], "Test failed");
+ was[edges[i]] = true;
+ }
+
+ for (int i = 1; i < (int)edges.size(); ++i) {
+ check(graph.id(graph.source(edges[i - 1])) <=
+ graph.id(graph.source(edges[i])), "Test failed");
+ }
+
+}
+
+void checkGraphCounterSort() {
+ typedef SmartGraph Graph;
+ typedef Graph::Node Node;
+ typedef Graph::Edge Edge;
+
+ const int n = 100;
+ const int e = (int)(n * log((double)n));
+
+ Graph graph;
+ vector<Node> nodes;
+
+ for (int i = 0; i < n; ++i) {
+ nodes.push_back(graph.addNode());
+ }
+ vector<Edge> edges;
+ for (int i = 0; i < e; ++i) {
+ int s = (int)(n * (double)rand() / (RAND_MAX + 1.0));
+ int t = (int)(n * (double)rand() / (RAND_MAX + 1.0));
+ edges.push_back(graph.addEdge(nodes[s], nodes[t]));
+ }
+
+ counterSort(edges.begin(), edges.end(),
+ mapFunctor(composeMap(IdMap<Graph, Node>(graph),
+ sourceMap(graph))));
+
+ counterSort(edges.begin(), edges.end(),
+ mapFunctor(composeMap(IdMap<Graph, Node>(graph),
+ targetMap(graph))));
+
+ Graph::EdgeMap<bool> was(graph, false);
+
+ for (int i = 0; i < (int)edges.size(); ++i) {
+ check(!was[edges[i]], "Test failed");
+ was[edges[i]] = true;
+ }
+
+ for (int i = 1; i < (int)edges.size(); ++i) {
+ check(graph.id(graph.target(edges[i - 1])) <
+ graph.id(graph.target(edges[i])) ||
+ (graph.id(graph.target(edges[i - 1])) ==
+ graph.id(graph.target(edges[i])) &&
+ graph.id(graph.source(edges[i - 1])) <=
+ graph.id(graph.source(edges[i]))), "Test failed");
+ }
+
+}
+
+void checkGraphSorts() {
+ checkGraphRadixSort();
+ checkGraphCounterSort();
+}
+
+int main() {
+ checkSorts();
+ checkGraphSorts();
+ return 0;
+}
More information about the Lemon-commits
mailing list