Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

645 lines
22KB

  1. // -*- C++ -*-
  2. // Copyright (C) 2007-2020 Free Software Foundation, Inc.
  3. //
  4. // This file is part of the GNU ISO C++ Library. This library is free
  5. // software; you can redistribute it and/or modify it under the terms
  6. // of the GNU General Public License as published by the Free Software
  7. // Foundation; either version 3, or (at your option) any later
  8. // version.
  9. // This library is distributed in the hope that it will be useful, but
  10. // WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. // General Public License for more details.
  13. // Under Section 7 of GPL version 3, you are granted additional
  14. // permissions described in the GCC Runtime Library Exception, version
  15. // 3.1, as published by the Free Software Foundation.
  16. // You should have received a copy of the GNU General Public License and
  17. // a copy of the GCC Runtime Library Exception along with this program;
  18. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. // <http://www.gnu.org/licenses/>.
  20. /** @file parallel/multiseq_selection.h
  21. * @brief Functions to find elements of a certain global __rank in
  22. * multiple sorted sequences. Also serves for splitting such
  23. * sequence sets.
  24. *
  25. * The algorithm description can be found in
  26. *
  27. * P. J. Varman, S. D. Scheufler, B. R. Iyer, and G. R. Ricard.
  28. * Merging Multiple Lists on Hierarchical-Memory Multiprocessors.
  29. * Journal of Parallel and Distributed Computing, 12(2):171-177, 1991.
  30. *
  31. * This file is a GNU parallel extension to the Standard C++ Library.
  32. */
  33. // Written by Johannes Singler.
  34. #ifndef _GLIBCXX_PARALLEL_MULTISEQ_SELECTION_H
  35. #define _GLIBCXX_PARALLEL_MULTISEQ_SELECTION_H 1
  36. #include <vector>
  37. #include <queue>
  38. #include <bits/stl_algo.h>
  39. namespace __gnu_parallel
  40. {
  41. /** @brief Compare __a pair of types lexicographically, ascending. */
  42. template<typename _T1, typename _T2, typename _Compare>
  43. class _Lexicographic
  44. : public std::binary_function<std::pair<_T1, _T2>,
  45. std::pair<_T1, _T2>, bool>
  46. {
  47. private:
  48. _Compare& _M_comp;
  49. public:
  50. _Lexicographic(_Compare& __comp) : _M_comp(__comp) { }
  51. bool
  52. operator()(const std::pair<_T1, _T2>& __p1,
  53. const std::pair<_T1, _T2>& __p2) const
  54. {
  55. if (_M_comp(__p1.first, __p2.first))
  56. return true;
  57. if (_M_comp(__p2.first, __p1.first))
  58. return false;
  59. // Firsts are equal.
  60. return __p1.second < __p2.second;
  61. }
  62. };
  63. /** @brief Compare __a pair of types lexicographically, descending. */
  64. template<typename _T1, typename _T2, typename _Compare>
  65. class _LexicographicReverse : public std::binary_function<_T1, _T2, bool>
  66. {
  67. private:
  68. _Compare& _M_comp;
  69. public:
  70. _LexicographicReverse(_Compare& __comp) : _M_comp(__comp) { }
  71. bool
  72. operator()(const std::pair<_T1, _T2>& __p1,
  73. const std::pair<_T1, _T2>& __p2) const
  74. {
  75. if (_M_comp(__p2.first, __p1.first))
  76. return true;
  77. if (_M_comp(__p1.first, __p2.first))
  78. return false;
  79. // Firsts are equal.
  80. return __p2.second < __p1.second;
  81. }
  82. };
  83. /**
  84. * @brief Splits several sorted sequences at a certain global __rank,
  85. * resulting in a splitting point for each sequence.
  86. * The sequences are passed via a sequence of random-access
  87. * iterator pairs, none of the sequences may be empty. If there
  88. * are several equal elements across the split, the ones on the
  89. * __left side will be chosen from sequences with smaller number.
  90. * @param __begin_seqs Begin of the sequence of iterator pairs.
  91. * @param __end_seqs End of the sequence of iterator pairs.
  92. * @param __rank The global rank to partition at.
  93. * @param __begin_offsets A random-access __sequence __begin where the
  94. * __result will be stored in. Each element of the sequence is an
  95. * iterator that points to the first element on the greater part of
  96. * the respective __sequence.
  97. * @param __comp The ordering functor, defaults to std::less<_Tp>.
  98. */
  99. template<typename _RanSeqs, typename _RankType, typename _RankIterator,
  100. typename _Compare>
  101. void
  102. multiseq_partition(_RanSeqs __begin_seqs, _RanSeqs __end_seqs,
  103. _RankType __rank,
  104. _RankIterator __begin_offsets,
  105. _Compare __comp = std::less<
  106. typename std::iterator_traits<typename
  107. std::iterator_traits<_RanSeqs>::value_type::
  108. first_type>::value_type>()) // std::less<_Tp>
  109. {
  110. _GLIBCXX_CALL(__end_seqs - __begin_seqs)
  111. typedef typename std::iterator_traits<_RanSeqs>::value_type::first_type
  112. _It;
  113. typedef typename std::iterator_traits<_RanSeqs>::difference_type
  114. _SeqNumber;
  115. typedef typename std::iterator_traits<_It>::difference_type
  116. _DifferenceType;
  117. typedef typename std::iterator_traits<_It>::value_type _ValueType;
  118. _Lexicographic<_ValueType, _SeqNumber, _Compare> __lcomp(__comp);
  119. _LexicographicReverse<_ValueType, _SeqNumber, _Compare> __lrcomp(__comp);
  120. // Number of sequences, number of elements in total (possibly
  121. // including padding).
  122. _DifferenceType __m = std::distance(__begin_seqs, __end_seqs), __nn = 0,
  123. __nmax, __n, __r;
  124. for (_SeqNumber __i = 0; __i < __m; __i++)
  125. {
  126. __nn += std::distance(__begin_seqs[__i].first,
  127. __begin_seqs[__i].second);
  128. _GLIBCXX_PARALLEL_ASSERT(
  129. std::distance(__begin_seqs[__i].first,
  130. __begin_seqs[__i].second) > 0);
  131. }
  132. if (__rank == __nn)
  133. {
  134. for (_SeqNumber __i = 0; __i < __m; __i++)
  135. __begin_offsets[__i] = __begin_seqs[__i].second; // Very end.
  136. // Return __m - 1;
  137. return;
  138. }
  139. _GLIBCXX_PARALLEL_ASSERT(__m != 0);
  140. _GLIBCXX_PARALLEL_ASSERT(__nn != 0);
  141. _GLIBCXX_PARALLEL_ASSERT(__rank >= 0);
  142. _GLIBCXX_PARALLEL_ASSERT(__rank < __nn);
  143. _DifferenceType* __ns = new _DifferenceType[__m];
  144. _DifferenceType* __a = new _DifferenceType[__m];
  145. _DifferenceType* __b = new _DifferenceType[__m];
  146. _DifferenceType __l;
  147. __ns[0] = std::distance(__begin_seqs[0].first, __begin_seqs[0].second);
  148. __nmax = __ns[0];
  149. for (_SeqNumber __i = 0; __i < __m; __i++)
  150. {
  151. __ns[__i] = std::distance(__begin_seqs[__i].first,
  152. __begin_seqs[__i].second);
  153. __nmax = std::max(__nmax, __ns[__i]);
  154. }
  155. __r = __rd_log2(__nmax) + 1;
  156. // Pad all lists to this length, at least as long as any ns[__i],
  157. // equality iff __nmax = 2^__k - 1.
  158. __l = (1ULL << __r) - 1;
  159. for (_SeqNumber __i = 0; __i < __m; __i++)
  160. {
  161. __a[__i] = 0;
  162. __b[__i] = __l;
  163. }
  164. __n = __l / 2;
  165. // Invariants:
  166. // 0 <= __a[__i] <= __ns[__i], 0 <= __b[__i] <= __l
  167. #define __S(__i) (__begin_seqs[__i].first)
  168. // Initial partition.
  169. std::vector<std::pair<_ValueType, _SeqNumber> > __sample;
  170. for (_SeqNumber __i = 0; __i < __m; __i++)
  171. if (__n < __ns[__i]) //__sequence long enough
  172. __sample.push_back(std::make_pair(__S(__i)[__n], __i));
  173. __gnu_sequential::sort(__sample.begin(), __sample.end(), __lcomp);
  174. for (_SeqNumber __i = 0; __i < __m; __i++) //conceptual infinity
  175. if (__n >= __ns[__i]) //__sequence too short, conceptual infinity
  176. __sample.push_back(
  177. std::make_pair(__S(__i)[0] /*__dummy element*/, __i));
  178. _DifferenceType __localrank = __rank / __l;
  179. _SeqNumber __j;
  180. for (__j = 0;
  181. __j < __localrank && ((__n + 1) <= __ns[__sample[__j].second]);
  182. ++__j)
  183. __a[__sample[__j].second] += __n + 1;
  184. for (; __j < __m; __j++)
  185. __b[__sample[__j].second] -= __n + 1;
  186. // Further refinement.
  187. while (__n > 0)
  188. {
  189. __n /= 2;
  190. _SeqNumber __lmax_seq = -1; // to avoid warning
  191. const _ValueType* __lmax = 0; // impossible to avoid the warning?
  192. for (_SeqNumber __i = 0; __i < __m; __i++)
  193. {
  194. if (__a[__i] > 0)
  195. {
  196. if (!__lmax)
  197. {
  198. __lmax = &(__S(__i)[__a[__i] - 1]);
  199. __lmax_seq = __i;
  200. }
  201. else
  202. {
  203. // Max, favor rear sequences.
  204. if (!__comp(__S(__i)[__a[__i] - 1], *__lmax))
  205. {
  206. __lmax = &(__S(__i)[__a[__i] - 1]);
  207. __lmax_seq = __i;
  208. }
  209. }
  210. }
  211. }
  212. _SeqNumber __i;
  213. for (__i = 0; __i < __m; __i++)
  214. {
  215. _DifferenceType __middle = (__b[__i] + __a[__i]) / 2;
  216. if (__lmax && __middle < __ns[__i] &&
  217. __lcomp(std::make_pair(__S(__i)[__middle], __i),
  218. std::make_pair(*__lmax, __lmax_seq)))
  219. __a[__i] = std::min(__a[__i] + __n + 1, __ns[__i]);
  220. else
  221. __b[__i] -= __n + 1;
  222. }
  223. _DifferenceType __leftsize = 0;
  224. for (_SeqNumber __i = 0; __i < __m; __i++)
  225. __leftsize += __a[__i] / (__n + 1);
  226. _DifferenceType __skew = __rank / (__n + 1) - __leftsize;
  227. if (__skew > 0)
  228. {
  229. // Move to the left, find smallest.
  230. std::priority_queue<std::pair<_ValueType, _SeqNumber>,
  231. std::vector<std::pair<_ValueType, _SeqNumber> >,
  232. _LexicographicReverse<_ValueType, _SeqNumber, _Compare> >
  233. __pq(__lrcomp);
  234. for (_SeqNumber __i = 0; __i < __m; __i++)
  235. if (__b[__i] < __ns[__i])
  236. __pq.push(std::make_pair(__S(__i)[__b[__i]], __i));
  237. for (; __skew != 0 && !__pq.empty(); --__skew)
  238. {
  239. _SeqNumber __source = __pq.top().second;
  240. __pq.pop();
  241. __a[__source]
  242. = std::min(__a[__source] + __n + 1, __ns[__source]);
  243. __b[__source] += __n + 1;
  244. if (__b[__source] < __ns[__source])
  245. __pq.push(
  246. std::make_pair(__S(__source)[__b[__source]], __source));
  247. }
  248. }
  249. else if (__skew < 0)
  250. {
  251. // Move to the right, find greatest.
  252. std::priority_queue<std::pair<_ValueType, _SeqNumber>,
  253. std::vector<std::pair<_ValueType, _SeqNumber> >,
  254. _Lexicographic<_ValueType, _SeqNumber, _Compare> >
  255. __pq(__lcomp);
  256. for (_SeqNumber __i = 0; __i < __m; __i++)
  257. if (__a[__i] > 0)
  258. __pq.push(std::make_pair(__S(__i)[__a[__i] - 1], __i));
  259. for (; __skew != 0; ++__skew)
  260. {
  261. _SeqNumber __source = __pq.top().second;
  262. __pq.pop();
  263. __a[__source] -= __n + 1;
  264. __b[__source] -= __n + 1;
  265. if (__a[__source] > 0)
  266. __pq.push(std::make_pair(
  267. __S(__source)[__a[__source] - 1], __source));
  268. }
  269. }
  270. }
  271. // Postconditions:
  272. // __a[__i] == __b[__i] in most cases, except when __a[__i] has been
  273. // clamped because of having reached the boundary
  274. // Now return the result, calculate the offset.
  275. // Compare the keys on both edges of the border.
  276. // Maximum of left edge, minimum of right edge.
  277. _ValueType* __maxleft = 0;
  278. _ValueType* __minright = 0;
  279. for (_SeqNumber __i = 0; __i < __m; __i++)
  280. {
  281. if (__a[__i] > 0)
  282. {
  283. if (!__maxleft)
  284. __maxleft = &(__S(__i)[__a[__i] - 1]);
  285. else
  286. {
  287. // Max, favor rear sequences.
  288. if (!__comp(__S(__i)[__a[__i] - 1], *__maxleft))
  289. __maxleft = &(__S(__i)[__a[__i] - 1]);
  290. }
  291. }
  292. if (__b[__i] < __ns[__i])
  293. {
  294. if (!__minright)
  295. __minright = &(__S(__i)[__b[__i]]);
  296. else
  297. {
  298. // Min, favor fore sequences.
  299. if (__comp(__S(__i)[__b[__i]], *__minright))
  300. __minright = &(__S(__i)[__b[__i]]);
  301. }
  302. }
  303. }
  304. _SeqNumber __seq = 0;
  305. for (_SeqNumber __i = 0; __i < __m; __i++)
  306. __begin_offsets[__i] = __S(__i) + __a[__i];
  307. delete[] __ns;
  308. delete[] __a;
  309. delete[] __b;
  310. }
  311. /**
  312. * @brief Selects the element at a certain global __rank from several
  313. * sorted sequences.
  314. *
  315. * The sequences are passed via a sequence of random-access
  316. * iterator pairs, none of the sequences may be empty.
  317. * @param __begin_seqs Begin of the sequence of iterator pairs.
  318. * @param __end_seqs End of the sequence of iterator pairs.
  319. * @param __rank The global rank to partition at.
  320. * @param __offset The rank of the selected element in the global
  321. * subsequence of elements equal to the selected element. If the
  322. * selected element is unique, this number is 0.
  323. * @param __comp The ordering functor, defaults to std::less.
  324. */
  325. template<typename _Tp, typename _RanSeqs, typename _RankType,
  326. typename _Compare>
  327. _Tp
  328. multiseq_selection(_RanSeqs __begin_seqs, _RanSeqs __end_seqs,
  329. _RankType __rank,
  330. _RankType& __offset, _Compare __comp = std::less<_Tp>())
  331. {
  332. _GLIBCXX_CALL(__end_seqs - __begin_seqs)
  333. typedef typename std::iterator_traits<_RanSeqs>::value_type::first_type
  334. _It;
  335. typedef typename std::iterator_traits<_RanSeqs>::difference_type
  336. _SeqNumber;
  337. typedef typename std::iterator_traits<_It>::difference_type
  338. _DifferenceType;
  339. _Lexicographic<_Tp, _SeqNumber, _Compare> __lcomp(__comp);
  340. _LexicographicReverse<_Tp, _SeqNumber, _Compare> __lrcomp(__comp);
  341. // Number of sequences, number of elements in total (possibly
  342. // including padding).
  343. _DifferenceType __m = std::distance(__begin_seqs, __end_seqs);
  344. _DifferenceType __nn = 0;
  345. _DifferenceType __nmax, __n, __r;
  346. for (_SeqNumber __i = 0; __i < __m; __i++)
  347. __nn += std::distance(__begin_seqs[__i].first,
  348. __begin_seqs[__i].second);
  349. if (__m == 0 || __nn == 0 || __rank < 0 || __rank >= __nn)
  350. {
  351. // result undefined if there is no data or __rank is outside bounds
  352. throw std::exception();
  353. }
  354. _DifferenceType* __ns = new _DifferenceType[__m];
  355. _DifferenceType* __a = new _DifferenceType[__m];
  356. _DifferenceType* __b = new _DifferenceType[__m];
  357. _DifferenceType __l;
  358. __ns[0] = std::distance(__begin_seqs[0].first, __begin_seqs[0].second);
  359. __nmax = __ns[0];
  360. for (_SeqNumber __i = 0; __i < __m; ++__i)
  361. {
  362. __ns[__i] = std::distance(__begin_seqs[__i].first,
  363. __begin_seqs[__i].second);
  364. __nmax = std::max(__nmax, __ns[__i]);
  365. }
  366. __r = __rd_log2(__nmax) + 1;
  367. // Pad all lists to this length, at least as long as any ns[__i],
  368. // equality iff __nmax = 2^__k - 1
  369. __l = __round_up_to_pow2(__r) - 1;
  370. for (_SeqNumber __i = 0; __i < __m; ++__i)
  371. {
  372. __a[__i] = 0;
  373. __b[__i] = __l;
  374. }
  375. __n = __l / 2;
  376. // Invariants:
  377. // 0 <= __a[__i] <= __ns[__i], 0 <= __b[__i] <= __l
  378. #define __S(__i) (__begin_seqs[__i].first)
  379. // Initial partition.
  380. std::vector<std::pair<_Tp, _SeqNumber> > __sample;
  381. for (_SeqNumber __i = 0; __i < __m; __i++)
  382. if (__n < __ns[__i])
  383. __sample.push_back(std::make_pair(__S(__i)[__n], __i));
  384. __gnu_sequential::sort(__sample.begin(), __sample.end(),
  385. __lcomp, sequential_tag());
  386. // Conceptual infinity.
  387. for (_SeqNumber __i = 0; __i < __m; __i++)
  388. if (__n >= __ns[__i])
  389. __sample.push_back(
  390. std::make_pair(__S(__i)[0] /*__dummy element*/, __i));
  391. _DifferenceType __localrank = __rank / __l;
  392. _SeqNumber __j;
  393. for (__j = 0;
  394. __j < __localrank && ((__n + 1) <= __ns[__sample[__j].second]);
  395. ++__j)
  396. __a[__sample[__j].second] += __n + 1;
  397. for (; __j < __m; ++__j)
  398. __b[__sample[__j].second] -= __n + 1;
  399. // Further refinement.
  400. while (__n > 0)
  401. {
  402. __n /= 2;
  403. const _Tp* __lmax = 0;
  404. for (_SeqNumber __i = 0; __i < __m; ++__i)
  405. {
  406. if (__a[__i] > 0)
  407. {
  408. if (!__lmax)
  409. __lmax = &(__S(__i)[__a[__i] - 1]);
  410. else
  411. {
  412. if (__comp(*__lmax, __S(__i)[__a[__i] - 1])) //max
  413. __lmax = &(__S(__i)[__a[__i] - 1]);
  414. }
  415. }
  416. }
  417. _SeqNumber __i;
  418. for (__i = 0; __i < __m; __i++)
  419. {
  420. _DifferenceType __middle = (__b[__i] + __a[__i]) / 2;
  421. if (__lmax && __middle < __ns[__i]
  422. && __comp(__S(__i)[__middle], *__lmax))
  423. __a[__i] = std::min(__a[__i] + __n + 1, __ns[__i]);
  424. else
  425. __b[__i] -= __n + 1;
  426. }
  427. _DifferenceType __leftsize = 0;
  428. for (_SeqNumber __i = 0; __i < __m; ++__i)
  429. __leftsize += __a[__i] / (__n + 1);
  430. _DifferenceType __skew = __rank / (__n + 1) - __leftsize;
  431. if (__skew > 0)
  432. {
  433. // Move to the left, find smallest.
  434. std::priority_queue<std::pair<_Tp, _SeqNumber>,
  435. std::vector<std::pair<_Tp, _SeqNumber> >,
  436. _LexicographicReverse<_Tp, _SeqNumber, _Compare> >
  437. __pq(__lrcomp);
  438. for (_SeqNumber __i = 0; __i < __m; ++__i)
  439. if (__b[__i] < __ns[__i])
  440. __pq.push(std::make_pair(__S(__i)[__b[__i]], __i));
  441. for (; __skew != 0 && !__pq.empty(); --__skew)
  442. {
  443. _SeqNumber __source = __pq.top().second;
  444. __pq.pop();
  445. __a[__source]
  446. = std::min(__a[__source] + __n + 1, __ns[__source]);
  447. __b[__source] += __n + 1;
  448. if (__b[__source] < __ns[__source])
  449. __pq.push(
  450. std::make_pair(__S(__source)[__b[__source]], __source));
  451. }
  452. }
  453. else if (__skew < 0)
  454. {
  455. // Move to the right, find greatest.
  456. std::priority_queue<std::pair<_Tp, _SeqNumber>,
  457. std::vector<std::pair<_Tp, _SeqNumber> >,
  458. _Lexicographic<_Tp, _SeqNumber, _Compare> > __pq(__lcomp);
  459. for (_SeqNumber __i = 0; __i < __m; ++__i)
  460. if (__a[__i] > 0)
  461. __pq.push(std::make_pair(__S(__i)[__a[__i] - 1], __i));
  462. for (; __skew != 0; ++__skew)
  463. {
  464. _SeqNumber __source = __pq.top().second;
  465. __pq.pop();
  466. __a[__source] -= __n + 1;
  467. __b[__source] -= __n + 1;
  468. if (__a[__source] > 0)
  469. __pq.push(std::make_pair(
  470. __S(__source)[__a[__source] - 1], __source));
  471. }
  472. }
  473. }
  474. // Postconditions:
  475. // __a[__i] == __b[__i] in most cases, except when __a[__i] has been
  476. // clamped because of having reached the boundary
  477. // Now return the result, calculate the offset.
  478. // Compare the keys on both edges of the border.
  479. // Maximum of left edge, minimum of right edge.
  480. bool __maxleftset = false, __minrightset = false;
  481. // Impossible to avoid the warning?
  482. _Tp __maxleft, __minright;
  483. for (_SeqNumber __i = 0; __i < __m; ++__i)
  484. {
  485. if (__a[__i] > 0)
  486. {
  487. if (!__maxleftset)
  488. {
  489. __maxleft = __S(__i)[__a[__i] - 1];
  490. __maxleftset = true;
  491. }
  492. else
  493. {
  494. // Max.
  495. if (__comp(__maxleft, __S(__i)[__a[__i] - 1]))
  496. __maxleft = __S(__i)[__a[__i] - 1];
  497. }
  498. }
  499. if (__b[__i] < __ns[__i])
  500. {
  501. if (!__minrightset)
  502. {
  503. __minright = __S(__i)[__b[__i]];
  504. __minrightset = true;
  505. }
  506. else
  507. {
  508. // Min.
  509. if (__comp(__S(__i)[__b[__i]], __minright))
  510. __minright = __S(__i)[__b[__i]];
  511. }
  512. }
  513. }
  514. // Minright is the __splitter, in any case.
  515. if (!__maxleftset || __comp(__minright, __maxleft))
  516. {
  517. // Good luck, everything is split unambiguously.
  518. __offset = 0;
  519. }
  520. else
  521. {
  522. // We have to calculate an offset.
  523. __offset = 0;
  524. for (_SeqNumber __i = 0; __i < __m; ++__i)
  525. {
  526. _DifferenceType lb
  527. = std::lower_bound(__S(__i), __S(__i) + __ns[__i],
  528. __minright,
  529. __comp) - __S(__i);
  530. __offset += __a[__i] - lb;
  531. }
  532. }
  533. delete[] __ns;
  534. delete[] __a;
  535. delete[] __b;
  536. return __minright;
  537. }
  538. }
  539. #undef __S
  540. #endif /* _GLIBCXX_PARALLEL_MULTISEQ_SELECTION_H */