You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

473 lines
18KB

  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/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. _GLIBCXX20_CONSTEXPR
  191. inline bool
  192. equal(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2)
  193. {
  194. #if __cplusplus > 201703L
  195. if (std::is_constant_evaluated())
  196. return _GLIBCXX_STD_A::equal(__begin1, __end1, __begin2);
  197. #endif
  198. return __gnu_parallel::mismatch(__begin1, __end1, __begin2).first
  199. == __end1;
  200. }
  201. // Public interface
  202. template<typename _IIter1, typename _IIter2, typename _Predicate>
  203. _GLIBCXX20_CONSTEXPR
  204. inline bool
  205. equal(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2,
  206. _Predicate __pred)
  207. {
  208. #if __cplusplus > 201703L
  209. if (std::is_constant_evaluated())
  210. return _GLIBCXX_STD_A::equal(__begin1, __end1, __begin2, __pred);
  211. #endif
  212. return __gnu_parallel::mismatch(__begin1, __end1, __begin2, __pred).first
  213. == __end1;
  214. }
  215. #if __cplusplus > 201103L
  216. // Sequential fallback
  217. template<typename _IIter1, typename _IIter2>
  218. inline bool
  219. equal(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2, _IIter2 __end2,
  220. __gnu_parallel::sequential_tag)
  221. {
  222. return _GLIBCXX_STD_A::equal(__begin1, __end1, __begin2, __end2);
  223. }
  224. // Sequential fallback
  225. template<typename _IIter1, typename _IIter2, typename _BinaryPredicate>
  226. inline bool
  227. equal(_IIter1 __begin1, _IIter1 __end1,
  228. _IIter2 __begin2, _IIter2 __end2, _BinaryPredicate __binary_pred,
  229. __gnu_parallel::sequential_tag)
  230. {
  231. return _GLIBCXX_STD_A::equal(__begin1, __end1, __begin2, __end2,
  232. __binary_pred);
  233. }
  234. // Sequential fallback for input iterator case
  235. template<typename _IIter1, typename _IIter2,
  236. typename _Predicate, typename _IteratorTag1, typename _IteratorTag2>
  237. inline bool
  238. __equal_switch(_IIter1 __begin1, _IIter1 __end1,
  239. _IIter2 __begin2, _IIter2 __end2, _Predicate __pred,
  240. _IteratorTag1, _IteratorTag2)
  241. {
  242. return _GLIBCXX_STD_A::equal(__begin1, __end1,
  243. __begin2, __end2, __pred);
  244. }
  245. // Parallel equal for random access iterators
  246. template<typename _RAIter1, typename _RAIter2, typename _Predicate>
  247. inline bool
  248. __equal_switch(_RAIter1 __begin1, _RAIter1 __end1,
  249. _RAIter2 __begin2, _RAIter2 __end2, _Predicate __pred,
  250. random_access_iterator_tag, random_access_iterator_tag)
  251. {
  252. if (_GLIBCXX_PARALLEL_CONDITION(true))
  253. {
  254. if (std::distance(__begin1, __end1)
  255. != std::distance(__begin2, __end2))
  256. return false;
  257. return __gnu_parallel::mismatch(__begin1, __end1, __begin2, __end2,
  258. __pred).first == __end1;
  259. }
  260. else
  261. return _GLIBCXX_STD_A::equal(__begin1, __end1,
  262. __begin2, __end2, __pred);
  263. }
  264. template<typename _IIter1, typename _IIter2>
  265. _GLIBCXX20_CONSTEXPR
  266. inline bool
  267. equal(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2, _IIter2 __end2)
  268. {
  269. #if __cplusplus > 201703L
  270. if (std::is_constant_evaluated())
  271. return _GLIBCXX_STD_A::equal(__begin1, __end1, __begin2, __end2);
  272. #endif
  273. typedef __gnu_parallel::_EqualTo<
  274. typename std::iterator_traits<_IIter1>::value_type,
  275. typename std::iterator_traits<_IIter2>::value_type> _EqualTo;
  276. return __equal_switch(__begin1, __end1, __begin2, __end2, _EqualTo(),
  277. std::__iterator_category(__begin1),
  278. std::__iterator_category(__begin2));
  279. }
  280. template<typename _IIter1, typename _IIter2, typename _BinaryPredicate>
  281. _GLIBCXX20_CONSTEXPR
  282. inline bool
  283. equal(_IIter1 __begin1, _IIter1 __end1,
  284. _IIter2 __begin2, _IIter2 __end2, _BinaryPredicate __binary_pred)
  285. {
  286. #if __cplusplus > 201703L
  287. if (std::is_constant_evaluated())
  288. return _GLIBCXX_STD_A::equal(__begin1, __end1, __begin2, __end2,
  289. __binary_pred);
  290. #endif
  291. return __equal_switch(__begin1, __end1, __begin2, __end2, __binary_pred,
  292. std::__iterator_category(__begin1),
  293. std::__iterator_category(__begin2));
  294. }
  295. #endif // C++14
  296. // Sequential fallback
  297. template<typename _IIter1, typename _IIter2>
  298. inline bool
  299. lexicographical_compare(_IIter1 __begin1, _IIter1 __end1,
  300. _IIter2 __begin2, _IIter2 __end2,
  301. __gnu_parallel::sequential_tag)
  302. { return _GLIBCXX_STD_A::lexicographical_compare(__begin1, __end1,
  303. __begin2, __end2); }
  304. // Sequential fallback
  305. template<typename _IIter1, typename _IIter2, typename _Predicate>
  306. inline bool
  307. lexicographical_compare(_IIter1 __begin1, _IIter1 __end1,
  308. _IIter2 __begin2, _IIter2 __end2,
  309. _Predicate __pred, __gnu_parallel::sequential_tag)
  310. { return _GLIBCXX_STD_A::lexicographical_compare(
  311. __begin1, __end1, __begin2, __end2, __pred); }
  312. // Sequential fallback for input iterator case
  313. template<typename _IIter1, typename _IIter2,
  314. typename _Predicate, typename _IteratorTag1, typename _IteratorTag2>
  315. inline bool
  316. __lexicographical_compare_switch(_IIter1 __begin1, _IIter1 __end1,
  317. _IIter2 __begin2, _IIter2 __end2,
  318. _Predicate __pred,
  319. _IteratorTag1, _IteratorTag2)
  320. { return _GLIBCXX_STD_A::lexicographical_compare(
  321. __begin1, __end1, __begin2, __end2, __pred); }
  322. // Parallel lexicographical_compare for random access iterators
  323. // Limitation: Both valuetypes must be the same
  324. template<typename _RAIter1, typename _RAIter2, typename _Predicate>
  325. bool
  326. __lexicographical_compare_switch(_RAIter1 __begin1, _RAIter1 __end1,
  327. _RAIter2 __begin2, _RAIter2 __end2,
  328. _Predicate __pred,
  329. random_access_iterator_tag,
  330. random_access_iterator_tag)
  331. {
  332. if (_GLIBCXX_PARALLEL_CONDITION(true))
  333. {
  334. typedef iterator_traits<_RAIter1> _TraitsType1;
  335. typedef typename _TraitsType1::value_type _ValueType1;
  336. typedef iterator_traits<_RAIter2> _TraitsType2;
  337. typedef typename _TraitsType2::value_type _ValueType2;
  338. typedef __gnu_parallel::
  339. _EqualFromLess<_ValueType1, _ValueType2, _Predicate>
  340. _EqualFromLessCompare;
  341. // Longer sequence in first place.
  342. if ((__end1 - __begin1) < (__end2 - __begin2))
  343. {
  344. typedef pair<_RAIter1, _RAIter2> _SpotType;
  345. _SpotType __mm = __mismatch_switch(__begin1, __end1, __begin2,
  346. _EqualFromLessCompare(__pred),
  347. random_access_iterator_tag(),
  348. random_access_iterator_tag());
  349. return (__mm.first == __end1)
  350. || bool(__pred(*__mm.first, *__mm.second));
  351. }
  352. else
  353. {
  354. typedef pair<_RAIter2, _RAIter1> _SpotType;
  355. _SpotType __mm = __mismatch_switch(__begin2, __end2, __begin1,
  356. _EqualFromLessCompare(__pred),
  357. random_access_iterator_tag(),
  358. random_access_iterator_tag());
  359. return (__mm.first != __end2)
  360. && bool(__pred(*__mm.second, *__mm.first));
  361. }
  362. }
  363. else
  364. return _GLIBCXX_STD_A::lexicographical_compare(
  365. __begin1, __end1, __begin2, __end2, __pred);
  366. }
  367. // Public interface
  368. template<typename _IIter1, typename _IIter2>
  369. _GLIBCXX20_CONSTEXPR
  370. inline bool
  371. lexicographical_compare(_IIter1 __begin1, _IIter1 __end1,
  372. _IIter2 __begin2, _IIter2 __end2)
  373. {
  374. #if __cplusplus > 201703L
  375. if (std::is_constant_evaluated())
  376. return _GLIBCXX_STD_A::lexicographical_compare(__begin1, __end1,
  377. __begin2, __end2);
  378. #endif
  379. typedef iterator_traits<_IIter1> _TraitsType1;
  380. typedef typename _TraitsType1::value_type _ValueType1;
  381. typedef typename _TraitsType1::iterator_category _IteratorCategory1;
  382. typedef iterator_traits<_IIter2> _TraitsType2;
  383. typedef typename _TraitsType2::value_type _ValueType2;
  384. typedef typename _TraitsType2::iterator_category _IteratorCategory2;
  385. typedef __gnu_parallel::_Less<_ValueType1, _ValueType2> _LessType;
  386. return __lexicographical_compare_switch(
  387. __begin1, __end1, __begin2, __end2, _LessType(),
  388. _IteratorCategory1(), _IteratorCategory2());
  389. }
  390. // Public interface
  391. template<typename _IIter1, typename _IIter2, typename _Predicate>
  392. _GLIBCXX20_CONSTEXPR
  393. inline bool
  394. lexicographical_compare(_IIter1 __begin1, _IIter1 __end1,
  395. _IIter2 __begin2, _IIter2 __end2,
  396. _Predicate __pred)
  397. {
  398. #if __cplusplus > 201703L
  399. if (std::is_constant_evaluated())
  400. return _GLIBCXX_STD_A::lexicographical_compare(__begin1, __end1,
  401. __begin2, __end2,
  402. __pred);
  403. #endif
  404. typedef iterator_traits<_IIter1> _TraitsType1;
  405. typedef typename _TraitsType1::iterator_category _IteratorCategory1;
  406. typedef iterator_traits<_IIter2> _TraitsType2;
  407. typedef typename _TraitsType2::iterator_category _IteratorCategory2;
  408. return __lexicographical_compare_switch(
  409. __begin1, __end1, __begin2, __end2, __pred,
  410. _IteratorCategory1(), _IteratorCategory2());
  411. }
  412. } // end namespace
  413. } // end namespace
  414. #endif /* _GLIBCXX_PARALLEL_ALGOBASE_H */