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.

512 lines
20KB

  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. /**
  21. * @file parallel/numeric
  22. *
  23. * @brief Parallel STL function calls corresponding to stl_numeric.h.
  24. * The functions defined here mainly do case switches and
  25. * call the actual parallelized versions in other files.
  26. * Inlining policy: Functions that basically only contain one function call,
  27. * are declared inline.
  28. * This file is a GNU parallel extension to the Standard C++ Library.
  29. */
  30. // Written by Johannes Singler and Felix Putze.
  31. #ifndef _GLIBCXX_PARALLEL_NUMERIC_H
  32. #define _GLIBCXX_PARALLEL_NUMERIC_H 1
  33. #include <numeric>
  34. #include <bits/stl_function.h>
  35. #include <parallel/numericfwd.h>
  36. #include <parallel/iterator.h>
  37. #include <parallel/for_each.h>
  38. #include <parallel/for_each_selectors.h>
  39. #include <parallel/partial_sum.h>
  40. namespace std _GLIBCXX_VISIBILITY(default)
  41. {
  42. namespace __parallel
  43. {
  44. // Sequential fallback.
  45. template<typename _IIter, typename _Tp>
  46. inline _Tp
  47. accumulate(_IIter __begin, _IIter __end, _Tp __init,
  48. __gnu_parallel::sequential_tag)
  49. { return _GLIBCXX_STD_A::accumulate(__begin, __end, __init); }
  50. template<typename _IIter, typename _Tp, typename _BinaryOperation>
  51. inline _Tp
  52. accumulate(_IIter __begin, _IIter __end, _Tp __init,
  53. _BinaryOperation __binary_op, __gnu_parallel::sequential_tag)
  54. { return _GLIBCXX_STD_A::accumulate(__begin, __end, __init, __binary_op); }
  55. // Sequential fallback for input iterator case.
  56. template<typename _IIter, typename _Tp, typename _IteratorTag>
  57. inline _Tp
  58. __accumulate_switch(_IIter __begin, _IIter __end,
  59. _Tp __init, _IteratorTag)
  60. { return accumulate(__begin, __end, __init,
  61. __gnu_parallel::sequential_tag()); }
  62. template<typename _IIter, typename _Tp, typename _BinaryOperation,
  63. typename _IteratorTag>
  64. inline _Tp
  65. __accumulate_switch(_IIter __begin, _IIter __end, _Tp __init,
  66. _BinaryOperation __binary_op, _IteratorTag)
  67. { return accumulate(__begin, __end, __init, __binary_op,
  68. __gnu_parallel::sequential_tag()); }
  69. // Parallel algorithm for random access iterators.
  70. template<typename __RAIter, typename _Tp, typename _BinaryOperation>
  71. _Tp
  72. __accumulate_switch(__RAIter __begin, __RAIter __end,
  73. _Tp __init, _BinaryOperation __binary_op,
  74. random_access_iterator_tag,
  75. __gnu_parallel::_Parallelism __parallelism_tag)
  76. {
  77. if (_GLIBCXX_PARALLEL_CONDITION(
  78. static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin)
  79. >= __gnu_parallel::_Settings::get().accumulate_minimal_n
  80. && __gnu_parallel::__is_parallel(__parallelism_tag)))
  81. {
  82. _Tp __res = __init;
  83. __gnu_parallel::__accumulate_selector<__RAIter>
  84. __my_selector;
  85. __gnu_parallel::
  86. __for_each_template_random_access_ed(__begin, __end,
  87. __gnu_parallel::_Nothing(),
  88. __my_selector,
  89. __gnu_parallel::
  90. __accumulate_binop_reduct
  91. <_BinaryOperation>(__binary_op),
  92. __res, __res, -1);
  93. return __res;
  94. }
  95. else
  96. return accumulate(__begin, __end, __init, __binary_op,
  97. __gnu_parallel::sequential_tag());
  98. }
  99. // Public interface.
  100. template<typename _IIter, typename _Tp>
  101. inline _Tp
  102. accumulate(_IIter __begin, _IIter __end, _Tp __init,
  103. __gnu_parallel::_Parallelism __parallelism_tag)
  104. {
  105. typedef std::iterator_traits<_IIter> _IteratorTraits;
  106. typedef typename _IteratorTraits::value_type _ValueType;
  107. typedef typename _IteratorTraits::iterator_category _IteratorCategory;
  108. return __accumulate_switch(__begin, __end, __init,
  109. __gnu_parallel::_Plus<_Tp, _ValueType>(),
  110. _IteratorCategory(), __parallelism_tag);
  111. }
  112. template<typename _IIter, typename _Tp>
  113. inline _Tp
  114. accumulate(_IIter __begin, _IIter __end, _Tp __init)
  115. {
  116. typedef std::iterator_traits<_IIter> _IteratorTraits;
  117. typedef typename _IteratorTraits::value_type _ValueType;
  118. typedef typename _IteratorTraits::iterator_category _IteratorCategory;
  119. return __accumulate_switch(__begin, __end, __init,
  120. __gnu_parallel::_Plus<_Tp, _ValueType>(),
  121. _IteratorCategory());
  122. }
  123. template<typename _IIter, typename _Tp, typename _BinaryOperation>
  124. inline _Tp
  125. accumulate(_IIter __begin, _IIter __end, _Tp __init,
  126. _BinaryOperation __binary_op,
  127. __gnu_parallel::_Parallelism __parallelism_tag)
  128. {
  129. typedef iterator_traits<_IIter> _IteratorTraits;
  130. typedef typename _IteratorTraits::iterator_category _IteratorCategory;
  131. return __accumulate_switch(__begin, __end, __init, __binary_op,
  132. _IteratorCategory(), __parallelism_tag);
  133. }
  134. template<typename _IIter, typename _Tp, typename _BinaryOperation>
  135. inline _Tp
  136. accumulate(_IIter __begin, _IIter __end, _Tp __init,
  137. _BinaryOperation __binary_op)
  138. {
  139. typedef iterator_traits<_IIter> _IteratorTraits;
  140. typedef typename _IteratorTraits::iterator_category _IteratorCategory;
  141. return __accumulate_switch(__begin, __end, __init, __binary_op,
  142. _IteratorCategory());
  143. }
  144. // Sequential fallback.
  145. template<typename _IIter1, typename _IIter2, typename _Tp>
  146. inline _Tp
  147. inner_product(_IIter1 __first1, _IIter1 __last1,
  148. _IIter2 __first2, _Tp __init,
  149. __gnu_parallel::sequential_tag)
  150. { return _GLIBCXX_STD_A::inner_product(
  151. __first1, __last1, __first2, __init); }
  152. template<typename _IIter1, typename _IIter2, typename _Tp,
  153. typename _BinaryFunction1, typename _BinaryFunction2>
  154. inline _Tp
  155. inner_product(_IIter1 __first1, _IIter1 __last1,
  156. _IIter2 __first2, _Tp __init, _BinaryFunction1 __binary_op1,
  157. _BinaryFunction2 __binary_op2,
  158. __gnu_parallel::sequential_tag)
  159. { return _GLIBCXX_STD_A::inner_product(__first1, __last1, __first2, __init,
  160. __binary_op1, __binary_op2); }
  161. // Parallel algorithm for random access iterators.
  162. template<typename _RAIter1, typename _RAIter2,
  163. typename _Tp, typename _BinaryFunction1, typename _BinaryFunction2>
  164. _Tp
  165. __inner_product_switch(_RAIter1 __first1,
  166. _RAIter1 __last1,
  167. _RAIter2 __first2, _Tp __init,
  168. _BinaryFunction1 __binary_op1,
  169. _BinaryFunction2 __binary_op2,
  170. random_access_iterator_tag,
  171. random_access_iterator_tag,
  172. __gnu_parallel::_Parallelism __parallelism_tag)
  173. {
  174. if (_GLIBCXX_PARALLEL_CONDITION((__last1 - __first1)
  175. >= __gnu_parallel::_Settings::get().
  176. accumulate_minimal_n
  177. && __gnu_parallel::
  178. __is_parallel(__parallelism_tag)))
  179. {
  180. _Tp __res = __init;
  181. __gnu_parallel::
  182. __inner_product_selector<_RAIter1,
  183. _RAIter2, _Tp> __my_selector(__first1, __first2);
  184. __gnu_parallel::
  185. __for_each_template_random_access_ed(
  186. __first1, __last1, __binary_op2, __my_selector, __binary_op1,
  187. __res, __res, -1);
  188. return __res;
  189. }
  190. else
  191. return inner_product(__first1, __last1, __first2, __init,
  192. __gnu_parallel::sequential_tag());
  193. }
  194. // No parallelism for input iterators.
  195. template<typename _IIter1, typename _IIter2, typename _Tp,
  196. typename _BinaryFunction1, typename _BinaryFunction2,
  197. typename _IteratorTag1, typename _IteratorTag2>
  198. inline _Tp
  199. __inner_product_switch(_IIter1 __first1, _IIter1 __last1,
  200. _IIter2 __first2, _Tp __init,
  201. _BinaryFunction1 __binary_op1,
  202. _BinaryFunction2 __binary_op2,
  203. _IteratorTag1, _IteratorTag2)
  204. { return inner_product(__first1, __last1, __first2, __init, __binary_op1,
  205. __binary_op2, __gnu_parallel::sequential_tag()); }
  206. template<typename _IIter1, typename _IIter2, typename _Tp,
  207. typename _BinaryFunction1, typename _BinaryFunction2>
  208. inline _Tp
  209. inner_product(_IIter1 __first1, _IIter1 __last1,
  210. _IIter2 __first2, _Tp __init, _BinaryFunction1 __binary_op1,
  211. _BinaryFunction2 __binary_op2,
  212. __gnu_parallel::_Parallelism __parallelism_tag)
  213. {
  214. typedef iterator_traits<_IIter1> _TraitsType1;
  215. typedef typename _TraitsType1::iterator_category _IteratorCategory1;
  216. typedef iterator_traits<_IIter2> _TraitsType2;
  217. typedef typename _TraitsType2::iterator_category _IteratorCategory2;
  218. return __inner_product_switch(__first1, __last1, __first2, __init,
  219. __binary_op1, __binary_op2,
  220. _IteratorCategory1(), _IteratorCategory2(),
  221. __parallelism_tag);
  222. }
  223. template<typename _IIter1, typename _IIter2, typename _Tp,
  224. typename _BinaryFunction1, typename _BinaryFunction2>
  225. inline _Tp
  226. inner_product(_IIter1 __first1, _IIter1 __last1,
  227. _IIter2 __first2, _Tp __init, _BinaryFunction1 __binary_op1,
  228. _BinaryFunction2 __binary_op2)
  229. {
  230. typedef iterator_traits<_IIter1> _TraitsType1;
  231. typedef typename _TraitsType1::iterator_category _IteratorCategory1;
  232. typedef iterator_traits<_IIter2> _TraitsType2;
  233. typedef typename _TraitsType2::iterator_category _IteratorCategory2;
  234. return __inner_product_switch(__first1, __last1, __first2, __init,
  235. __binary_op1, __binary_op2,
  236. _IteratorCategory1(),
  237. _IteratorCategory2());
  238. }
  239. template<typename _IIter1, typename _IIter2, typename _Tp>
  240. inline _Tp
  241. inner_product(_IIter1 __first1, _IIter1 __last1,
  242. _IIter2 __first2, _Tp __init,
  243. __gnu_parallel::_Parallelism __parallelism_tag)
  244. {
  245. typedef iterator_traits<_IIter1> _TraitsType1;
  246. typedef typename _TraitsType1::value_type _ValueType1;
  247. typedef iterator_traits<_IIter2> _TraitsType2;
  248. typedef typename _TraitsType2::value_type _ValueType2;
  249. typedef typename
  250. __gnu_parallel::_Multiplies<_ValueType1, _ValueType2>::result_type
  251. _MultipliesResultType;
  252. return __gnu_parallel::inner_product(__first1, __last1, __first2, __init,
  253. __gnu_parallel::_Plus<_Tp, _MultipliesResultType>(),
  254. __gnu_parallel::
  255. _Multiplies<_ValueType1, _ValueType2>(),
  256. __parallelism_tag);
  257. }
  258. template<typename _IIter1, typename _IIter2, typename _Tp>
  259. inline _Tp
  260. inner_product(_IIter1 __first1, _IIter1 __last1,
  261. _IIter2 __first2, _Tp __init)
  262. {
  263. typedef iterator_traits<_IIter1> _TraitsType1;
  264. typedef typename _TraitsType1::value_type _ValueType1;
  265. typedef iterator_traits<_IIter2> _TraitsType2;
  266. typedef typename _TraitsType2::value_type _ValueType2;
  267. typedef typename
  268. __gnu_parallel::_Multiplies<_ValueType1, _ValueType2>::result_type
  269. _MultipliesResultType;
  270. return __gnu_parallel::inner_product(__first1, __last1, __first2, __init,
  271. __gnu_parallel::_Plus<_Tp, _MultipliesResultType>(),
  272. __gnu_parallel::
  273. _Multiplies<_ValueType1, _ValueType2>());
  274. }
  275. // Sequential fallback.
  276. template<typename _IIter, typename _OutputIterator>
  277. inline _OutputIterator
  278. partial_sum(_IIter __begin, _IIter __end, _OutputIterator __result,
  279. __gnu_parallel::sequential_tag)
  280. { return _GLIBCXX_STD_A::partial_sum(__begin, __end, __result); }
  281. // Sequential fallback.
  282. template<typename _IIter, typename _OutputIterator,
  283. typename _BinaryOperation>
  284. inline _OutputIterator
  285. partial_sum(_IIter __begin, _IIter __end, _OutputIterator __result,
  286. _BinaryOperation __bin_op, __gnu_parallel::sequential_tag)
  287. { return _GLIBCXX_STD_A::partial_sum(__begin, __end, __result, __bin_op); }
  288. // Sequential fallback for input iterator case.
  289. template<typename _IIter, typename _OutputIterator,
  290. typename _BinaryOperation, typename _IteratorTag1,
  291. typename _IteratorTag2>
  292. inline _OutputIterator
  293. __partial_sum_switch(_IIter __begin, _IIter __end,
  294. _OutputIterator __result, _BinaryOperation __bin_op,
  295. _IteratorTag1, _IteratorTag2)
  296. { return _GLIBCXX_STD_A::partial_sum(__begin, __end, __result, __bin_op); }
  297. // Parallel algorithm for random access iterators.
  298. template<typename _IIter, typename _OutputIterator,
  299. typename _BinaryOperation>
  300. _OutputIterator
  301. __partial_sum_switch(_IIter __begin, _IIter __end,
  302. _OutputIterator __result, _BinaryOperation __bin_op,
  303. random_access_iterator_tag,
  304. random_access_iterator_tag)
  305. {
  306. if (_GLIBCXX_PARALLEL_CONDITION(
  307. static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin)
  308. >= __gnu_parallel::_Settings::get().partial_sum_minimal_n))
  309. return __gnu_parallel::__parallel_partial_sum(__begin, __end,
  310. __result, __bin_op);
  311. else
  312. return partial_sum(__begin, __end, __result, __bin_op,
  313. __gnu_parallel::sequential_tag());
  314. }
  315. // Public interface.
  316. template<typename _IIter, typename _OutputIterator>
  317. inline _OutputIterator
  318. partial_sum(_IIter __begin, _IIter __end, _OutputIterator __result)
  319. {
  320. typedef typename iterator_traits<_IIter>::value_type _ValueType;
  321. return __gnu_parallel::partial_sum(__begin, __end,
  322. __result, std::plus<_ValueType>());
  323. }
  324. // Public interface
  325. template<typename _IIter, typename _OutputIterator,
  326. typename _BinaryOperation>
  327. inline _OutputIterator
  328. partial_sum(_IIter __begin, _IIter __end, _OutputIterator __result,
  329. _BinaryOperation __binary_op)
  330. {
  331. typedef iterator_traits<_IIter> _ITraitsType;
  332. typedef typename _ITraitsType::iterator_category _IIteratorCategory;
  333. typedef iterator_traits<_OutputIterator> _OTraitsType;
  334. typedef typename _OTraitsType::iterator_category _OIterCategory;
  335. return __partial_sum_switch(__begin, __end, __result, __binary_op,
  336. _IIteratorCategory(), _OIterCategory());
  337. }
  338. // Sequential fallback.
  339. template<typename _IIter, typename _OutputIterator>
  340. inline _OutputIterator
  341. adjacent_difference(_IIter __begin, _IIter __end, _OutputIterator __result,
  342. __gnu_parallel::sequential_tag)
  343. { return _GLIBCXX_STD_A::adjacent_difference(__begin, __end, __result); }
  344. // Sequential fallback.
  345. template<typename _IIter, typename _OutputIterator,
  346. typename _BinaryOperation>
  347. inline _OutputIterator
  348. adjacent_difference(_IIter __begin, _IIter __end,
  349. _OutputIterator __result, _BinaryOperation __bin_op,
  350. __gnu_parallel::sequential_tag)
  351. { return _GLIBCXX_STD_A::adjacent_difference(__begin, __end,
  352. __result, __bin_op); }
  353. // Sequential fallback for input iterator case.
  354. template<typename _IIter, typename _OutputIterator,
  355. typename _BinaryOperation, typename _IteratorTag1,
  356. typename _IteratorTag2>
  357. inline _OutputIterator
  358. __adjacent_difference_switch(_IIter __begin, _IIter __end,
  359. _OutputIterator __result,
  360. _BinaryOperation __bin_op, _IteratorTag1,
  361. _IteratorTag2)
  362. { return adjacent_difference(__begin, __end, __result, __bin_op,
  363. __gnu_parallel::sequential_tag()); }
  364. // Parallel algorithm for random access iterators.
  365. template<typename _IIter, typename _OutputIterator,
  366. typename _BinaryOperation>
  367. _OutputIterator
  368. __adjacent_difference_switch(_IIter __begin, _IIter __end,
  369. _OutputIterator __result,
  370. _BinaryOperation __bin_op,
  371. random_access_iterator_tag,
  372. random_access_iterator_tag,
  373. __gnu_parallel::_Parallelism
  374. __parallelism_tag)
  375. {
  376. if (_GLIBCXX_PARALLEL_CONDITION(
  377. static_cast<__gnu_parallel::_SequenceIndex>(__end - __begin)
  378. >= __gnu_parallel::_Settings::get().adjacent_difference_minimal_n
  379. && __gnu_parallel::__is_parallel(__parallelism_tag)))
  380. {
  381. bool __dummy = true;
  382. typedef __gnu_parallel::_IteratorPair<_IIter, _OutputIterator,
  383. random_access_iterator_tag> _ItTrip;
  384. *__result = *__begin;
  385. _ItTrip __begin_pair(__begin + 1, __result + 1),
  386. __end_pair(__end, __result + (__end - __begin));
  387. __gnu_parallel::__adjacent_difference_selector<_ItTrip>
  388. __functionality;
  389. __gnu_parallel::
  390. __for_each_template_random_access_ed(
  391. __begin_pair, __end_pair, __bin_op, __functionality,
  392. __gnu_parallel::_DummyReduct(), __dummy, __dummy, -1);
  393. return __functionality._M_finish_iterator;
  394. }
  395. else
  396. return adjacent_difference(__begin, __end, __result, __bin_op,
  397. __gnu_parallel::sequential_tag());
  398. }
  399. // Public interface.
  400. template<typename _IIter, typename _OutputIterator>
  401. inline _OutputIterator
  402. adjacent_difference(_IIter __begin, _IIter __end,
  403. _OutputIterator __result,
  404. __gnu_parallel::_Parallelism __parallelism_tag)
  405. {
  406. typedef iterator_traits<_IIter> _TraitsType;
  407. typedef typename _TraitsType::value_type _ValueType;
  408. return adjacent_difference(__begin, __end, __result,
  409. std::minus<_ValueType>(),
  410. __parallelism_tag);
  411. }
  412. template<typename _IIter, typename _OutputIterator>
  413. inline _OutputIterator
  414. adjacent_difference(_IIter __begin, _IIter __end,
  415. _OutputIterator __result)
  416. {
  417. typedef iterator_traits<_IIter> _TraitsType;
  418. typedef typename _TraitsType::value_type _ValueType;
  419. return adjacent_difference(__begin, __end, __result,
  420. std::minus<_ValueType>());
  421. }
  422. template<typename _IIter, typename _OutputIterator,
  423. typename _BinaryOperation>
  424. inline _OutputIterator
  425. adjacent_difference(_IIter __begin, _IIter __end,
  426. _OutputIterator __result, _BinaryOperation __binary_op,
  427. __gnu_parallel::_Parallelism __parallelism_tag)
  428. {
  429. typedef iterator_traits<_IIter> _ITraitsType;
  430. typedef typename _ITraitsType::iterator_category _IIteratorCategory;
  431. typedef iterator_traits<_OutputIterator> _OTraitsType;
  432. typedef typename _OTraitsType::iterator_category _OIterCategory;
  433. return __adjacent_difference_switch(__begin, __end, __result,
  434. __binary_op,
  435. _IIteratorCategory(),
  436. _OIterCategory(),
  437. __parallelism_tag);
  438. }
  439. template<typename _IIter, typename _OutputIterator,
  440. typename _BinaryOperation>
  441. inline _OutputIterator
  442. adjacent_difference(_IIter __begin, _IIter __end,
  443. _OutputIterator __result, _BinaryOperation __binary_op)
  444. {
  445. typedef iterator_traits<_IIter> _ITraitsType;
  446. typedef typename _ITraitsType::iterator_category _IIteratorCategory;
  447. typedef iterator_traits<_OutputIterator> _OTraitsType;
  448. typedef typename _OTraitsType::iterator_category _OIterCategory;
  449. return __adjacent_difference_switch(__begin, __end, __result,
  450. __binary_op,
  451. _IIteratorCategory(),
  452. _OIterCategory());
  453. }
  454. } // end namespace
  455. } // end namespace
  456. #endif /* _GLIBCXX_NUMERIC_H */