[compute] 05/49: Reduce by key algorithm (serial implementation)

Ghislain Vaillant ghisvail-guest at moszumanska.debian.org
Fri Dec 18 17:58:15 UTC 2015


This is an automated email from the git hooks/post-receive script.

ghisvail-guest pushed a commit to branch master
in repository compute.

commit 706af4fce8c2f70d21f05013ff79a25419a2988b
Author: Jakub Szuppe <j.szuppe at gmail.com>
Date:   Sat Jul 4 20:49:43 2015 +0200

    Reduce by key algorithm (serial implementation)
---
 .../compute/algorithm/detail/reduce_by_key.hpp     |  75 ++++++++
 .../algorithm/detail/serial_reduce_by_key.hpp      | 108 +++++++++++
 include/boost/compute/algorithm/reduce_by_key.hpp  | 118 ++++++++++++
 test/CMakeLists.txt                                |   1 +
 test/test_reduce_by_key.cpp                        | 210 +++++++++++++++++++++
 5 files changed, 512 insertions(+)

diff --git a/include/boost/compute/algorithm/detail/reduce_by_key.hpp b/include/boost/compute/algorithm/detail/reduce_by_key.hpp
new file mode 100644
index 0000000..bdcd14d
--- /dev/null
+++ b/include/boost/compute/algorithm/detail/reduce_by_key.hpp
@@ -0,0 +1,75 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2015 Jakub Szuppe <j.szuppe at gmail.com>
+//
+// Distributed under the Boost Software License, Version 1.0
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_REDUCE_BY_KEY_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_REDUCE_BY_KEY_HPP
+
+#include <algorithm>
+#include <iterator>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/algorithm/detail/serial_reduce_by_key.hpp>
+#include <boost/compute/type_traits.hpp>
+#include <boost/compute/utility/program_cache.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class InputKeyIterator, class InputValueIterator,
+         class OutputKeyIterator, class OutputValueIterator,
+         class BinaryFunction, class BinaryPredicate>
+inline std::pair<OutputKeyIterator, OutputValueIterator>
+dispatch_reduce_by_key(InputKeyIterator keys_first,
+                       InputKeyIterator keys_last,
+                       InputValueIterator values_first,
+                       OutputKeyIterator keys_result,
+                       OutputValueIterator values_result,
+                       BinaryFunction function,
+                       BinaryPredicate predicate,
+                       command_queue &queue)
+{
+    typedef typename
+        std::iterator_traits<OutputKeyIterator>::difference_type key_difference_type;
+    typedef typename
+        std::iterator_traits<OutputValueIterator>::difference_type value_difference_type;
+
+    const size_t count = detail::iterator_range_size(keys_first, keys_last);
+    if (count < 2) {
+        boost::compute::copy_n(keys_first, count, keys_result, queue);
+        boost::compute::copy_n(values_first, count, values_result, queue);
+        return
+            std::make_pair<OutputKeyIterator, OutputValueIterator>(
+                keys_result + static_cast<key_difference_type>(count),
+                values_result + static_cast<value_difference_type>(count)
+            );
+    }
+
+    size_t result_size =
+        detail::serial_reduce_by_key(keys_first, keys_last, values_first,
+                                     keys_result, values_result, function,
+                                     predicate, queue);
+
+
+    return
+        std::make_pair<OutputKeyIterator, OutputValueIterator>(
+            keys_result + static_cast<key_difference_type>(result_size),
+            values_result + static_cast<value_difference_type>(result_size)
+        );
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_REDUCE_BY_KEY_HPP
diff --git a/include/boost/compute/algorithm/detail/serial_reduce_by_key.hpp b/include/boost/compute/algorithm/detail/serial_reduce_by_key.hpp
new file mode 100644
index 0000000..f9bda8e
--- /dev/null
+++ b/include/boost/compute/algorithm/detail/serial_reduce_by_key.hpp
@@ -0,0 +1,108 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2015 Jakub Szuppe <j.szuppe at gmail.com>
+//
+// Distributed under the Boost Software License, Version 1.0
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_DETAIL_SERIAL_REDUCE_BY_KEY_HPP
+#define BOOST_COMPUTE_ALGORITHM_DETAIL_SERIAL_REDUCE_BY_KEY_HPP
+
+#include <iterator>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/container/vector.hpp>
+#include <boost/compute/container/detail/scalar.hpp>
+#include <boost/compute/detail/meta_kernel.hpp>
+#include <boost/compute/detail/iterator_range_size.hpp>
+#include <boost/compute/type_traits/result_of.hpp>
+
+namespace boost {
+namespace compute {
+namespace detail {
+
+template<class InputKeyIterator, class InputValueIterator,
+         class OutputKeyIterator, class OutputValueIterator,
+         class BinaryFunction, class BinaryPredicate>
+inline size_t serial_reduce_by_key(InputKeyIterator keys_first,
+                                   InputKeyIterator keys_last,
+                                   InputValueIterator values_first,
+                                   OutputKeyIterator keys_result,
+                                   OutputValueIterator values_result,
+                                   BinaryFunction function,
+                                   BinaryPredicate predicate,
+                                   command_queue &queue)
+{
+    typedef typename
+        std::iterator_traits<InputValueIterator>::value_type value_type;
+    typedef typename
+        std::iterator_traits<InputKeyIterator>::value_type key_type;
+    typedef typename
+        ::boost::compute::result_of<BinaryFunction(value_type, value_type)>::type result_type;
+
+    const context &context = queue.get_context();
+    size_t count = detail::iterator_range_size(keys_first, keys_last);
+    if(count < 1){
+        return count;
+    }
+
+    meta_kernel k("serial_reduce_by_key");
+    size_t count_arg = k.add_arg<uint_>("count");
+    size_t result_size_arg = k.add_arg<uint_ *>(memory_object::global_memory,
+                                                "result_size");
+
+    convert<result_type> to_result_type;
+
+    k <<
+        k.decl<result_type>("result") <<
+            " = " << to_result_type(values_first[0]) << ";\n" <<
+        k.decl<key_type>("previous_key") << " = " << keys_first[0] << ";\n" <<
+        k.decl<result_type>("value") << ";\n" <<
+        k.decl<key_type>("key") << ";\n" <<
+
+        k.decl<uint_>("size") << " = 1;\n" <<
+
+        keys_result[0] << " = previous_key;\n" <<
+        values_result[0] << " = result;\n" <<
+
+        "for(ulong i = 1; i < count; i++) {\n" <<
+        "    value = " << to_result_type(values_first[k.var<uint_>("i")]) << ";\n" <<
+        "    key = " << keys_first[k.var<uint_>("i")] << ";\n" <<
+        "    if (" << predicate(k.var<key_type>("previous_key"),
+                                k.var<key_type>("key")) << ") {\n" <<
+
+        "        result = " << function(k.var<result_type>("result"),
+                                        k.var<result_type>("value")) << ";\n" <<
+        "    }\n " <<
+        "    else { \n" <<
+                 keys_result[k.var<uint_>("size - 1")] << " = previous_key;\n" <<
+                 values_result[k.var<uint_>("size - 1")] << " = result;\n" <<
+        "        result = value;\n" <<
+        "        size++;\n" <<
+        "    } \n" <<
+        "    previous_key = key;\n" <<
+        "}\n" <<
+        keys_result[k.var<uint_>("size - 1")] << " = previous_key;\n" <<
+        values_result[k.var<uint_>("size - 1")] << " = result;\n" <<
+        "*result_size = size;";
+
+    kernel kernel = k.compile(context);
+
+    scalar<uint_> result_size(context);
+    kernel.set_arg(result_size_arg, result_size.get_buffer());
+    kernel.set_arg(count_arg, static_cast<uint_>(count));
+
+    queue.enqueue_task(kernel);
+
+    return static_cast<size_t>(result_size.read(queue));
+}
+
+} // end detail namespace
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_DETAIL_SERIAL_REDUCE_BY_KEY_HPP
diff --git a/include/boost/compute/algorithm/reduce_by_key.hpp b/include/boost/compute/algorithm/reduce_by_key.hpp
new file mode 100644
index 0000000..87c73e8
--- /dev/null
+++ b/include/boost/compute/algorithm/reduce_by_key.hpp
@@ -0,0 +1,118 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2015 Jakub Szuppe <j.szuppe at gmail.com>
+//
+// Distributed under the Boost Software License, Version 1.0
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#ifndef BOOST_COMPUTE_ALGORITHM_REDUCE_BY_KEY_HPP
+#define BOOST_COMPUTE_ALGORITHM_REDUCE_BY_KEY_HPP
+
+#include <iterator>
+#include <utility>
+
+#include <boost/compute/command_queue.hpp>
+#include <boost/compute/device.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/algorithm/detail/reduce_by_key.hpp>
+
+namespace boost {
+namespace compute {
+
+/// The \c reduce_by_key() algorithm performs reduction for each contiguous
+/// subsequence of values determinate by equivalent keys.
+///
+/// Returns a pair of iterators at the end of the ranges [\p keys_result, keys_result_last)
+/// and [\p values_result, \p values_result_last).
+///
+/// If no function is specified, \c plus will be used.
+/// If no predicate is specified, \c equal_to will be used.
+///
+/// \param keys_first the first key
+/// \param keys_last the last key
+/// \param values_first the first input value
+/// \param keys_result iterator pointing to the key output
+/// \param values_result iterator pointing to the reduced value output
+/// \param function binary reduction function
+/// \param predicate binary predicate which returns true only if two keys are equal
+/// \param queue command queue to perform the operation
+///
+/// The \c reduce_by_key() algorithm assumes that the binary reduction function
+/// is associative. When used with non-associative functions the result may
+/// be non-deterministic and vary in precision. Notably this affects the
+/// \c plus<float>() function as floating-point addition is not associative
+/// and may produce slightly different results than a serial algorithm.
+///
+/// For example, to calculate the sum of the values for each key:
+///
+/// \snippet test/test_reduce_by_key.cpp reduce_by_key_int
+///
+/// \see reduce()
+template<class InputKeyIterator, class InputValueIterator,
+         class OutputKeyIterator, class OutputValueIterator,
+         class BinaryFunction, class BinaryPredicate>
+inline std::pair<OutputKeyIterator, OutputValueIterator>
+reduce_by_key(InputKeyIterator keys_first,
+              InputKeyIterator keys_last,
+              InputValueIterator values_first,
+              OutputKeyIterator keys_result,
+              OutputValueIterator values_result,
+              BinaryFunction function,
+              BinaryPredicate predicate,
+              command_queue &queue = system::default_queue())
+{
+    return detail::dispatch_reduce_by_key(keys_first, keys_last, values_first,
+                                          keys_result, values_result,
+                                          function, predicate,
+                                          queue);
+}
+
+/// \overload
+template<class InputKeyIterator, class InputValueIterator,
+         class OutputKeyIterator, class OutputValueIterator,
+         class BinaryFunction>
+inline std::pair<OutputKeyIterator, OutputValueIterator>
+reduce_by_key(InputKeyIterator keys_first,
+              InputKeyIterator keys_last,
+              InputValueIterator values_first,
+              OutputKeyIterator keys_result,
+              OutputValueIterator values_result,
+              BinaryFunction function,
+              command_queue &queue = system::default_queue())
+{
+    typedef typename std::iterator_traits<InputKeyIterator>::value_type key_type;
+
+    return reduce_by_key(keys_first, keys_last, values_first,
+                         keys_result, values_result,
+                         function, equal_to<key_type>(),
+                         queue);
+}
+
+/// \overload
+template<class InputKeyIterator, class InputValueIterator,
+         class OutputKeyIterator, class OutputValueIterator>
+inline std::pair<OutputKeyIterator, OutputValueIterator>
+reduce_by_key(InputKeyIterator keys_first,
+              InputKeyIterator keys_last,
+              InputValueIterator values_first,
+              OutputKeyIterator keys_result,
+              OutputValueIterator values_result,
+              command_queue &queue = system::default_queue())
+{
+    typedef typename std::iterator_traits<InputKeyIterator>::value_type key_type;
+    typedef typename std::iterator_traits<InputValueIterator>::value_type value_type;
+
+    return reduce_by_key(keys_first, keys_last, values_first,
+                         keys_result, values_result,
+                         plus<value_type>(), equal_to<key_type>(),
+                         queue);
+}
+
+} // end compute namespace
+} // end boost namespace
+
+#endif // BOOST_COMPUTE_ALGORITHM_REDUCE_BY_KEY_HPP
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index ff2532c..3c23853 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -99,6 +99,7 @@ add_compute_test("algorithm.radix_sort" test_radix_sort.cpp)
 add_compute_test("algorithm.random_fill" test_random_fill.cpp)
 add_compute_test("algorithm.random_shuffle" test_random_shuffle.cpp)
 add_compute_test("algorithm.reduce" test_reduce.cpp)
+add_compute_test("algorithm.reduce_by_key" test_reduce_by_key.cpp)
 add_compute_test("algorithm.remove" test_remove.cpp)
 add_compute_test("algorithm.replace" test_replace.cpp)
 add_compute_test("algorithm.reverse" test_reverse.cpp)
diff --git a/test/test_reduce_by_key.cpp b/test/test_reduce_by_key.cpp
new file mode 100644
index 0000000..50c0c63
--- /dev/null
+++ b/test/test_reduce_by_key.cpp
@@ -0,0 +1,210 @@
+//---------------------------------------------------------------------------//
+// Copyright (c) 2015 Jakub Szuppe <j.szuppe at gmail.com>
+//
+// Distributed under the Boost Software License, Version 1.0
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+//
+// See http://boostorg.github.com/compute for more information.
+//---------------------------------------------------------------------------//
+
+#define BOOST_TEST_MODULE TestReduceByKey
+#include <boost/test/unit_test.hpp>
+
+#include <boost/compute/lambda.hpp>
+#include <boost/compute/system.hpp>
+#include <boost/compute/functional.hpp>
+#include <boost/compute/algorithm/inclusive_scan.hpp>
+#include <boost/compute/algorithm/reduce_by_key.hpp>
+#include <boost/compute/container/vector.hpp>
+
+#include "check_macros.hpp"
+#include "context_setup.hpp"
+
+namespace bc = boost::compute;
+
+BOOST_AUTO_TEST_CASE(reduce_by_key_int)
+{
+//! [reduce_by_key_int]
+// setup keys and values
+int keys[] = { 0, 2, -3, -3, -3, -3, -3, 4 };
+int data[] = { 1, 1, 1, 1, 1, 2, 5, 1 };
+
+boost::compute::vector<int> keys_input(keys, keys + 8, queue);
+boost::compute::vector<int> values_input(data, data + 8, queue);
+
+boost::compute::vector<int> keys_output(8, context);
+boost::compute::vector<int> values_output(8, context);
+// reduce by key
+boost::compute::reduce_by_key(keys_input.begin(), keys_input.end(), values_input.begin(),
+                              keys_output.begin(), values_output.begin(), queue);
+// keys_output = { 0, 2, -3, 4 }
+// values_output = { 1, 1, 10, 1 }
+//! [reduce_by_key_int]
+    CHECK_RANGE_EQUAL(int, 4, keys_output,   (0, 2, -3,  4));
+    CHECK_RANGE_EQUAL(int, 4, values_output, (1, 1, 10, 1));
+}
+
+BOOST_AUTO_TEST_CASE(reduce_by_key_int_long_vector)
+{
+    size_t size = 1024;
+    bc::vector<int> keys_input(size, int(0), queue);
+    bc::vector<int> values_input(size, int(1), queue);
+
+    bc::vector<int> keys_output(size, context);
+    bc::vector<int> values_output(size, context);
+
+    bc::reduce_by_key(keys_input.begin(), keys_input.end(), values_input.begin(),
+                      keys_output.begin(), values_output.begin(), queue);
+
+    CHECK_RANGE_EQUAL(int, 1, keys_output,   (0));
+    CHECK_RANGE_EQUAL(int, 1, values_output, (static_cast<int>(size)));
+
+    keys_input[137] = 1;
+    keys_input[677] = 1;
+    keys_input[1001] = 1;
+    bc::inclusive_scan(keys_input.begin(), keys_input.end(), keys_input.begin(), queue);
+
+    bc::reduce_by_key(keys_input.begin(), keys_input.end(), values_input.begin(),
+                      keys_output.begin(), values_output.begin(), queue);
+
+    CHECK_RANGE_EQUAL(int, 4, keys_output,   (0, 1, 2, 3));
+    CHECK_RANGE_EQUAL(int, 4, values_output, (137, 540, 324, 23));
+}
+
+BOOST_AUTO_TEST_CASE(reduce_by_key_empty_vector)
+{
+    bc::vector<int> keys_input(context);
+    bc::vector<int> values_input(context);
+
+    bc::vector<int> keys_output(context);
+    bc::vector<int> values_output(context);
+
+    bc::reduce_by_key(keys_input.begin(), keys_input.end(), values_input.begin(),
+                      keys_output.begin(), values_output.begin(), queue);
+
+    BOOST_CHECK(keys_output.empty());
+    BOOST_CHECK(values_output.empty());
+}
+
+BOOST_AUTO_TEST_CASE(reduce_by_key_int_one_key_value)
+{
+    int keys[] = { 22 };
+    int data[] = { -9 };
+
+    bc::vector<int> keys_input(keys, keys + 1, queue);
+    bc::vector<int> values_input(data, data + 1, queue);
+
+    bc::vector<int> keys_output(1, context);
+    bc::vector<int> values_output(1, context);
+
+    bc::reduce_by_key(keys_input.begin(), keys_input.end(), values_input.begin(),
+                      keys_output.begin(), values_output.begin(), queue);
+
+    CHECK_RANGE_EQUAL(int, 1, keys_output,   (22));
+    CHECK_RANGE_EQUAL(int, 1, values_output, (-9));
+}
+
+BOOST_AUTO_TEST_CASE(reduce_by_key_int_min_max)
+{
+    int keys[] = { 0, 2, 2, 3, 3, 3, 3, 3, 4 };
+    int data[] = { 1, 2, 1, -3, 1, 4, 2, 5, 77 };
+
+    bc::vector<int> keys_input(keys, keys + 9, queue);
+    bc::vector<int> values_input(data, data + 9, queue);
+
+    bc::vector<int> keys_output(9, context);
+    bc::vector<int> values_output(9, context);
+
+    bc::reduce_by_key(keys_input.begin(), keys_input.end(), values_input.begin(),
+                      keys_output.begin(), values_output.begin(), bc::min<int>(),
+                      bc::equal_to<int>(), queue);
+
+    CHECK_RANGE_EQUAL(int, 4, keys_output,   (0, 2, 3,  4));
+    CHECK_RANGE_EQUAL(int, 4, values_output, (1, 1, -3, 77));
+
+    bc::reduce_by_key(keys_input.begin(), keys_input.end(), values_input.begin(),
+                      keys_output.begin(), values_output.begin(), bc::max<int>(),
+                      bc::equal_to<int>(), queue);
+
+    CHECK_RANGE_EQUAL(int, 4, keys_output,   (0, 2, 3,  4));
+    CHECK_RANGE_EQUAL(int, 4, values_output, (1, 2, 5, 77));
+}
+
+BOOST_AUTO_TEST_CASE(reduce_by_key_float_max)
+{
+    int keys[] = { 0, 2, 2, 3, 3, 3, 3, 3, 4 };
+    float data[] = { 1.0, 2.0, -1.5, -3.0, 1.0, -0.24, 2, 5, 77.1 };
+
+    bc::vector<int> keys_input(keys, keys + 9, queue);
+    bc::vector<float> values_input(data, data + 9, queue);
+
+    bc::vector<int> keys_output(9, context);
+    bc::vector<float> values_output(9, context);
+
+    bc::reduce_by_key(keys_input.begin(), keys_input.end(), values_input.begin(),
+                      keys_output.begin(), values_output.begin(), bc::max<float>(),
+                      queue);
+
+    CHECK_RANGE_EQUAL(int, 4, keys_output, (0, 2, 3, 4));
+    BOOST_CHECK_CLOSE(float(values_output[0]), 1.0f, 1e-4f);
+    BOOST_CHECK_CLOSE(float(values_output[1]), 2.0f, 1e-4f);
+    BOOST_CHECK_CLOSE(float(values_output[2]), 5.0f, 1e-4f);
+    BOOST_CHECK_CLOSE(float(values_output[3]), 77.1f, 1e-4f);
+}
+
+BOOST_AUTO_TEST_CASE(reduce_by_key_int2)
+{
+    using bc::int2_;
+
+    int keys[] = { 0, 2, 3, 3, 3, 3, 4, 4 };
+    int2_ data[] = {
+        int2_(0, 1), int2_(-3, 2), int2_(0, 1), int2_(0, 1),
+        int2_(-3, 0), int2_(0, 0), int2_(-3, 2), int2_(-7, -2)
+    };
+
+    bc::vector<int> keys_input(keys, keys + 8, queue);
+    bc::vector<int2_> values_input(data, data + 8, queue);
+
+    bc::vector<int> keys_output(8, context);
+    bc::vector<int2_> values_output(8, context);
+
+    bc::reduce_by_key(keys_input.begin(), keys_input.end(), values_input.begin(),
+                      keys_output.begin(), values_output.begin(), queue);
+
+    CHECK_RANGE_EQUAL(int, 4, keys_output, (0, 2, 3, 4));
+    CHECK_RANGE_EQUAL(int2_, 4, values_output,
+        (int2_(0, 1), int2_(-3, 2), int2_(-3, 2), int2_(-10, 0)));
+}
+
+BOOST_AUTO_TEST_CASE(reduce_by_key_int2_long_vector)
+{
+    using bc::int2_;
+
+    size_t size = 1024;
+    bc::vector<int> keys_input(size, int(0), queue);
+    bc::vector<int2_> values_input(size, int2_(1, -1), queue);
+
+    bc::vector<int> keys_output(size, context);
+    bc::vector<int2_> values_output(size, context);
+
+    bc::reduce_by_key(keys_input.begin(), keys_input.end(), values_input.begin(),
+                      keys_output.begin(), values_output.begin(), queue);
+
+    CHECK_RANGE_EQUAL(int, 1, keys_output,   (0));
+    CHECK_RANGE_EQUAL(int2_, 1, values_output, (int2_(size, -size)));
+
+    keys_input[137] = 1;
+    keys_input[677] = 1;
+    keys_input[1001] = 1;
+    bc::inclusive_scan(keys_input.begin(), keys_input.end(), keys_input.begin(), queue);
+
+    bc::reduce_by_key(keys_input.begin(), keys_input.end(), values_input.begin(),
+                      keys_output.begin(), values_output.begin(), queue);
+
+    CHECK_RANGE_EQUAL(int, 4, keys_output,   (0, 1, 2, 3));
+    CHECK_RANGE_EQUAL(int2_, 4, values_output,
+        (int2_(137, -137), int2_(540, -540), int2_(324, -324), int2_(23, -23)));
+}
+
+BOOST_AUTO_TEST_SUITE_END()

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/compute.git



More information about the debian-science-commits mailing list