range.hpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. //----------------------------------------------------------------------------
  2. /// @file range.hpp
  3. /// @brief Define a range [first, last), and the associated operations
  4. ///
  5. /// @author Copyright (c) 2016 Francisco José Tapia (fjtapia@gmail.com )\n
  6. /// Distributed under the Boost Software License, Version 1.0.\n
  7. /// ( See accompanyingfile LICENSE_1_0.txt or copy at
  8. /// http://www.boost.org/LICENSE_1_0.txt )
  9. /// @version 0.1
  10. ///
  11. /// @remarks
  12. //-----------------------------------------------------------------------------
  13. #ifndef __BOOST_SORT_PARALLEL_DETAIL_UTIL_RANGE_HPP
  14. #define __BOOST_SORT_PARALLEL_DETAIL_UTIL_RANGE_HPP
  15. #include <boost/sort/common/util/algorithm.hpp>
  16. #include <boost/sort/common/util/merge.hpp>
  17. #include <boost/sort/common/util/traits.hpp>
  18. #include <cassert>
  19. #include <functional>
  20. #include <memory>
  21. #include <vector>
  22. namespace boost
  23. {
  24. namespace sort
  25. {
  26. namespace common
  27. {
  28. ///---------------------------------------------------------------------------
  29. /// @struct range
  30. /// @brief this represent a range between two iterators
  31. /// @remarks
  32. //----------------------------------------------------------------------------
  33. template <class Iter_t>
  34. struct range
  35. {
  36. Iter_t first, last;
  37. //
  38. //------------------------------------------------------------------------
  39. // function : range
  40. /// @brief empty constructor
  41. //------------------------------------------------------------------------
  42. range(void) { };
  43. //
  44. //------------------------------------------------------------------------
  45. // function : range
  46. /// @brief constructor with two parameters
  47. /// @param frs : iterator to the first element
  48. /// @param lst : iterator to the last element
  49. //-----------------------------------------------------------------------
  50. range(const Iter_t &frs, const Iter_t &lst): first(frs), last(lst) { };
  51. //
  52. //-----------------------------------------------------------------------
  53. // function : empty
  54. /// @brief indicate if the range is empty
  55. /// @return true : empty false : not empty
  56. //-----------------------------------------------------------------------
  57. bool empty(void) const { return (first == last); };
  58. //
  59. //-----------------------------------------------------------------------
  60. // function : not_empty
  61. /// @brief indicate if the range is not empty
  62. /// @return true : not empty false : empty
  63. //-----------------------------------------------------------------------
  64. bool not_empty(void) const {return (first != last); };
  65. //
  66. //-----------------------------------------------------------------------
  67. // function : valid
  68. /// @brief Indicate if the range is well constructed, and valid
  69. /// @return true : valid, false : not valid
  70. //-----------------------------------------------------------------------
  71. bool valid(void) const { return ((last - first) >= 0); };
  72. //
  73. //-----------------------------------------------------------------------
  74. // function : size
  75. /// @brief return the size of the range
  76. /// @return size
  77. //-----------------------------------------------------------------------
  78. size_t size(void) const { return (last - first); };
  79. //
  80. //------------------------------------------------------------------------
  81. // function : front
  82. /// @brief return an iterator to the first element of the range
  83. /// @return iterator
  84. //-----------------------------------------------------------------------
  85. Iter_t front(void) const { return first; };
  86. //
  87. //-------------------------------------------------------------------------
  88. // function : back
  89. /// @brief return an iterator to the last element of the range
  90. /// @return iterator
  91. //-------------------------------------------------------------------------
  92. Iter_t back(void) const {return (last - 1); };
  93. };
  94. //
  95. //-----------------------------------------------------------------------------
  96. // function : concat
  97. /// @brief concatenate two contiguous ranges
  98. /// @param it1 : first range
  99. /// @param it2 : second range
  100. /// @return range resulting of the concatenation
  101. //-----------------------------------------------------------------------------
  102. template<class Iter_t>
  103. inline range<Iter_t> concat(const range<Iter_t> &it1, const range<Iter_t> &it2)
  104. {
  105. return range<Iter_t>(it1.first, it2.last);
  106. }
  107. ;
  108. //
  109. //-----------------------------------------------------------------------------
  110. // function : move_forward
  111. /// @brief Move initialized objets from the range src to dest
  112. /// @param dest : range where move the objects
  113. /// @param src : range from where move the objects
  114. /// @return range with the objects moved and the size adjusted
  115. //-----------------------------------------------------------------------------
  116. template <class Iter1_t, class Iter2_t>
  117. inline range<Iter2_t> move_forward(const range<Iter2_t> &dest,
  118. const range<Iter1_t> &src)
  119. {
  120. assert(dest.size() >= src.size());
  121. Iter2_t it_aux = util::move_forward(dest.first, src.first, src.last);
  122. return range<Iter2_t>(dest.first, it_aux);
  123. };
  124. //
  125. //-----------------------------------------------------------------------------
  126. // function : move_backward
  127. /// @brief Move initialized objets from the range src to dest
  128. /// @param dest : range where move the objects
  129. /// @param src : range from where move the objects
  130. /// @return range with the objects moved and the size adjusted
  131. //-----------------------------------------------------------------------------
  132. template <class Iter1_t, class Iter2_t>
  133. inline range<Iter2_t> move_backward(const range<Iter2_t> &dest,
  134. const range<Iter1_t> &src)
  135. {
  136. assert(dest.size() >= src.size());
  137. Iter2_t it_aux = util::move_backward(dest.first + src.size(), src.first,
  138. src.last);
  139. return range<Iter2_t>(dest.first, dest.src.size());
  140. };
  141. //-----------------------------------------------------------------------------
  142. // function : uninit_move
  143. /// @brief Move uninitialized objets from the range src creating them in dest
  144. ///
  145. /// @param dest : range where move and create the objects
  146. /// @param src : range from where move the objects
  147. /// @return range with the objects moved and the size adjusted
  148. //-----------------------------------------------------------------------------
  149. template<class Iter_t, class Value_t = util::value_iter<Iter_t> >
  150. inline range<Value_t*> move_construct(const range<Value_t*> &dest,
  151. const range<Iter_t> &src)
  152. {
  153. Value_t *ptr_aux = util::move_construct(dest.first, src.first, src.last);
  154. return range<Value_t*>(dest.first, ptr_aux);
  155. };
  156. //
  157. //-----------------------------------------------------------------------------
  158. // function : destroy
  159. /// @brief destroy a range of objects
  160. /// @param rng : range to destroy
  161. //-----------------------------------------------------------------------------
  162. template<class Iter_t>
  163. inline void destroy(range<Iter_t> rng)
  164. {
  165. util::destroy(rng.first, rng.last);
  166. };
  167. //
  168. //-----------------------------------------------------------------------------
  169. // function : initialize
  170. /// @brief initialize a range of objects with the object val moving across them
  171. /// @param rng : range of elements not initialized
  172. /// @param val : object used for the initialization
  173. /// @return range initialized
  174. //-----------------------------------------------------------------------------
  175. template<class Iter_t, class Value_t = util::value_iter<Iter_t> >
  176. inline range<Iter_t> initialize(const range<Iter_t> &rng, Value_t &val)
  177. {
  178. util::initialize(rng.first, rng.last, val);
  179. return rng;
  180. };
  181. //
  182. //-----------------------------------------------------------------------------
  183. // function : is_mergeable
  184. /// @brief : indicate if two ranges have a possible merge
  185. /// @param src1 : first range
  186. /// @param src2 : second range
  187. /// @param comp : object for to compare elements
  188. /// @return true : they can be merged
  189. /// false : they can't be merged
  190. //-----------------------------------------------------------------------------
  191. template<class Iter1_t, class Iter2_t, class Compare>
  192. inline bool is_mergeable(const range<Iter1_t> &src1, const range<Iter2_t> &src2,
  193. Compare comp)
  194. {
  195. //------------------------------------------------------------------------
  196. // Metaprogramming
  197. //------------------------------------------------------------------------
  198. typedef util::value_iter<Iter1_t> type1;
  199. typedef util::value_iter<Iter2_t> type2;
  200. static_assert (std::is_same< type1, type2 >::value,
  201. "Incompatible iterators\n");
  202. //------------------------------------------------------------------------
  203. // Code
  204. //------------------------------------------------------------------------
  205. return comp(*(src2.front()), *(src1.back()));
  206. };
  207. //
  208. //-----------------------------------------------------------------------------
  209. // function : is_mergeable_stable
  210. /// @brief : indicate if two ranges have a possible merge
  211. /// @param src1 : first range
  212. /// @param src2 : second range
  213. /// @param comp : object for to compare elements
  214. /// @return true : they can be merged
  215. /// false : they can't be merged
  216. //-----------------------------------------------------------------------------
  217. template<class Iter1_t, class Iter2_t, class Compare>
  218. inline bool is_mergeable_stable(const range<Iter1_t> &src1,
  219. const range<Iter2_t> &src2, Compare comp)
  220. {
  221. //------------------------------------------------------------------------
  222. // Metaprogramming
  223. //------------------------------------------------------------------------
  224. typedef util::value_iter<Iter1_t> type1;
  225. typedef util::value_iter<Iter2_t> type2;
  226. static_assert (std::is_same< type1, type2 >::value,
  227. "Incompatible iterators\n");
  228. //------------------------------------------------------------------------
  229. // Code
  230. //------------------------------------------------------------------------
  231. return not comp(*(src1.back()), *(src2.front()));
  232. };
  233. //
  234. //-----------------------------------------------------------------------------
  235. // function : merge
  236. /// @brief Merge two contiguous ranges src1 and src2, and put the result in
  237. /// the range dest, returning the range merged
  238. ///
  239. /// @param dest : range where locate the lements merged. the size of dest
  240. /// must be greater or equal than the sum of the sizes of
  241. /// src1 and src2
  242. /// @param src1 : first range to merge
  243. /// @param src2 : second range to merge
  244. /// @param comp : comparison object
  245. /// @return range with the elements merged and the size adjusted
  246. //-----------------------------------------------------------------------------
  247. template<class Iter1_t, class Iter2_t, class Iter3_t, class Compare>
  248. inline range<Iter3_t> merge(const range<Iter3_t> &dest,
  249. const range<Iter1_t> &src1,
  250. const range<Iter2_t> &src2, Compare comp)
  251. {
  252. Iter3_t it_aux = util::merge(src1.first, src1.last, src2.first, src2.last,
  253. dest.first, comp);
  254. return range<Iter3_t>(dest.first, it_aux);
  255. };
  256. //-----------------------------------------------------------------------------
  257. // function : merge_construct
  258. /// @brief Merge two contiguous uninitialized ranges src1 and src2, and create
  259. /// and move the result in the uninitialized range dest, returning the
  260. /// range merged
  261. //
  262. /// @param dest : range where locate the elements merged. the size of dest
  263. /// must be greater or equal than the sum of the sizes of
  264. /// src1 and src2. Initially is uninitialize memory
  265. /// @param src1 : first range to merge
  266. /// @param src2 : second range to merge
  267. /// @param comp : comparison object
  268. /// @return range with the elements merged and the size adjusted
  269. //-----------------------------------------------------------------------------
  270. template<class Iter1_t, class Iter2_t, class Value_t, class Compare>
  271. inline range<Value_t *> merge_construct(const range<Value_t *> &dest,
  272. const range<Iter1_t> &src1,
  273. const range<Iter2_t> &src2,
  274. Compare comp)
  275. {
  276. Value_t * ptr_aux = util::merge_construct(src1.first, src1.last, src2.first,
  277. src2.last, dest.first, comp);
  278. return range<Value_t*>(dest.first, ptr_aux);
  279. };
  280. //
  281. //---------------------------------------------------------------------------
  282. // function : half_merge
  283. /// @brief : Merge two initialized buffers. The first buffer is in a separate
  284. /// memory
  285. //
  286. /// @param dest : range where finish the two buffers merged
  287. /// @param src1 : first range to merge in a separate memory
  288. /// @param src2 : second range to merge, in the final part of the
  289. /// range where deposit the final results
  290. /// @param comp : object for compare two elements of the type pointed
  291. /// by the Iter1_t and Iter2_t
  292. /// @return : range with the two buffers merged
  293. //---------------------------------------------------------------------------
  294. template<class Iter1_t, class Iter2_t, class Compare>
  295. inline range<Iter2_t> merge_half(const range<Iter2_t> &dest,
  296. const range<Iter1_t> &src1,
  297. const range<Iter2_t> &src2, Compare comp)
  298. {
  299. Iter2_t it_aux = util::merge_half(src1.first, src1.last, src2.first,
  300. src2.last, dest.first, comp);
  301. return range<Iter2_t>(dest.first, it_aux);
  302. };
  303. //
  304. //-----------------------------------------------------------------------------
  305. // function : merge_uncontiguous
  306. /// @brief : merge two non contiguous ranges src1, src2, using the range
  307. /// aux as auxiliary memory. The results are in the original ranges
  308. //
  309. /// @param src1 : first range to merge
  310. /// @param src2 : second range to merge
  311. /// @param aux : auxiliary range used in the merge
  312. /// @param comp : object for to compare elements
  313. /// @return true : not changes done, false : changes in the buffers
  314. //-----------------------------------------------------------------------------
  315. template<class Iter1_t, class Iter2_t, class Iter3_t, class Compare>
  316. inline bool merge_uncontiguous(const range<Iter1_t> &src1,
  317. const range<Iter2_t> &src2,
  318. const range<Iter3_t> &aux, Compare comp)
  319. {
  320. return util::merge_uncontiguous(src1.first, src1.last, src2.first,
  321. src2.last, aux.first, comp);
  322. };
  323. //
  324. //-----------------------------------------------------------------------------
  325. // function : merge_contiguous
  326. /// @brief : merge two contiguous ranges ( src1, src2) using buf as
  327. /// auxiliary memory. The results are in the same ranges
  328. /// @param src1 : first range to merge
  329. /// @param src1 : second range to merge
  330. /// @param buf : auxiliary memory used in the merge
  331. /// @param comp : object for to compare elements
  332. /// @return true : not changes done, false : changes in the buffers
  333. //-----------------------------------------------------------------------------
  334. template<class Iter1_t, class Iter2_t, class Compare>
  335. inline range<Iter1_t> merge_contiguous(const range<Iter1_t> &src1,
  336. const range<Iter1_t> &src2,
  337. const range<Iter2_t> &buf, Compare comp)
  338. {
  339. util::merge_contiguous(src1.first, src1.last, src2.last, buf.first, comp);
  340. return concat(src1, src2);
  341. };
  342. //
  343. //-----------------------------------------------------------------------------
  344. // function : merge_flow
  345. /// @brief : merge two ranges, as part of a merge the ranges in a list. This
  346. /// function reduce the number of movements compared with inplace_merge
  347. /// when you need to merge a sequence of ranges.
  348. /// This function merge the ranges rbuf and rng2, and the results
  349. /// are in rng1 and rbuf
  350. //
  351. /// @param rng1 : range where locate the first elements of the merge
  352. /// @param rbuf : range which provide the first elements, and where store
  353. /// the last results of the merge
  354. /// @param rng2 : range which provide the last elements to merge
  355. /// @param comp : object for to compare elements
  356. /// @return true : not changes done, false : changes in the buffers
  357. //-----------------------------------------------------------------------------
  358. template<class Iter1_t, class Iter2_t, class Compare>
  359. static void merge_flow(range<Iter1_t> rng1, range<Iter2_t> rbuf,
  360. range<Iter1_t> rng2, Compare cmp)
  361. {
  362. //-------------------------------------------------------------------------
  363. // Metaprogramming
  364. //-------------------------------------------------------------------------
  365. typedef util::value_iter<Iter1_t> type1;
  366. typedef util::value_iter<Iter2_t> type2;
  367. static_assert (std::is_same< type1, type2 >::value,
  368. "Incompatible iterators\n");
  369. //-------------------------------------------------------------------------
  370. // Code
  371. //-------------------------------------------------------------------------
  372. range<Iter2_t> rbx(rbuf);
  373. range<Iter1_t> rx1(rng1), rx2(rng2);
  374. assert(rbx.size() == rx1.size() and rx1.size() == rx2.size());
  375. while (rx1.first != rx1.last)
  376. {
  377. *(rx1.first++) = (cmp(*rbx.first, *rx2.first)) ?
  378. std::move(*(rbx.first++)):
  379. std::move(*(rx2.first++));
  380. };
  381. if (rx2.first == rx2.last) return;
  382. if (rbx.first == rbx.last) move_forward(rbuf, rng2);
  383. else merge_half(rbuf, rx2, rbx, cmp);
  384. };
  385. //****************************************************************************
  386. };// End namespace common
  387. };// End namespace sort
  388. };// End namespace boost
  389. //****************************************************************************
  390. //
  391. #endif