range.hpp 18 KB

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