numeric 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. // -*- C++ -*-
  2. // Copyright (C) 2007, 2008, 2009 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 <functional>
  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
  41. {
  42. namespace __parallel
  43. {
  44. // Sequential fallback.
  45. template<typename InputIterator, typename T>
  46. inline T
  47. accumulate(InputIterator begin, InputIterator end, T init,
  48. __gnu_parallel::sequential_tag)
  49. { return _GLIBCXX_STD_P::accumulate(begin, end, init); }
  50. template<typename InputIterator, typename T, typename BinaryOperation>
  51. inline T
  52. accumulate(InputIterator begin, InputIterator end, T init,
  53. BinaryOperation binary_op, __gnu_parallel::sequential_tag)
  54. { return _GLIBCXX_STD_P::accumulate(begin, end, init, binary_op); }
  55. // Sequential fallback for input iterator case.
  56. template<typename InputIterator, typename T, typename IteratorTag>
  57. inline T
  58. accumulate_switch(InputIterator begin, InputIterator end,
  59. T init, IteratorTag)
  60. { return accumulate(begin, end, init, __gnu_parallel::sequential_tag()); }
  61. template<typename InputIterator, typename T, typename BinaryOperation,
  62. typename IteratorTag>
  63. inline T
  64. accumulate_switch(InputIterator begin, InputIterator end, T init,
  65. BinaryOperation binary_op, IteratorTag)
  66. { return accumulate(begin, end, init, binary_op,
  67. __gnu_parallel::sequential_tag()); }
  68. // Parallel algorithm for random access iterators.
  69. template<typename _RandomAccessIterator, typename T,
  70. typename BinaryOperation>
  71. T
  72. accumulate_switch(_RandomAccessIterator begin, _RandomAccessIterator end,
  73. T init, BinaryOperation binary_op,
  74. random_access_iterator_tag,
  75. __gnu_parallel::_Parallelism parallelism_tag
  76. = __gnu_parallel::parallel_unbalanced)
  77. {
  78. if (_GLIBCXX_PARALLEL_CONDITION(
  79. static_cast<__gnu_parallel::sequence_index_t>(end - begin)
  80. >= __gnu_parallel::_Settings::get().accumulate_minimal_n
  81. && __gnu_parallel::is_parallel(parallelism_tag)))
  82. {
  83. T res = init;
  84. __gnu_parallel::accumulate_selector<_RandomAccessIterator>
  85. my_selector;
  86. __gnu_parallel::
  87. for_each_template_random_access_ed(begin, end,
  88. __gnu_parallel::nothing(),
  89. my_selector,
  90. __gnu_parallel::
  91. accumulate_binop_reduct
  92. <BinaryOperation>(binary_op),
  93. res, res, -1);
  94. return res;
  95. }
  96. else
  97. return accumulate(begin, end, init, binary_op,
  98. __gnu_parallel::sequential_tag());
  99. }
  100. // Public interface.
  101. template<typename InputIterator, typename T>
  102. inline T
  103. accumulate(InputIterator begin, InputIterator end, T init,
  104. __gnu_parallel::_Parallelism parallelism_tag)
  105. {
  106. typedef std::iterator_traits<InputIterator> iterator_traits;
  107. typedef typename iterator_traits::value_type value_type;
  108. typedef typename iterator_traits::iterator_category iterator_category;
  109. return accumulate_switch(begin, end, init,
  110. __gnu_parallel::plus<T, value_type>(),
  111. iterator_category(), parallelism_tag);
  112. }
  113. template<typename InputIterator, typename T>
  114. inline T
  115. accumulate(InputIterator begin, InputIterator end, T init)
  116. {
  117. typedef std::iterator_traits<InputIterator> iterator_traits;
  118. typedef typename iterator_traits::value_type value_type;
  119. typedef typename iterator_traits::iterator_category iterator_category;
  120. return accumulate_switch(begin, end, init,
  121. __gnu_parallel::plus<T, value_type>(),
  122. iterator_category());
  123. }
  124. template<typename InputIterator, typename T, typename BinaryOperation>
  125. inline T
  126. accumulate(InputIterator begin, InputIterator end, T init,
  127. BinaryOperation binary_op,
  128. __gnu_parallel::_Parallelism parallelism_tag)
  129. {
  130. typedef iterator_traits<InputIterator> iterator_traits;
  131. typedef typename iterator_traits::iterator_category iterator_category;
  132. return accumulate_switch(begin, end, init, binary_op,
  133. iterator_category(), parallelism_tag);
  134. }
  135. template<typename InputIterator, typename T, typename BinaryOperation>
  136. inline T
  137. accumulate(InputIterator begin, InputIterator end, T init,
  138. BinaryOperation binary_op)
  139. {
  140. typedef iterator_traits<InputIterator> iterator_traits;
  141. typedef typename iterator_traits::iterator_category iterator_category;
  142. return accumulate_switch(begin, end, init, binary_op,
  143. iterator_category());
  144. }
  145. // Sequential fallback.
  146. template<typename InputIterator1, typename InputIterator2, typename T>
  147. inline T
  148. inner_product(InputIterator1 first1, InputIterator1 last1,
  149. InputIterator2 first2, T init,
  150. __gnu_parallel::sequential_tag)
  151. { return _GLIBCXX_STD_P::inner_product(first1, last1, first2, init); }
  152. template<typename InputIterator1, typename InputIterator2, typename T,
  153. typename BinaryFunction1, typename BinaryFunction2>
  154. inline T
  155. inner_product(InputIterator1 first1, InputIterator1 last1,
  156. InputIterator2 first2, T init, BinaryFunction1 binary_op1,
  157. BinaryFunction2 binary_op2, __gnu_parallel::sequential_tag)
  158. { return _GLIBCXX_STD_P::inner_product(first1, last1, first2, init,
  159. binary_op1, binary_op2); }
  160. // Parallel algorithm for random access iterators.
  161. template<typename RandomAccessIterator1, typename RandomAccessIterator2,
  162. typename T, typename BinaryFunction1, typename BinaryFunction2>
  163. T
  164. inner_product_switch(RandomAccessIterator1 first1,
  165. RandomAccessIterator1 last1,
  166. RandomAccessIterator2 first2, T init,
  167. BinaryFunction1 binary_op1,
  168. BinaryFunction2 binary_op2,
  169. random_access_iterator_tag,
  170. random_access_iterator_tag,
  171. __gnu_parallel::_Parallelism parallelism_tag
  172. = __gnu_parallel::parallel_unbalanced)
  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. T res = init;
  181. __gnu_parallel::
  182. inner_product_selector<RandomAccessIterator1,
  183. RandomAccessIterator2, T> my_selector(first1, first2);
  184. __gnu_parallel::
  185. for_each_template_random_access_ed(first1, last1, binary_op2,
  186. 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 InputIterator1, typename InputIterator2, typename T,
  196. typename BinaryFunction1, typename BinaryFunction2,
  197. typename IteratorTag1, typename IteratorTag2>
  198. inline T
  199. inner_product_switch(InputIterator1 first1, InputIterator1 last1,
  200. InputIterator2 first2, T init,
  201. BinaryFunction1 binary_op1,
  202. BinaryFunction2 binary_op2,
  203. IteratorTag1, IteratorTag2)
  204. { return inner_product(first1, last1, first2, init,
  205. binary_op1, binary_op2,
  206. __gnu_parallel::sequential_tag()); }
  207. template<typename InputIterator1, typename InputIterator2, typename T,
  208. typename BinaryFunction1, typename BinaryFunction2>
  209. inline T
  210. inner_product(InputIterator1 first1, InputIterator1 last1,
  211. InputIterator2 first2, T init, BinaryFunction1 binary_op1,
  212. BinaryFunction2 binary_op2,
  213. __gnu_parallel::_Parallelism parallelism_tag)
  214. {
  215. typedef iterator_traits<InputIterator1> traits1_type;
  216. typedef typename traits1_type::iterator_category iterator1_category;
  217. typedef iterator_traits<InputIterator2> traits2_type;
  218. typedef typename traits2_type::iterator_category iterator2_category;
  219. return inner_product_switch(first1, last1, first2, init, binary_op1,
  220. binary_op2, iterator1_category(),
  221. iterator2_category(), parallelism_tag);
  222. }
  223. template<typename InputIterator1, typename InputIterator2, typename T,
  224. typename BinaryFunction1, typename BinaryFunction2>
  225. inline T
  226. inner_product(InputIterator1 first1, InputIterator1 last1,
  227. InputIterator2 first2, T init, BinaryFunction1 binary_op1,
  228. BinaryFunction2 binary_op2)
  229. {
  230. typedef iterator_traits<InputIterator1> traits1_type;
  231. typedef typename traits1_type::iterator_category iterator1_category;
  232. typedef iterator_traits<InputIterator2> traits2_type;
  233. typedef typename traits2_type::iterator_category iterator2_category;
  234. return inner_product_switch(first1, last1, first2, init, binary_op1,
  235. binary_op2, iterator1_category(),
  236. iterator2_category());
  237. }
  238. template<typename InputIterator1, typename InputIterator2, typename T>
  239. inline T
  240. inner_product(InputIterator1 first1, InputIterator1 last1,
  241. InputIterator2 first2, T init,
  242. __gnu_parallel::_Parallelism parallelism_tag)
  243. {
  244. typedef iterator_traits<InputIterator1> traits_type1;
  245. typedef typename traits_type1::value_type value_type1;
  246. typedef iterator_traits<InputIterator2> traits_type2;
  247. typedef typename traits_type2::value_type value_type2;
  248. typedef typename
  249. __gnu_parallel::multiplies<value_type1, value_type2>::result
  250. multiplies_result_type;
  251. return _GLIBCXX_STD_P::inner_product(first1, last1, first2, init,
  252. __gnu_parallel::plus<T, multiplies_result_type>(),
  253. __gnu_parallel::
  254. multiplies<value_type1, value_type2>(),
  255. parallelism_tag);
  256. }
  257. template<typename InputIterator1, typename InputIterator2, typename T>
  258. inline T
  259. inner_product(InputIterator1 first1, InputIterator1 last1,
  260. InputIterator2 first2, T init)
  261. {
  262. typedef iterator_traits<InputIterator1> traits_type1;
  263. typedef typename traits_type1::value_type value_type1;
  264. typedef iterator_traits<InputIterator2> traits_type2;
  265. typedef typename traits_type2::value_type value_type2;
  266. typedef typename
  267. __gnu_parallel::multiplies<value_type1, value_type2>::result
  268. multiplies_result_type;
  269. return _GLIBCXX_STD_P::inner_product(first1, last1, first2, init,
  270. __gnu_parallel::plus<T, multiplies_result_type>(),
  271. __gnu_parallel::
  272. multiplies<value_type1, value_type2>());
  273. }
  274. // Sequential fallback.
  275. template<typename InputIterator, typename OutputIterator>
  276. inline OutputIterator
  277. partial_sum(InputIterator begin, InputIterator end, OutputIterator result,
  278. __gnu_parallel::sequential_tag)
  279. { return _GLIBCXX_STD_P::partial_sum(begin, end, result); }
  280. // Sequential fallback.
  281. template<typename InputIterator, typename OutputIterator,
  282. typename BinaryOperation>
  283. inline OutputIterator
  284. partial_sum(InputIterator begin, InputIterator end, OutputIterator result,
  285. BinaryOperation bin_op, __gnu_parallel::sequential_tag)
  286. { return _GLIBCXX_STD_P::partial_sum(begin, end, result, bin_op); }
  287. // Sequential fallback for input iterator case.
  288. template<typename InputIterator, typename OutputIterator,
  289. typename BinaryOperation, typename IteratorTag1,
  290. typename IteratorTag2>
  291. inline OutputIterator
  292. partial_sum_switch(InputIterator begin, InputIterator end,
  293. OutputIterator result, BinaryOperation bin_op,
  294. IteratorTag1, IteratorTag2)
  295. { return _GLIBCXX_STD_P::partial_sum(begin, end, result, bin_op); }
  296. // Parallel algorithm for random access iterators.
  297. template<typename InputIterator, typename OutputIterator,
  298. typename BinaryOperation>
  299. OutputIterator
  300. partial_sum_switch(InputIterator begin, InputIterator end,
  301. OutputIterator result, BinaryOperation bin_op,
  302. random_access_iterator_tag, random_access_iterator_tag)
  303. {
  304. if (_GLIBCXX_PARALLEL_CONDITION(
  305. static_cast<__gnu_parallel::sequence_index_t>(end - begin)
  306. >= __gnu_parallel::_Settings::get().partial_sum_minimal_n))
  307. return __gnu_parallel::parallel_partial_sum(begin, end,
  308. result, bin_op);
  309. else
  310. return partial_sum(begin, end, result, bin_op,
  311. __gnu_parallel::sequential_tag());
  312. }
  313. // Public interface.
  314. template<typename InputIterator, typename OutputIterator>
  315. inline OutputIterator
  316. partial_sum(InputIterator begin, InputIterator end, OutputIterator result)
  317. {
  318. typedef typename iterator_traits<InputIterator>::value_type value_type;
  319. return _GLIBCXX_STD_P::partial_sum(begin, end, result,
  320. std::plus<value_type>());
  321. }
  322. // Public interface
  323. template<typename InputIterator, typename OutputIterator,
  324. typename BinaryOperation>
  325. inline OutputIterator
  326. partial_sum(InputIterator begin, InputIterator end, OutputIterator result,
  327. BinaryOperation binary_op)
  328. {
  329. typedef iterator_traits<InputIterator> traitsi_type;
  330. typedef typename traitsi_type::iterator_category iteratori_category;
  331. typedef iterator_traits<OutputIterator> traitso_type;
  332. typedef typename traitso_type::iterator_category iteratoro_category;
  333. return partial_sum_switch(begin, end, result, binary_op,
  334. iteratori_category(), iteratoro_category());
  335. }
  336. // Sequential fallback.
  337. template<typename InputIterator, typename OutputIterator>
  338. inline OutputIterator
  339. adjacent_difference(InputIterator begin, InputIterator end,
  340. OutputIterator result, __gnu_parallel::sequential_tag)
  341. { return _GLIBCXX_STD_P::adjacent_difference(begin, end, result); }
  342. // Sequential fallback.
  343. template<typename InputIterator, typename OutputIterator,
  344. typename BinaryOperation>
  345. inline OutputIterator
  346. adjacent_difference(InputIterator begin, InputIterator end,
  347. OutputIterator result, BinaryOperation bin_op,
  348. __gnu_parallel::sequential_tag)
  349. { return _GLIBCXX_STD_P::adjacent_difference(begin, end, result, bin_op); }
  350. // Sequential fallback for input iterator case.
  351. template<typename InputIterator, typename OutputIterator,
  352. typename BinaryOperation, typename IteratorTag1,
  353. typename IteratorTag2>
  354. inline OutputIterator
  355. adjacent_difference_switch(InputIterator begin, InputIterator end,
  356. OutputIterator result, BinaryOperation bin_op,
  357. IteratorTag1, IteratorTag2)
  358. { return adjacent_difference(begin, end, result, bin_op,
  359. __gnu_parallel::sequential_tag()); }
  360. // Parallel algorithm for random access iterators.
  361. template<typename InputIterator, typename OutputIterator,
  362. typename BinaryOperation>
  363. OutputIterator
  364. adjacent_difference_switch(InputIterator begin, InputIterator end,
  365. OutputIterator result, BinaryOperation bin_op,
  366. random_access_iterator_tag,
  367. random_access_iterator_tag,
  368. __gnu_parallel::_Parallelism parallelism_tag
  369. = __gnu_parallel::parallel_balanced)
  370. {
  371. if (_GLIBCXX_PARALLEL_CONDITION(
  372. static_cast<__gnu_parallel::sequence_index_t>(end - begin)
  373. >= __gnu_parallel::_Settings::get().adjacent_difference_minimal_n
  374. && __gnu_parallel::is_parallel(parallelism_tag)))
  375. {
  376. bool dummy = true;
  377. typedef __gnu_parallel::iterator_pair<InputIterator, OutputIterator,
  378. random_access_iterator_tag> ip;
  379. *result = *begin;
  380. ip begin_pair(begin + 1, result + 1),
  381. end_pair(end, result + (end - begin));
  382. __gnu_parallel::adjacent_difference_selector<ip> functionality;
  383. __gnu_parallel::
  384. for_each_template_random_access_ed(begin_pair, end_pair, bin_op,
  385. functionality,
  386. __gnu_parallel::dummy_reduct(),
  387. dummy, dummy, -1);
  388. return functionality.finish_iterator;
  389. }
  390. else
  391. return adjacent_difference(begin, end, result, bin_op,
  392. __gnu_parallel::sequential_tag());
  393. }
  394. // Public interface.
  395. template<typename InputIterator, typename OutputIterator>
  396. inline OutputIterator
  397. adjacent_difference(InputIterator begin, InputIterator end,
  398. OutputIterator result,
  399. __gnu_parallel::_Parallelism parallelism_tag)
  400. {
  401. typedef iterator_traits<InputIterator> traits_type;
  402. typedef typename traits_type::value_type value_type;
  403. return adjacent_difference(begin, end, result, std::minus<value_type>(),
  404. parallelism_tag);
  405. }
  406. template<typename InputIterator, typename OutputIterator>
  407. inline OutputIterator
  408. adjacent_difference(InputIterator begin, InputIterator end,
  409. OutputIterator result)
  410. {
  411. typedef iterator_traits<InputIterator> traits_type;
  412. typedef typename traits_type::value_type value_type;
  413. return adjacent_difference(begin, end, result, std::minus<value_type>());
  414. }
  415. template<typename InputIterator, typename OutputIterator,
  416. typename BinaryOperation>
  417. inline OutputIterator
  418. adjacent_difference(InputIterator begin, InputIterator end,
  419. OutputIterator result, BinaryOperation binary_op,
  420. __gnu_parallel::_Parallelism parallelism_tag)
  421. {
  422. typedef iterator_traits<InputIterator> traitsi_type;
  423. typedef typename traitsi_type::iterator_category iteratori_category;
  424. typedef iterator_traits<OutputIterator> traitso_type;
  425. typedef typename traitso_type::iterator_category iteratoro_category;
  426. return adjacent_difference_switch(begin, end, result, binary_op,
  427. iteratori_category(),
  428. iteratoro_category(), parallelism_tag);
  429. }
  430. template<typename InputIterator, typename OutputIterator,
  431. typename BinaryOperation>
  432. inline OutputIterator
  433. adjacent_difference(InputIterator begin, InputIterator end,
  434. OutputIterator result, BinaryOperation binary_op)
  435. {
  436. typedef iterator_traits<InputIterator> traitsi_type;
  437. typedef typename traitsi_type::iterator_category iteratori_category;
  438. typedef iterator_traits<OutputIterator> traitso_type;
  439. typedef typename traitso_type::iterator_category iteratoro_category;
  440. return adjacent_difference_switch(begin, end, result, binary_op,
  441. iteratori_category(),
  442. iteratoro_category());
  443. }
  444. } // end namespace
  445. } // end namespace
  446. #endif /* _GLIBCXX_NUMERIC_H */