summaryrefslogtreecommitdiff
path: root/boost/sort/common/range.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/sort/common/range.hpp')
-rw-r--r--boost/sort/common/range.hpp399
1 files changed, 399 insertions, 0 deletions
diff --git a/boost/sort/common/range.hpp b/boost/sort/common/range.hpp
new file mode 100644
index 0000000000..072d98a938
--- /dev/null
+++ b/boost/sort/common/range.hpp
@@ -0,0 +1,399 @@
+//----------------------------------------------------------------------------
+/// @file range.hpp
+/// @brief Define a range [first, last), and the associated operations
+///
+/// @author Copyright (c) 2016 Francisco José Tapia (fjtapia@gmail.com )\n
+/// Distributed under the Boost Software License, Version 1.0.\n
+/// ( See accompanyingfile LICENSE_1_0.txt or copy at
+/// http://www.boost.org/LICENSE_1_0.txt )
+/// @version 0.1
+///
+/// @remarks
+//-----------------------------------------------------------------------------
+#ifndef __BOOST_SORT_PARALLEL_DETAIL_UTIL_RANGE_HPP
+#define __BOOST_SORT_PARALLEL_DETAIL_UTIL_RANGE_HPP
+
+#include <boost/sort/common/util/algorithm.hpp>
+#include <boost/sort/common/util/merge.hpp>
+#include <boost/sort/common/util/traits.hpp>
+#include <cassert>
+#include <functional>
+#include <memory>
+#include <vector>
+
+namespace boost
+{
+namespace sort
+{
+namespace common
+{
+
+///---------------------------------------------------------------------------
+/// @struct range
+/// @brief this represent a range between two iterators
+/// @remarks
+//----------------------------------------------------------------------------
+template <class Iter_t>
+struct range
+{
+ Iter_t first, last;
+ //
+ //------------------------------------------------------------------------
+ // function : range
+ /// @brief empty constructor
+ //------------------------------------------------------------------------
+ range(void) { };
+ //
+ //------------------------------------------------------------------------
+ // function : range
+ /// @brief constructor with two parameters
+ /// @param frs : iterator to the first element
+ /// @param lst : iterator to the last element
+ //-----------------------------------------------------------------------
+ range(const Iter_t &frs, const Iter_t &lst): first(frs), last(lst) { };
+ //
+ //-----------------------------------------------------------------------
+ // function : empty
+ /// @brief indicate if the range is empty
+ /// @return true : empty false : not empty
+ //-----------------------------------------------------------------------
+ bool empty(void) const { return (first == last); };
+ //
+ //-----------------------------------------------------------------------
+ // function : not_empty
+ /// @brief indicate if the range is not empty
+ /// @return true : not empty false : empty
+ //-----------------------------------------------------------------------
+ bool not_empty(void) const {return (first != last); };
+ //
+ //-----------------------------------------------------------------------
+ // function : valid
+ /// @brief Indicate if the range is well constructed, and valid
+ /// @return true : valid, false : not valid
+ //-----------------------------------------------------------------------
+ bool valid(void) const { return ((last - first) >= 0); };
+ //
+ //-----------------------------------------------------------------------
+ // function : size
+ /// @brief return the size of the range
+ /// @return size
+ //-----------------------------------------------------------------------
+ size_t size(void) const { return (last - first); };
+ //
+ //------------------------------------------------------------------------
+ // function : front
+ /// @brief return an iterator to the first element of the range
+ /// @return iterator
+ //-----------------------------------------------------------------------
+ Iter_t front(void) const { return first; };
+ //
+ //-------------------------------------------------------------------------
+ // function : back
+ /// @brief return an iterator to the last element of the range
+ /// @return iterator
+ //-------------------------------------------------------------------------
+ Iter_t back(void) const {return (last - 1); };
+};
+
+//
+//-----------------------------------------------------------------------------
+// function : concat
+/// @brief concatenate two contiguous ranges
+/// @param it1 : first range
+/// @param it2 : second range
+/// @return range resulting of the concatenation
+//-----------------------------------------------------------------------------
+template<class Iter_t>
+inline range<Iter_t> concat(const range<Iter_t> &it1, const range<Iter_t> &it2)
+{
+ return range<Iter_t>(it1.first, it2.last);
+}
+;
+//
+//-----------------------------------------------------------------------------
+// function : move_forward
+/// @brief Move initialized objets from the range src to dest
+/// @param dest : range where move the objects
+/// @param src : range from where move the objects
+/// @return range with the objects moved and the size adjusted
+//-----------------------------------------------------------------------------
+template <class Iter1_t, class Iter2_t>
+inline range<Iter2_t> move_forward(const range<Iter2_t> &dest,
+ const range<Iter1_t> &src)
+{
+ assert(dest.size() >= src.size());
+ Iter2_t it_aux = util::move_forward(dest.first, src.first, src.last);
+ return range<Iter2_t>(dest.first, it_aux);
+};
+//
+//-----------------------------------------------------------------------------
+// function : move_backward
+/// @brief Move initialized objets from the range src to dest
+/// @param dest : range where move the objects
+/// @param src : range from where move the objects
+/// @return range with the objects moved and the size adjusted
+//-----------------------------------------------------------------------------
+template <class Iter1_t, class Iter2_t>
+inline range<Iter2_t> move_backward(const range<Iter2_t> &dest,
+ const range<Iter1_t> &src)
+{
+ assert(dest.size() >= src.size());
+ Iter2_t it_aux = util::move_backward(dest.first + src.size(), src.first,
+ src.last);
+ return range<Iter2_t>(dest.first, dest.src.size());
+};
+
+//-----------------------------------------------------------------------------
+// function : uninit_move
+/// @brief Move uninitialized objets from the range src creating them in dest
+///
+/// @param dest : range where move and create the objects
+/// @param src : range from where move the objects
+/// @return range with the objects moved and the size adjusted
+//-----------------------------------------------------------------------------
+template<class Iter_t, class Value_t = util::value_iter<Iter_t> >
+inline range<Value_t*> move_construct(const range<Value_t*> &dest,
+ const range<Iter_t> &src)
+{
+ Value_t *ptr_aux = util::move_construct(dest.first, src.first, src.last);
+ return range<Value_t*>(dest.first, ptr_aux);
+};
+//
+//-----------------------------------------------------------------------------
+// function : destroy
+/// @brief destroy a range of objects
+/// @param rng : range to destroy
+//-----------------------------------------------------------------------------
+template<class Iter_t>
+inline void destroy(range<Iter_t> rng)
+{
+ util::destroy(rng.first, rng.last);
+};
+//
+//-----------------------------------------------------------------------------
+// function : initialize
+/// @brief initialize a range of objects with the object val moving across them
+/// @param rng : range of elements not initialized
+/// @param val : object used for the initialization
+/// @return range initialized
+//-----------------------------------------------------------------------------
+template<class Iter_t, class Value_t = util::value_iter<Iter_t> >
+inline range<Iter_t> initialize(const range<Iter_t> &rng, Value_t &val)
+{
+ util::initialize(rng.first, rng.last, val);
+ return rng;
+};
+//
+//-----------------------------------------------------------------------------
+// function : is_mergeable
+/// @brief : indicate if two ranges have a possible merge
+/// @param src1 : first range
+/// @param src2 : second range
+/// @param comp : object for to compare elements
+/// @return true : they can be merged
+/// false : they can't be merged
+//-----------------------------------------------------------------------------
+template<class Iter1_t, class Iter2_t, class Compare>
+inline bool is_mergeable(const range<Iter1_t> &src1, const range<Iter2_t> &src2,
+ Compare comp)
+{
+ //------------------------------------------------------------------------
+ // Metaprogramming
+ //------------------------------------------------------------------------
+ typedef util::value_iter<Iter1_t> type1;
+ typedef util::value_iter<Iter2_t> type2;
+ static_assert (std::is_same< type1, type2 >::value,
+ "Incompatible iterators\n");
+ //------------------------------------------------------------------------
+ // Code
+ //------------------------------------------------------------------------
+ return comp(*(src2.front()), *(src1.back()));
+};
+//
+//-----------------------------------------------------------------------------
+// function : is_mergeable_stable
+/// @brief : indicate if two ranges have a possible merge
+/// @param src1 : first range
+/// @param src2 : second range
+/// @param comp : object for to compare elements
+/// @return true : they can be merged
+/// false : they can't be merged
+//-----------------------------------------------------------------------------
+template<class Iter1_t, class Iter2_t, class Compare>
+inline bool is_mergeable_stable(const range<Iter1_t> &src1,
+ const range<Iter2_t> &src2, Compare comp)
+{
+ //------------------------------------------------------------------------
+ // Metaprogramming
+ //------------------------------------------------------------------------
+ typedef util::value_iter<Iter1_t> type1;
+ typedef util::value_iter<Iter2_t> type2;
+ static_assert (std::is_same< type1, type2 >::value,
+ "Incompatible iterators\n");
+ //------------------------------------------------------------------------
+ // Code
+ //------------------------------------------------------------------------
+ return not comp(*(src1.back()), *(src2.front()));
+};
+//
+//-----------------------------------------------------------------------------
+// function : merge
+/// @brief Merge two contiguous ranges src1 and src2, and put the result in
+/// the range dest, returning the range merged
+///
+/// @param dest : range where locate the lements merged. the size of dest
+/// must be greater or equal than the sum of the sizes of
+/// src1 and src2
+/// @param src1 : first range to merge
+/// @param src2 : second range to merge
+/// @param comp : comparison object
+/// @return range with the elements merged and the size adjusted
+//-----------------------------------------------------------------------------
+template<class Iter1_t, class Iter2_t, class Iter3_t, class Compare>
+inline range<Iter3_t> merge(const range<Iter3_t> &dest,
+ const range<Iter1_t> &src1,
+ const range<Iter2_t> &src2, Compare comp)
+{
+ Iter3_t it_aux = util::merge(src1.first, src1.last, src2.first, src2.last,
+ dest.first, comp);
+ return range<Iter3_t>(dest.first, it_aux);
+};
+
+//-----------------------------------------------------------------------------
+// function : merge_construct
+/// @brief Merge two contiguous uninitialized ranges src1 and src2, and create
+/// and move the result in the uninitialized range dest, returning the
+/// range merged
+//
+/// @param dest : range where locate the elements merged. the size of dest
+/// must be greater or equal than the sum of the sizes of
+/// src1 and src2. Initially is uninitialize memory
+/// @param src1 : first range to merge
+/// @param src2 : second range to merge
+/// @param comp : comparison object
+/// @return range with the elements merged and the size adjusted
+//-----------------------------------------------------------------------------
+template<class Iter1_t, class Iter2_t, class Value_t, class Compare>
+inline range<Value_t *> merge_construct(const range<Value_t *> &dest,
+ const range<Iter1_t> &src1,
+ const range<Iter2_t> &src2,
+ Compare comp)
+{
+ Value_t * ptr_aux = util::merge_construct(src1.first, src1.last, src2.first,
+ src2.last, dest.first, comp);
+ return range<Value_t*>(dest.first, ptr_aux);
+};
+//
+//---------------------------------------------------------------------------
+// function : half_merge
+/// @brief : Merge two initialized buffers. The first buffer is in a separate
+/// memory
+//
+/// @param dest : range where finish the two buffers merged
+/// @param src1 : first range to merge in a separate memory
+/// @param src2 : second range to merge, in the final part of the
+/// range where deposit the final results
+/// @param comp : object for compare two elements of the type pointed
+/// by the Iter1_t and Iter2_t
+/// @return : range with the two buffers merged
+//---------------------------------------------------------------------------
+template<class Iter1_t, class Iter2_t, class Compare>
+inline range<Iter2_t> merge_half(const range<Iter2_t> &dest,
+ const range<Iter1_t> &src1,
+ const range<Iter2_t> &src2, Compare comp)
+{
+ Iter2_t it_aux = util::merge_half(src1.first, src1.last, src2.first,
+ src2.last, dest.first, comp);
+ return range<Iter2_t>(dest.first, it_aux);
+};
+//
+//-----------------------------------------------------------------------------
+// function : merge_uncontiguous
+/// @brief : merge two non contiguous ranges src1, src2, using the range
+/// aux as auxiliary memory. The results are in the original ranges
+//
+/// @param src1 : first range to merge
+/// @param src2 : second range to merge
+/// @param aux : auxiliary range used in the merge
+/// @param comp : object for to compare elements
+/// @return true : not changes done, false : changes in the buffers
+//-----------------------------------------------------------------------------
+template<class Iter1_t, class Iter2_t, class Iter3_t, class Compare>
+inline bool merge_uncontiguous(const range<Iter1_t> &src1,
+ const range<Iter2_t> &src2,
+ const range<Iter3_t> &aux, Compare comp)
+{
+ return util::merge_uncontiguous(src1.first, src1.last, src2.first,
+ src2.last, aux.first, comp);
+};
+//
+//-----------------------------------------------------------------------------
+// function : merge_contiguous
+/// @brief : merge two contiguous ranges ( src1, src2) using buf as
+/// auxiliary memory. The results are in the same ranges
+/// @param src1 : first range to merge
+/// @param src1 : second range to merge
+/// @param buf : auxiliary memory used in the merge
+/// @param comp : object for to compare elements
+/// @return true : not changes done, false : changes in the buffers
+//-----------------------------------------------------------------------------
+template<class Iter1_t, class Iter2_t, class Compare>
+inline range<Iter1_t> merge_contiguous(const range<Iter1_t> &src1,
+ const range<Iter1_t> &src2,
+ const range<Iter2_t> &buf, Compare comp)
+{
+ util::merge_contiguous(src1.first, src1.last, src2.last, buf.first, comp);
+ return concat(src1, src2);
+};
+//
+//-----------------------------------------------------------------------------
+// function : merge_flow
+/// @brief : merge two ranges, as part of a merge the ranges in a list. This
+/// function reduce the number of movements compared with inplace_merge
+/// when you need to merge a sequence of ranges.
+/// This function merge the ranges rbuf and rng2, and the results
+/// are in rng1 and rbuf
+//
+/// @param rng1 : range where locate the first elements of the merge
+/// @param rbuf : range which provide the first elements, and where store
+/// the last results of the merge
+/// @param rng2 : range which provide the last elements to merge
+/// @param comp : object for to compare elements
+/// @return true : not changes done, false : changes in the buffers
+//-----------------------------------------------------------------------------
+template<class Iter1_t, class Iter2_t, class Compare>
+static void merge_flow(range<Iter1_t> rng1, range<Iter2_t> rbuf,
+ range<Iter1_t> rng2, Compare cmp)
+{
+ //-------------------------------------------------------------------------
+ // Metaprogramming
+ //-------------------------------------------------------------------------
+ typedef util::value_iter<Iter1_t> type1;
+ typedef util::value_iter<Iter2_t> type2;
+ static_assert (std::is_same< type1, type2 >::value,
+ "Incompatible iterators\n");
+
+ //-------------------------------------------------------------------------
+ // Code
+ //-------------------------------------------------------------------------
+ range<Iter2_t> rbx(rbuf);
+ range<Iter1_t> rx1(rng1), rx2(rng2);
+ assert(rbx.size() == rx1.size() and rx1.size() == rx2.size());
+ while (rx1.first != rx1.last)
+ {
+ *(rx1.first++) = (cmp(*rbx.first, *rx2.first)) ?
+ std::move(*(rbx.first++)):
+ std::move(*(rx2.first++));
+ };
+ if (rx2.first == rx2.last) return;
+ if (rbx.first == rbx.last) move_forward(rbuf, rng2);
+ else merge_half(rbuf, rx2, rbx, cmp);
+};
+
+//****************************************************************************
+};// End namespace common
+};// End namespace sort
+};// End namespace boost
+//****************************************************************************
+//
+#endif