diff --git a/hpx/parallel/algorithms/sort.hpp b/hpx/parallel/algorithms/sort.hpp index f93a8f29f2dc..44a84232c81c 100755 --- a/hpx/parallel/algorithms/sort.hpp +++ b/hpx/parallel/algorithms/sort.hpp @@ -1,6 +1,6 @@ // Copyright (c) 2015 John Biddiscombe // Copyright (c) 2015 Hartmut Kaiser -// Copyright (c) 2015 Francisco José Tapia +// Copyright (c) 2015 Francisco Jose Tapia // // 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) @@ -45,25 +45,6 @@ namespace hpx { namespace parallel { HPX_INLINE_NAMESPACE(v1) typedef typename std::remove_reference()))>::type type; }; -/* - //--------------------------------------------------------------------------- - /// @typename less_ptr_no_null - /// - /// @remarks this is the comparison object for pointers. Receive an object - /// for to compare the objects pointed. The pointers can't be nullptr - //--------------------------------------------------------------------------- - template < typename RandomIt, - typename Comp = std::less::type> > - struct less_ptr_no_null - { - Comp comp; - inline less_ptr_no_null (Comp C1 = Comp()) : comp(C1) {}; - inline bool operator ()(RandomIt T1, RandomIt T2) const - { - return comp(*T1 ,*T2); - }; - }; -*/ static const std::size_t SortLimitPerTask = 65536; @@ -78,75 +59,77 @@ namespace hpx { namespace parallel { HPX_INLINE_NAMESPACE(v1) template < typename RandomIt, typename Compare> hpx::future sort_thread(RandomIt first, RandomIt last, Compare comp) { - using hpx::lcos::local::dataflow; + using hpx::lcos::local::dataflow; - //------------------------- begin ---------------------- - size_t N = last - first; - if (N <= SortLimitPerTask) { - return hpx::async( - [first, last, comp]() { - std::sort(first, last, comp); - } - ); - }; + //------------------------- begin ---------------------- + size_t N = last - first; + if (N <= SortLimitPerTask) { + return hpx::async( + [first, last, comp]() { + std::sort(first, last, comp); + } + ); + }; - //---------------------------------------------------------------- - // split - //---------------------------------------------------------------- - typedef typename iter_value::type value_t; + //---------------------------------------------------------------- + // split + //---------------------------------------------------------------- + typedef typename iter_value::type value_t; - //------------------- check if sort ------------------------------ - bool SW = true; - for (RandomIt it1 = first, it2 = first + 1; - it2 != last && (SW = !comp(*it2, *it1)); it1 = it2++); + //------------------- check if sort ------------------------------ + bool SW = true; + for (RandomIt it1 = first, it2 = first + 1; + it2 != last && (SW = !comp(*it2, *it1)); it1 = it2++) {}; if (SW) { - return hpx::make_ready_future(); + return hpx::make_ready_future(); }; - //---------------------- pivot select ---------------------------- - size_t Nx = (size_t(N) >> 1); + //---------------------- pivot select ---------------------------- + size_t Nx = (size_t(N) >> 1); - RandomIt itA = first + 1; - RandomIt itB = first + Nx; - RandomIt itC = last - 1; + RandomIt itA = first + 1; + RandomIt itB = first + Nx; + RandomIt itC = last - 1; - if (comp(*itB, *itA)) std::swap(*itA, *itB); - if (comp(*itC, *itB)) - { - std::swap(*itC, *itB); if (comp(*itB, *itA)) std::swap(*itA, *itB); - }; - std::swap(*first, *itB); - value_t & val = const_cast < value_t &>(*first); - RandomIt c_first = first + 2, c_last = last - 2; + if (comp(*itC, *itB)) + { + std::swap(*itC, *itB); + if (comp(*itB, *itA)) std::swap(*itA, *itB); + }; + std::swap(*first, *itB); + value_t & val = const_cast < value_t &>(*first); + RandomIt c_first = first + 2, c_last = last - 2; - while (c_first != last && comp(*c_first, val)) ++c_first; - while (comp(val, *c_last)) --c_last; - while (!(c_first > c_last)) - { - std::swap(*(c_first++), *(c_last--)); - while (comp(*c_first, val)) ++c_first; + while (c_first != last && comp(*c_first, val)) ++c_first; while (comp(val, *c_last)) --c_last; - }; // End while - std::swap(*first, *c_last); + while (!(c_first > c_last)) + { + std::swap(*(c_first++), *(c_last--)); + while (comp(*c_first, val)) ++c_first; + while (comp(val, *c_last)) --c_last; + }; // End while + std::swap(*first, *c_last); - // spawn tasks for each sub section - hpx::future hk1 = hpx::async< decltype(&sort_thread) >(&sort_thread, first, c_last, comp); - hpx::future hk2 = hpx::async< decltype(&sort_thread) >(&sort_thread, c_first, last, comp); - return dataflow( - [](future f1, future f2) -> void - { - f1.get(); - f2.get(); - return; - }, std::move(hk1), std::move(hk2) + // spawn tasks for each sub section + hpx::future hk1 = + hpx::async< decltype(&sort_thread) > + (&sort_thread, first, c_last, comp); + hpx::future hk2 = + hpx::async< decltype(&sort_thread) > + (&sort_thread, c_first, last, comp); + return dataflow( + [](future f1, future f2) -> void + { + f1.get(); + f2.get(); + }, std::move(hk1), std::move(hk2) ); } - + //------------------------------------------------------------------------ // function : parallel_sort_async //------------------------------------------------------------------------ - /// @brief constructor of the struct /// @param [in] first : iterator to the first element to sort /// @param [in] last : iterator to the next element after the last /// @param [in] comp : object for to compare @@ -158,7 +141,7 @@ namespace hpx { namespace parallel { HPX_INLINE_NAMESPACE(v1) hpx::future parallel_sort_async(RandomIt first, RandomIt last, Compare comp) { size_t N = last - first; - assert (N >=0); + HPX_ASSERT(N>=0); if (N < SortLimitPerTask) { @@ -169,10 +152,11 @@ namespace hpx { namespace parallel { HPX_INLINE_NAMESPACE(v1) // check if already sorted bool SW = true; for ( RandomIt it1 = first, it2 = first+1; - it2 != last && (SW = !comp(*it2,*it1));it1 = it2++); + it2 != last && (SW = !comp(*it2,*it1));it1 = it2++); if (SW) return hpx::make_ready_future(); - return hpx::async< decltype(&sort_thread) >(&sort_thread, first, last, comp); + return hpx::async< decltype(&sort_thread) > + (&sort_thread, first, last, comp); } /////////////////////////////////////////////////////////////////////////// @@ -190,8 +174,8 @@ namespace hpx { namespace parallel { HPX_INLINE_NAMESPACE(v1) typename Compare = std::less::type>, typename Proj = util::projection_identity > static hpx::util::unused_type - sequential(ExPolicy, RandomIt first, RandomIt last, Compare && comp = Compare(), - Proj && proj = Proj()) + sequential(ExPolicy, RandomIt first, RandomIt last, + Compare && comp = Compare(), Proj && proj = Proj()) { std::sort(first, last, std::forward(comp)); return hpx::util::unused; @@ -202,15 +186,16 @@ namespace hpx { namespace parallel { HPX_INLINE_NAMESPACE(v1) typename Compare = std::less::type>, typename Proj = util::projection_identity> static typename util::detail::algorithm_result::type - parallel(ExPolicy policy, RandomIt first, RandomIt last, Compare && comp = Compare(), - Proj && proj = Proj()) + parallel(ExPolicy policy, RandomIt first, RandomIt last, + Compare && comp = Compare(), Proj && proj = Proj()) { - // call the sort routine and return the right type, depending on execution policy + // call the sort routine and return the right type, + // depending on execution policy return util::detail::algorithm_result::get( parallel_sort_async(first, last, std::forward(comp))); } }; - /// \endcond + /// \endcond } //----------------------------------------------------------------------------- @@ -235,14 +220,14 @@ namespace hpx { namespace parallel { HPX_INLINE_NAMESPACE(v1) /// the algorithm will be applied to. /// \param last Refers to the end of the sequence of elements /// the algorithm will be applied to. - /// \param comp comparison operator used to order the elements pointed by RandomIt - /// iterators + /// \param comp comparison operator used to order the elements + /// pointed by RandomIt iterators /// @exception /// @return /// @remarks //----------------------------------------------------------------------------- - template ::type > > inline typename boost::enable_if< is_execution_policy, diff --git a/tests/unit/parallel/algorithms/sort_tests.hpp b/tests/unit/parallel/algorithms/sort_tests.hpp index d3e85252184e..845080951949 100644 --- a/tests/unit/parallel/algorithms/sort_tests.hpp +++ b/tests/unit/parallel/algorithms/sort_tests.hpp @@ -41,21 +41,21 @@ int verify(const std::vector &A, Compare comp, bool print) { IA temp = *(A.begin()); for (typename std::vector::const_iterator it=A.begin(); it!=A.end(); ++it) { if (comp((*it),temp)) { - if (print) std::cout << "Verify fail " << A.size() << std::endl; + if (print) std::cout << "fail " << A.size() << std::endl; return 0; } temp = (*it); } } - if (print) std::cout << "Verify OK " << A.size() << std::endl; + if (print) std::cout << "OK " << A.size() << std::endl; return 1; } #define msg(a,b,c,d,e) \ std::cout \ - << std::setw(60) << a << std::setw(3) << b \ - << std::setw(20) << c << std::setw(6) << #d \ + << std::setw(60) << a << std::setw(12) << b \ + << std::setw(40) << c << std::setw(6) << #d \ << std::setw(8) << #e << "\t"; //////////////////////////////////////////////////////////////////////////////// @@ -68,7 +68,8 @@ void test_sort1(ExPolicy && policy, T) // Fill vector with random values std::vector c(5000000); - rnd_fill(c, std::numeric_limits::min(), std::numeric_limits::max(), std::random_device{}()); + rnd_fill(c, (std::numeric_limits::min)(), + (std::numeric_limits::max)(), std::random_device{}()); // sort, blocking when seq, par, par_vec hpx::parallel::sort(std::forward(policy), @@ -88,7 +89,8 @@ template > // Fill vector with random values std::vector c(5000000); - rnd_fill(c, std::numeric_limits::min(), std::numeric_limits::max(), std::random_device{}()); + rnd_fill(c, (std::numeric_limits::min)(), + (std::numeric_limits::max)(), std::random_device{}()); // sort, blocking when seq, par, par_vec hpx::parallel::sort(std::forward(policy), @@ -107,7 +109,8 @@ template > // Fill vector with random values std::vector c(5000000); - rnd_fill(c, std::numeric_limits::min(), std::numeric_limits::max(), std::random_device{}()); + rnd_fill(c, (std::numeric_limits::min)(), + (std::numeric_limits::max)(), std::random_device{}()); // sort, non blocking hpx::future f = hpx::parallel::sort(std::forward(policy), @@ -176,197 +179,5 @@ void test_sort2_async(ExPolicy && policy, T, Compare comp = Compare()) bool is_sorted = (verify(c, comp, true)!=0); HPX_TEST(is_sorted); } -/* -//////////////////////////////////////////////////////////////////////////////// -template -void test_sorted3(ExPolicy policy, IteratorTag) -{ - BOOST_STATIC_ASSERT(hpx::parallel::is_execution_policy::value); - - typedef std::vector::iterator base_iterator; - typedef test::test_iterator iterator; - - std::vector c_beg(10007); - std::vector c_end(10007); - //Fill with sorted values from 0 to 10006 - std::iota(boost::begin(c_beg), boost::end(c_beg), 0); - std::iota(boost::begin(c_end), boost::end(c_end), 0); - //add unsorted element to c_beg, c_end at the beginning, end respectively - c_beg[0] = 20000; - c_end[c_end.size()-1] = 0; - - bool is_ordered1 = hpx::parallel::is_sorted(policy, - iterator(boost::begin(c_beg)), iterator(boost::end(c_beg))); - bool is_ordered2 = hpx::parallel::is_sorted(policy, - iterator(boost::begin(c_end)), iterator(boost::end(c_end))); - - HPX_TEST(!is_ordered1); - HPX_TEST(!is_ordered2); -} - -template -void test_sorted3_async(ExPolicy p, IteratorTag) -{ - BOOST_STATIC_ASSERT(hpx::parallel::is_execution_policy::value); - - typedef std::vector::iterator base_iterator; - typedef test::test_iterator iterator; - - std::vector c_beg(10007); - std::vector c_end(10007); - //Fill with sorted values from 0 to 10006 - std::iota(boost::begin(c_beg), boost::end(c_beg), 0); - std::iota(boost::begin(c_end), boost::end(c_end), 0); - //add unsorted element to c_beg, c_end at the beginning, end respectively - c_beg[0] = 20000; - c_end[c_end.size()-1] = 0; - - hpx::future f1 = hpx::parallel::is_sorted(p, - iterator(boost::begin(c_beg)), iterator(boost::end(c_beg))); - hpx::future f2 = hpx::parallel::is_sorted(p, - iterator(boost::begin(c_end)), iterator(boost::end(c_end))); - f1.wait(); - HPX_TEST(!f1.get()); - f2.wait(); - HPX_TEST(!f2.get()); -} - -//////////////////////////////////////////////////////////////////////////////// -template -void test_sorted_exception(ExPolicy policy, IteratorTag) -{ - BOOST_STATIC_ASSERT(hpx::parallel::is_execution_policy::value); - - typedef std::vector::iterator base_iterator; - typedef test::decorated_iterator - decorated_iterator; - std::vector c(10007); - std::iota(boost::begin(c), boost::end(c), 0); - - bool caught_exception = false; - try{ - hpx::parallel::is_sorted(policy, - decorated_iterator( - boost::begin(c), - [](){ throw std::runtime_error("test"); }), - decorated_iterator( - boost::end(c), - [](){ throw std::runtime_error("test"); })); - } - catch(hpx::exception_list const& e) { - caught_exception = true; - test::test_num_exceptions::call(policy, e); - } - catch(...) { - HPX_TEST(false); - } - HPX_TEST(caught_exception); -} - -template -void test_sorted_exception_async(ExPolicy p, IteratorTag) -{ - typedef std::vector::iterator base_iterator; - typedef test::decorated_iterator - decorated_iterator; - - std::vector c(10007); - std::iota(boost::begin(c), boost::end(c), std::rand() + 1); - - bool caught_exception = false; - try { - hpx::future f = - hpx::parallel::is_sorted(p, - decorated_iterator( - boost::begin(c), - [](){ throw std::runtime_error("test"); }), - decorated_iterator( - boost::end(c), - [](){ throw std::runtime_error("test"); })); - f.get(); - - HPX_TEST(false); - } - catch(hpx::exception_list const& e) { - caught_exception = true; - test::test_num_exceptions< - ExPolicy, IteratorTag - >::call(p, e); - } - catch(...) { - HPX_TEST(false); - } - - HPX_TEST(caught_exception); -} - -//////////////////////////////////////////////////////////////////////////////// -template -void test_sorted_bad_alloc(ExPolicy policy, IteratorTag) -{ - BOOST_STATIC_ASSERT(hpx::parallel::is_execution_policy::value); - - typedef std::vector::iterator base_iterator; - typedef test::decorated_iterator - decorated_iterator; - - std::vector c(100007); - std::iota(boost::begin(c), boost::end(c), 0); - - bool caught_bad_alloc = false; - try { - hpx::parallel::is_sorted(policy, - decorated_iterator( - boost::begin(c), - [](){ throw std::bad_alloc(); }), - decorated_iterator( - boost::end(c), - [](){ throw std::bad_alloc(); })); - HPX_TEST(false); - } - catch(std::bad_alloc const&) { - caught_bad_alloc = true; - } - catch(...) { - HPX_TEST(false); - } - - HPX_TEST(caught_bad_alloc); -} - -template -void test_sorted_bad_alloc_async(ExPolicy p, IteratorTag) -{ - typedef std::vector::iterator base_iterator; - typedef test::decorated_iterator - decorated_iterator; - - std::vector c(10007); - std::iota(boost::begin(c), boost::end(c), 0); - - bool caught_bad_alloc = false; - try { - hpx::future f = - hpx::parallel::is_sorted(p, - decorated_iterator( - boost::begin(c), - [](){ throw std::bad_alloc(); }), - decorated_iterator( - boost::end(c), - [](){ throw std::bad_alloc(); })); - - f.get(); - HPX_TEST(false); - } - catch(std::bad_alloc const&) { - caught_bad_alloc = true; - } - catch(...) { - HPX_TEST(false); - } - - HPX_TEST(caught_bad_alloc); -} - */ #endif