algobase.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. // -*- C++ -*-
  2. // Copyright (C) 2007-2015 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/algobase.h
  21. * @brief Parallel STL function calls corresponding to the
  22. * stl_algobase.h header. The functions defined here mainly do case
  23. * switches and call the actual parallelized versions in other files.
  24. * Inlining policy: Functions that basically only contain one
  25. * function call, are declared inline.
  26. * This file is a GNU parallel extension to the Standard C++ Library.
  27. */
  28. // Written by Johannes Singler and Felix Putze.
  29. #ifndef _GLIBCXX_PARALLEL_ALGOBASE_H
  30. #define _GLIBCXX_PARALLEL_ALGOBASE_H 1
  31. #include <bits/stl_algobase.h>
  32. #include <parallel/base.h>
  33. #include <parallel/algorithmfwd.h>
  34. #include <parallel/find.h>
  35. #include <parallel/find_selectors.h>
  36. namespace std _GLIBCXX_VISIBILITY(default)
  37. {
  38. namespace __parallel
  39. {
  40. // NB: equal and lexicographical_compare require mismatch.
  41. // Sequential fallback
  42. template<typename _IIter1, typename _IIter2>
  43. inline pair<_IIter1, _IIter2>
  44. mismatch(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2,
  45. __gnu_parallel::sequential_tag)
  46. { return _GLIBCXX_STD_A::mismatch(__begin1, __end1, __begin2); }
  47. // Sequential fallback
  48. template<typename _IIter1, typename _IIter2, typename _Predicate>
  49. inline pair<_IIter1, _IIter2>
  50. mismatch(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2,
  51. _Predicate __pred, __gnu_parallel::sequential_tag)
  52. { return _GLIBCXX_STD_A::mismatch(__begin1, __end1, __begin2, __pred); }
  53. // Sequential fallback for input iterator case
  54. template<typename _IIter1, typename _IIter2,
  55. typename _Predicate, typename _IteratorTag1, typename _IteratorTag2>
  56. inline pair<_IIter1, _IIter2>
  57. __mismatch_switch(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2,
  58. _Predicate __pred, _IteratorTag1, _IteratorTag2)
  59. { return _GLIBCXX_STD_A::mismatch(__begin1, __end1, __begin2, __pred); }
  60. // Parallel mismatch for random access iterators
  61. template<typename _RAIter1, typename _RAIter2, typename _Predicate>
  62. pair<_RAIter1, _RAIter2>
  63. __mismatch_switch(_RAIter1 __begin1, _RAIter1 __end1,
  64. _RAIter2 __begin2, _Predicate __pred,
  65. random_access_iterator_tag, random_access_iterator_tag)
  66. {
  67. if (_GLIBCXX_PARALLEL_CONDITION(true))
  68. {
  69. _RAIter1 __res =
  70. __gnu_parallel::__find_template(__begin1, __end1, __begin2, __pred,
  71. __gnu_parallel::
  72. __mismatch_selector()).first;
  73. return make_pair(__res , __begin2 + (__res - __begin1));
  74. }
  75. else
  76. return _GLIBCXX_STD_A::mismatch(__begin1, __end1, __begin2, __pred);
  77. }
  78. // Public interface
  79. template<typename _IIter1, typename _IIter2>
  80. inline pair<_IIter1, _IIter2>
  81. mismatch(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2)
  82. {
  83. typedef __gnu_parallel::_EqualTo<
  84. typename std::iterator_traits<_IIter1>::value_type,
  85. typename std::iterator_traits<_IIter2>::value_type> _EqualTo;
  86. return __mismatch_switch(__begin1, __end1, __begin2, _EqualTo(),
  87. std::__iterator_category(__begin1),
  88. std::__iterator_category(__begin2));
  89. }
  90. // Public interface
  91. template<typename _IIter1, typename _IIter2, typename _Predicate>
  92. inline pair<_IIter1, _IIter2>
  93. mismatch(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2,
  94. _Predicate __pred)
  95. {
  96. return __mismatch_switch(__begin1, __end1, __begin2, __pred,
  97. std::__iterator_category(__begin1),
  98. std::__iterator_category(__begin2));
  99. }
  100. #if __cplusplus > 201103L
  101. // Sequential fallback.
  102. template<typename _InputIterator1, typename _InputIterator2>
  103. inline pair<_InputIterator1, _InputIterator2>
  104. mismatch(_InputIterator1 __first1, _InputIterator1 __last1,
  105. _InputIterator2 __first2, _InputIterator2 __last2,
  106. __gnu_parallel::sequential_tag)
  107. { return _GLIBCXX_STD_A::mismatch(__first1, __last1, __first2, __last2); }
  108. // Sequential fallback.
  109. template<typename _InputIterator1, typename _InputIterator2,
  110. typename _BinaryPredicate>
  111. inline pair<_InputIterator1, _InputIterator2>
  112. mismatch(_InputIterator1 __first1, _InputIterator1 __last1,
  113. _InputIterator2 __first2, _InputIterator2 __last2,
  114. _BinaryPredicate __binary_pred,
  115. __gnu_parallel::sequential_tag)
  116. {
  117. return _GLIBCXX_STD_A::mismatch(__first1, __last1, __first2, __last2,
  118. __binary_pred);
  119. }
  120. // Sequential fallback for input iterator case
  121. template<typename _IIter1, typename _IIter2,
  122. typename _Predicate, typename _IteratorTag1, typename _IteratorTag2>
  123. inline pair<_IIter1, _IIter2>
  124. __mismatch_switch(_IIter1 __begin1, _IIter1 __end1,
  125. _IIter2 __begin2, _IIter2 __end2, _Predicate __pred,
  126. _IteratorTag1, _IteratorTag2)
  127. {
  128. return _GLIBCXX_STD_A::mismatch(__begin1, __end1,
  129. __begin2, __end2, __pred);
  130. }
  131. // Parallel mismatch for random access iterators
  132. template<typename _RAIter1, typename _RAIter2, typename _Predicate>
  133. pair<_RAIter1, _RAIter2>
  134. __mismatch_switch(_RAIter1 __begin1, _RAIter1 __end1,
  135. _RAIter2 __begin2, _RAIter2 __end2, _Predicate __pred,
  136. random_access_iterator_tag, random_access_iterator_tag)
  137. {
  138. if (_GLIBCXX_PARALLEL_CONDITION(true))
  139. {
  140. if ((__end2 - __begin2) < (__end1 - __begin1))
  141. __end1 = __begin1 + (__end2 - __begin2);
  142. _RAIter1 __res =
  143. __gnu_parallel::__find_template(__begin1, __end1, __begin2, __pred,
  144. __gnu_parallel::
  145. __mismatch_selector()).first;
  146. return make_pair(__res , __begin2 + (__res - __begin1));
  147. }
  148. else
  149. return _GLIBCXX_STD_A::mismatch(__begin1, __end1,
  150. __begin2, __end2, __pred);
  151. }
  152. template<typename _IIter1, typename _IIter2>
  153. inline pair<_IIter1, _IIter2>
  154. mismatch(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2, _IIter2 __end2)
  155. {
  156. typedef __gnu_parallel::_EqualTo<
  157. typename std::iterator_traits<_IIter1>::value_type,
  158. typename std::iterator_traits<_IIter2>::value_type> _EqualTo;
  159. return __mismatch_switch(__begin1, __end1, __begin2, __end2, _EqualTo(),
  160. std::__iterator_category(__begin1),
  161. std::__iterator_category(__begin2));
  162. }
  163. template<typename _InputIterator1, typename _InputIterator2,
  164. typename _BinaryPredicate>
  165. inline pair<_InputIterator1, _InputIterator2>
  166. mismatch(_InputIterator1 __begin1, _InputIterator1 __end1,
  167. _InputIterator2 __begin2, _InputIterator2 __end2,
  168. _BinaryPredicate __binary_pred)
  169. {
  170. return __mismatch_switch(__begin1, __end1, __begin2, __end2,
  171. __binary_pred,
  172. std::__iterator_category(__begin1),
  173. std::__iterator_category(__begin2));
  174. }
  175. #endif
  176. // Sequential fallback
  177. template<typename _IIter1, typename _IIter2>
  178. inline bool
  179. equal(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2,
  180. __gnu_parallel::sequential_tag)
  181. { return _GLIBCXX_STD_A::equal(__begin1, __end1, __begin2); }
  182. // Sequential fallback
  183. template<typename _IIter1, typename _IIter2, typename _Predicate>
  184. inline bool
  185. equal(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2,
  186. _Predicate __pred, __gnu_parallel::sequential_tag)
  187. { return _GLIBCXX_STD_A::equal(__begin1, __end1, __begin2, __pred); }
  188. // Public interface
  189. template<typename _IIter1, typename _IIter2>
  190. inline bool
  191. equal(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2)
  192. {
  193. return __gnu_parallel::mismatch(__begin1, __end1, __begin2).first
  194. == __end1;
  195. }
  196. // Public interface
  197. template<typename _IIter1, typename _IIter2, typename _Predicate>
  198. inline bool
  199. equal(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2,
  200. _Predicate __pred)
  201. {
  202. return __gnu_parallel::mismatch(__begin1, __end1, __begin2, __pred).first
  203. == __end1;
  204. }
  205. #if __cplusplus > 201103L
  206. // Sequential fallback
  207. template<typename _IIter1, typename _IIter2>
  208. inline bool
  209. equal(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2, _IIter2 __end2,
  210. __gnu_parallel::sequential_tag)
  211. {
  212. return _GLIBCXX_STD_A::equal(__begin1, __end1, __begin2, __end2);
  213. }
  214. // Sequential fallback
  215. template<typename _IIter1, typename _IIter2, typename _BinaryPredicate>
  216. inline bool
  217. equal(_IIter1 __begin1, _IIter1 __end1,
  218. _IIter2 __begin2, _IIter2 __end2, _BinaryPredicate __binary_pred,
  219. __gnu_parallel::sequential_tag)
  220. {
  221. return _GLIBCXX_STD_A::equal(__begin1, __end1, __begin2, __end2,
  222. __binary_pred);
  223. }
  224. // Sequential fallback for input iterator case
  225. template<typename _IIter1, typename _IIter2,
  226. typename _Predicate, typename _IteratorTag1, typename _IteratorTag2>
  227. inline bool
  228. __equal_switch(_IIter1 __begin1, _IIter1 __end1,
  229. _IIter2 __begin2, _IIter2 __end2, _Predicate __pred,
  230. _IteratorTag1, _IteratorTag2)
  231. {
  232. return _GLIBCXX_STD_A::equal(__begin1, __end1,
  233. __begin2, __end2, __pred);
  234. }
  235. // Parallel equal for random access iterators
  236. template<typename _RAIter1, typename _RAIter2, typename _Predicate>
  237. inline bool
  238. __equal_switch(_RAIter1 __begin1, _RAIter1 __end1,
  239. _RAIter2 __begin2, _RAIter2 __end2, _Predicate __pred,
  240. random_access_iterator_tag, random_access_iterator_tag)
  241. {
  242. if (_GLIBCXX_PARALLEL_CONDITION(true))
  243. {
  244. if (std::distance(__begin1, __end1)
  245. != std::distance(__begin2, __end2))
  246. return false;
  247. return __gnu_parallel::mismatch(__begin1, __end1, __begin2, __end2,
  248. __pred).first == __end1;
  249. }
  250. else
  251. return _GLIBCXX_STD_A::equal(__begin1, __end1,
  252. __begin2, __end2, __pred);
  253. }
  254. template<typename _IIter1, typename _IIter2>
  255. inline bool
  256. equal(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2, _IIter2 __end2)
  257. {
  258. typedef __gnu_parallel::_EqualTo<
  259. typename std::iterator_traits<_IIter1>::value_type,
  260. typename std::iterator_traits<_IIter2>::value_type> _EqualTo;
  261. return __equal_switch(__begin1, __end1, __begin2, __end2, _EqualTo(),
  262. std::__iterator_category(__begin1),
  263. std::__iterator_category(__begin2));
  264. }
  265. template<typename _IIter1, typename _IIter2, typename _BinaryPredicate>
  266. inline bool
  267. equal(_IIter1 __begin1, _IIter1 __end1,
  268. _IIter2 __begin2, _IIter2 __end2, _BinaryPredicate __binary_pred)
  269. {
  270. return __equal_switch(__begin1, __end1, __begin2, __end2, __binary_pred,
  271. std::__iterator_category(__begin1),
  272. std::__iterator_category(__begin2));
  273. }
  274. #endif
  275. // Sequential fallback
  276. template<typename _IIter1, typename _IIter2>
  277. inline bool
  278. lexicographical_compare(_IIter1 __begin1, _IIter1 __end1,
  279. _IIter2 __begin2, _IIter2 __end2,
  280. __gnu_parallel::sequential_tag)
  281. { return _GLIBCXX_STD_A::lexicographical_compare(__begin1, __end1,
  282. __begin2, __end2); }
  283. // Sequential fallback
  284. template<typename _IIter1, typename _IIter2, typename _Predicate>
  285. inline bool
  286. lexicographical_compare(_IIter1 __begin1, _IIter1 __end1,
  287. _IIter2 __begin2, _IIter2 __end2,
  288. _Predicate __pred, __gnu_parallel::sequential_tag)
  289. { return _GLIBCXX_STD_A::lexicographical_compare(
  290. __begin1, __end1, __begin2, __end2, __pred); }
  291. // Sequential fallback for input iterator case
  292. template<typename _IIter1, typename _IIter2,
  293. typename _Predicate, typename _IteratorTag1, typename _IteratorTag2>
  294. inline bool
  295. __lexicographical_compare_switch(_IIter1 __begin1, _IIter1 __end1,
  296. _IIter2 __begin2, _IIter2 __end2,
  297. _Predicate __pred,
  298. _IteratorTag1, _IteratorTag2)
  299. { return _GLIBCXX_STD_A::lexicographical_compare(
  300. __begin1, __end1, __begin2, __end2, __pred); }
  301. // Parallel lexicographical_compare for random access iterators
  302. // Limitation: Both valuetypes must be the same
  303. template<typename _RAIter1, typename _RAIter2, typename _Predicate>
  304. bool
  305. __lexicographical_compare_switch(_RAIter1 __begin1, _RAIter1 __end1,
  306. _RAIter2 __begin2, _RAIter2 __end2,
  307. _Predicate __pred,
  308. random_access_iterator_tag,
  309. random_access_iterator_tag)
  310. {
  311. if (_GLIBCXX_PARALLEL_CONDITION(true))
  312. {
  313. typedef iterator_traits<_RAIter1> _TraitsType1;
  314. typedef typename _TraitsType1::value_type _ValueType1;
  315. typedef iterator_traits<_RAIter2> _TraitsType2;
  316. typedef typename _TraitsType2::value_type _ValueType2;
  317. typedef __gnu_parallel::
  318. _EqualFromLess<_ValueType1, _ValueType2, _Predicate>
  319. _EqualFromLessCompare;
  320. // Longer sequence in first place.
  321. if ((__end1 - __begin1) < (__end2 - __begin2))
  322. {
  323. typedef pair<_RAIter1, _RAIter2> _SpotType;
  324. _SpotType __mm = __mismatch_switch(__begin1, __end1, __begin2,
  325. _EqualFromLessCompare(__pred),
  326. random_access_iterator_tag(),
  327. random_access_iterator_tag());
  328. return (__mm.first == __end1)
  329. || bool(__pred(*__mm.first, *__mm.second));
  330. }
  331. else
  332. {
  333. typedef pair<_RAIter2, _RAIter1> _SpotType;
  334. _SpotType __mm = __mismatch_switch(__begin2, __end2, __begin1,
  335. _EqualFromLessCompare(__pred),
  336. random_access_iterator_tag(),
  337. random_access_iterator_tag());
  338. return (__mm.first != __end2)
  339. && bool(__pred(*__mm.second, *__mm.first));
  340. }
  341. }
  342. else
  343. return _GLIBCXX_STD_A::lexicographical_compare(
  344. __begin1, __end1, __begin2, __end2, __pred);
  345. }
  346. // Public interface
  347. template<typename _IIter1, typename _IIter2>
  348. inline bool
  349. lexicographical_compare(_IIter1 __begin1, _IIter1 __end1,
  350. _IIter2 __begin2, _IIter2 __end2)
  351. {
  352. typedef iterator_traits<_IIter1> _TraitsType1;
  353. typedef typename _TraitsType1::value_type _ValueType1;
  354. typedef typename _TraitsType1::iterator_category _IteratorCategory1;
  355. typedef iterator_traits<_IIter2> _TraitsType2;
  356. typedef typename _TraitsType2::value_type _ValueType2;
  357. typedef typename _TraitsType2::iterator_category _IteratorCategory2;
  358. typedef __gnu_parallel::_Less<_ValueType1, _ValueType2> _LessType;
  359. return __lexicographical_compare_switch(
  360. __begin1, __end1, __begin2, __end2, _LessType(),
  361. _IteratorCategory1(), _IteratorCategory2());
  362. }
  363. // Public interface
  364. template<typename _IIter1, typename _IIter2, typename _Predicate>
  365. inline bool
  366. lexicographical_compare(_IIter1 __begin1, _IIter1 __end1,
  367. _IIter2 __begin2, _IIter2 __end2,
  368. _Predicate __pred)
  369. {
  370. typedef iterator_traits<_IIter1> _TraitsType1;
  371. typedef typename _TraitsType1::iterator_category _IteratorCategory1;
  372. typedef iterator_traits<_IIter2> _TraitsType2;
  373. typedef typename _TraitsType2::iterator_category _IteratorCategory2;
  374. return __lexicographical_compare_switch(
  375. __begin1, __end1, __begin2, __end2, __pred,
  376. _IteratorCategory1(), _IteratorCategory2());
  377. }
  378. } // end namespace
  379. } // end namespace
  380. #endif /* _GLIBCXX_PARALLEL_ALGOBASE_H */