3 // Copyright (C) 2007, 2008 Free Software Foundation, Inc.
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the terms
7 // of the GNU General Public License as published by the Free Software
8 // Foundation; either version 2, or (at your option) any later
11 // This library is distributed in the hope that it will be useful, but
12 // WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this library; see the file COPYING. If not, write to
18 // the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
19 // MA 02111-1307, USA.
21 // As a special exception, you may use this file as part of a free
22 // software library without restriction. Specifically, if other files
23 // instantiate templates or use macros or inline functions from this
24 // file, or you compile this file and link it with other files to
25 // produce an executable, this file does not by itself cause the
26 // resulting executable to be covered by the GNU General Public
27 // License. This exception does not however invalidate any other
28 // reasons why the executable file might be covered by the GNU General
32 * @file parallel/numeric
34 * @brief Parallel STL function calls corresponding to stl_numeric.h.
35 * The functions defined here mainly do case switches and
36 * call the actual parallelized versions in other files.
37 * Inlining policy: Functions that basically only contain one function call,
38 * are declared inline.
39 * This file is a GNU parallel extension to the Standard C++ Library.
42 // Written by Johannes Singler and Felix Putze.
44 #ifndef _GLIBCXX_PARALLEL_NUMERIC_H
45 #define _GLIBCXX_PARALLEL_NUMERIC_H 1
49 #include <parallel/numericfwd.h>
50 #include <parallel/iterator.h>
51 #include <parallel/for_each.h>
52 #include <parallel/for_each_selectors.h>
53 #include <parallel/partial_sum.h>
59 // Sequential fallback.
60 template<typename InputIterator, typename T>
62 accumulate(InputIterator begin, InputIterator end, T init,
63 __gnu_parallel::sequential_tag)
64 { return _GLIBCXX_STD_P::accumulate(begin, end, init); }
66 template<typename InputIterator, typename T, typename BinaryOperation>
68 accumulate(InputIterator begin, InputIterator end, T init,
69 BinaryOperation binary_op, __gnu_parallel::sequential_tag)
70 { return _GLIBCXX_STD_P::accumulate(begin, end, init, binary_op); }
72 // Sequential fallback for input iterator case.
73 template<typename InputIterator, typename T, typename IteratorTag>
75 accumulate_switch(InputIterator begin, InputIterator end,
77 { return accumulate(begin, end, init, __gnu_parallel::sequential_tag()); }
79 template<typename InputIterator, typename T, typename BinaryOperation,
82 accumulate_switch(InputIterator begin, InputIterator end, T init,
83 BinaryOperation binary_op, IteratorTag)
84 { return accumulate(begin, end, init, binary_op,
85 __gnu_parallel::sequential_tag()); }
87 // Parallel algorithm for random access iterators.
88 template<typename _RandomAccessIterator, typename T,
89 typename BinaryOperation>
91 accumulate_switch(_RandomAccessIterator begin, _RandomAccessIterator end,
92 T init, BinaryOperation binary_op,
93 random_access_iterator_tag,
94 __gnu_parallel::_Parallelism parallelism_tag
95 = __gnu_parallel::parallel_unbalanced)
97 if (_GLIBCXX_PARALLEL_CONDITION(
98 static_cast<__gnu_parallel::sequence_index_t>(end - begin)
99 >= __gnu_parallel::_Settings::get().accumulate_minimal_n
100 && __gnu_parallel::is_parallel(parallelism_tag)))
103 __gnu_parallel::accumulate_selector<_RandomAccessIterator>
106 for_each_template_random_access(begin, end,
107 __gnu_parallel::nothing(),
110 accumulate_binop_reduct
111 <BinaryOperation>(binary_op),
112 res, res, -1, parallelism_tag);
116 return accumulate(begin, end, init, binary_op,
117 __gnu_parallel::sequential_tag());
121 template<typename InputIterator, typename T>
123 accumulate(InputIterator begin, InputIterator end, T init,
124 __gnu_parallel::_Parallelism parallelism_tag)
126 typedef std::iterator_traits<InputIterator> iterator_traits;
127 typedef typename iterator_traits::value_type value_type;
128 typedef typename iterator_traits::iterator_category iterator_category;
130 return accumulate_switch(begin, end, init,
131 __gnu_parallel::plus<T, value_type>(),
132 iterator_category(), parallelism_tag);
135 template<typename InputIterator, typename T>
137 accumulate(InputIterator begin, InputIterator end, T init)
139 typedef std::iterator_traits<InputIterator> iterator_traits;
140 typedef typename iterator_traits::value_type value_type;
141 typedef typename iterator_traits::iterator_category iterator_category;
143 return accumulate_switch(begin, end, init,
144 __gnu_parallel::plus<T, value_type>(),
145 iterator_category());
148 template<typename InputIterator, typename T, typename BinaryOperation>
150 accumulate(InputIterator begin, InputIterator end, T init,
151 BinaryOperation binary_op,
152 __gnu_parallel::_Parallelism parallelism_tag)
154 typedef iterator_traits<InputIterator> iterator_traits;
155 typedef typename iterator_traits::iterator_category iterator_category;
156 return accumulate_switch(begin, end, init, binary_op,
157 iterator_category(), parallelism_tag);
160 template<typename InputIterator, typename T, typename BinaryOperation>
162 accumulate(InputIterator begin, InputIterator end, T init,
163 BinaryOperation binary_op)
165 typedef iterator_traits<InputIterator> iterator_traits;
166 typedef typename iterator_traits::iterator_category iterator_category;
167 return accumulate_switch(begin, end, init, binary_op,
168 iterator_category());
172 // Sequential fallback.
173 template<typename InputIterator1, typename InputIterator2, typename T>
175 inner_product(InputIterator1 first1, InputIterator1 last1,
176 InputIterator2 first2, T init,
177 __gnu_parallel::sequential_tag)
178 { return _GLIBCXX_STD_P::inner_product(first1, last1, first2, init); }
180 template<typename InputIterator1, typename InputIterator2, typename T,
181 typename BinaryFunction1, typename BinaryFunction2>
183 inner_product(InputIterator1 first1, InputIterator1 last1,
184 InputIterator2 first2, T init, BinaryFunction1 binary_op1,
185 BinaryFunction2 binary_op2, __gnu_parallel::sequential_tag)
186 { return _GLIBCXX_STD_P::inner_product(first1, last1, first2, init,
187 binary_op1, binary_op2); }
189 // Parallel algorithm for random access iterators.
190 template<typename RandomAccessIterator1, typename RandomAccessIterator2,
191 typename T, typename BinaryFunction1, typename BinaryFunction2>
193 inner_product_switch(RandomAccessIterator1 first1,
194 RandomAccessIterator1 last1,
195 RandomAccessIterator2 first2, T init,
196 BinaryFunction1 binary_op1,
197 BinaryFunction2 binary_op2,
198 random_access_iterator_tag,
199 random_access_iterator_tag,
200 __gnu_parallel::_Parallelism parallelism_tag
201 = __gnu_parallel::parallel_unbalanced)
203 if (_GLIBCXX_PARALLEL_CONDITION((last1 - first1)
204 >= __gnu_parallel::_Settings::get().
207 is_parallel(parallelism_tag)))
211 inner_product_selector<RandomAccessIterator1,
212 RandomAccessIterator2, T> my_selector(first1, first2);
214 for_each_template_random_access(first1, last1, binary_op2,
215 my_selector, binary_op1,
216 res, res, -1, parallelism_tag);
220 return inner_product(first1, last1, first2, init,
221 __gnu_parallel::sequential_tag());
224 // No parallelism for input iterators.
225 template<typename InputIterator1, typename InputIterator2, typename T,
226 typename BinaryFunction1, typename BinaryFunction2,
227 typename IteratorTag1, typename IteratorTag2>
229 inner_product_switch(InputIterator1 first1, InputIterator1 last1,
230 InputIterator2 first2, T init,
231 BinaryFunction1 binary_op1,
232 BinaryFunction2 binary_op2,
233 IteratorTag1, IteratorTag2)
234 { return inner_product(first1, last1, first2, init,
235 binary_op1, binary_op2,
236 __gnu_parallel::sequential_tag()); }
238 template<typename InputIterator1, typename InputIterator2, typename T,
239 typename BinaryFunction1, typename BinaryFunction2>
241 inner_product(InputIterator1 first1, InputIterator1 last1,
242 InputIterator2 first2, T init, BinaryFunction1 binary_op1,
243 BinaryFunction2 binary_op2,
244 __gnu_parallel::_Parallelism parallelism_tag)
246 typedef iterator_traits<InputIterator1> traits1_type;
247 typedef typename traits1_type::iterator_category iterator1_category;
249 typedef iterator_traits<InputIterator2> traits2_type;
250 typedef typename traits2_type::iterator_category iterator2_category;
252 return inner_product_switch(first1, last1, first2, init, binary_op1,
253 binary_op2, iterator1_category(),
254 iterator2_category(), parallelism_tag);
257 template<typename InputIterator1, typename InputIterator2, typename T,
258 typename BinaryFunction1, typename BinaryFunction2>
260 inner_product(InputIterator1 first1, InputIterator1 last1,
261 InputIterator2 first2, T init, BinaryFunction1 binary_op1,
262 BinaryFunction2 binary_op2)
264 typedef iterator_traits<InputIterator1> traits1_type;
265 typedef typename traits1_type::iterator_category iterator1_category;
267 typedef iterator_traits<InputIterator2> traits2_type;
268 typedef typename traits2_type::iterator_category iterator2_category;
270 return inner_product_switch(first1, last1, first2, init, binary_op1,
271 binary_op2, iterator1_category(),
272 iterator2_category());
275 template<typename InputIterator1, typename InputIterator2, typename T>
277 inner_product(InputIterator1 first1, InputIterator1 last1,
278 InputIterator2 first2, T init,
279 __gnu_parallel::_Parallelism parallelism_tag)
281 typedef iterator_traits<InputIterator1> traits_type1;
282 typedef typename traits_type1::value_type value_type1;
283 typedef iterator_traits<InputIterator2> traits_type2;
284 typedef typename traits_type2::value_type value_type2;
287 __gnu_parallel::multiplies<value_type1, value_type2>::result
288 multiplies_result_type;
289 return inner_product(first1, last1, first2, init,
290 __gnu_parallel::plus<T, multiplies_result_type>(),
292 multiplies<value_type1, value_type2>(),
296 template<typename InputIterator1, typename InputIterator2, typename T>
298 inner_product(InputIterator1 first1, InputIterator1 last1,
299 InputIterator2 first2, T init)
301 typedef iterator_traits<InputIterator1> traits_type1;
302 typedef typename traits_type1::value_type value_type1;
303 typedef iterator_traits<InputIterator2> traits_type2;
304 typedef typename traits_type2::value_type value_type2;
307 __gnu_parallel::multiplies<value_type1, value_type2>::result
308 multiplies_result_type;
309 return inner_product(first1, last1, first2, init,
310 __gnu_parallel::plus<T, multiplies_result_type>(),
312 multiplies<value_type1, value_type2>());
315 // Sequential fallback.
316 template<typename InputIterator, typename OutputIterator>
317 inline OutputIterator
318 partial_sum(InputIterator begin, InputIterator end, OutputIterator result,
319 __gnu_parallel::sequential_tag)
320 { return _GLIBCXX_STD_P::partial_sum(begin, end, result); }
322 // Sequential fallback.
323 template<typename InputIterator, typename OutputIterator,
324 typename BinaryOperation>
325 inline OutputIterator
326 partial_sum(InputIterator begin, InputIterator end, OutputIterator result,
327 BinaryOperation bin_op, __gnu_parallel::sequential_tag)
328 { return _GLIBCXX_STD_P::partial_sum(begin, end, result, bin_op); }
330 // Sequential fallback for input iterator case.
331 template<typename InputIterator, typename OutputIterator,
332 typename BinaryOperation, typename IteratorTag1,
333 typename IteratorTag2>
334 inline OutputIterator
335 partial_sum_switch(InputIterator begin, InputIterator end,
336 OutputIterator result, BinaryOperation bin_op,
337 IteratorTag1, IteratorTag2)
338 { return _GLIBCXX_STD_P::partial_sum(begin, end, result, bin_op); }
340 // Parallel algorithm for random access iterators.
341 template<typename InputIterator, typename OutputIterator,
342 typename BinaryOperation>
344 partial_sum_switch(InputIterator begin, InputIterator end,
345 OutputIterator result, BinaryOperation bin_op,
346 random_access_iterator_tag, random_access_iterator_tag)
348 if (_GLIBCXX_PARALLEL_CONDITION(
349 static_cast<__gnu_parallel::sequence_index_t>(end - begin)
350 >= __gnu_parallel::_Settings::get().partial_sum_minimal_n))
351 return __gnu_parallel::parallel_partial_sum(begin, end,
354 return partial_sum(begin, end, result, bin_op,
355 __gnu_parallel::sequential_tag());
359 template<typename InputIterator, typename OutputIterator>
360 inline OutputIterator
361 partial_sum(InputIterator begin, InputIterator end, OutputIterator result)
363 typedef typename iterator_traits<InputIterator>::value_type value_type;
364 return partial_sum(begin, end, result, std::plus<value_type>());
368 template<typename InputIterator, typename OutputIterator,
369 typename BinaryOperation>
370 inline OutputIterator
371 partial_sum(InputIterator begin, InputIterator end, OutputIterator result,
372 BinaryOperation binary_op)
374 typedef iterator_traits<InputIterator> traitsi_type;
375 typedef typename traitsi_type::iterator_category iteratori_category;
377 typedef iterator_traits<OutputIterator> traitso_type;
378 typedef typename traitso_type::iterator_category iteratoro_category;
380 return partial_sum_switch(begin, end, result, binary_op,
381 iteratori_category(), iteratoro_category());
384 // Sequential fallback.
385 template<typename InputIterator, typename OutputIterator>
386 inline OutputIterator
387 adjacent_difference(InputIterator begin, InputIterator end,
388 OutputIterator result, __gnu_parallel::sequential_tag)
389 { return _GLIBCXX_STD_P::adjacent_difference(begin, end, result); }
391 // Sequential fallback.
392 template<typename InputIterator, typename OutputIterator,
393 typename BinaryOperation>
394 inline OutputIterator
395 adjacent_difference(InputIterator begin, InputIterator end,
396 OutputIterator result, BinaryOperation bin_op,
397 __gnu_parallel::sequential_tag)
398 { return _GLIBCXX_STD_P::adjacent_difference(begin, end, result, bin_op); }
400 // Sequential fallback for input iterator case.
401 template<typename InputIterator, typename OutputIterator,
402 typename BinaryOperation, typename IteratorTag1,
403 typename IteratorTag2>
404 inline OutputIterator
405 adjacent_difference_switch(InputIterator begin, InputIterator end,
406 OutputIterator result, BinaryOperation bin_op,
407 IteratorTag1, IteratorTag2)
408 { return adjacent_difference(begin, end, result, bin_op,
409 __gnu_parallel::sequential_tag()); }
411 // Parallel algorithm for random access iterators.
412 template<typename InputIterator, typename OutputIterator,
413 typename BinaryOperation>
415 adjacent_difference_switch(InputIterator begin, InputIterator end,
416 OutputIterator result, BinaryOperation bin_op,
417 random_access_iterator_tag,
418 random_access_iterator_tag,
419 __gnu_parallel::_Parallelism parallelism_tag
420 = __gnu_parallel::parallel_balanced)
422 if (_GLIBCXX_PARALLEL_CONDITION(
423 static_cast<__gnu_parallel::sequence_index_t>(end - begin)
424 >= __gnu_parallel::_Settings::get().adjacent_difference_minimal_n
425 && __gnu_parallel::is_parallel(parallelism_tag)))
428 typedef __gnu_parallel::iterator_pair<InputIterator, OutputIterator,
429 random_access_iterator_tag> ip;
431 ip begin_pair(begin + 1, result + 1),
432 end_pair(end, result + (end - begin));
433 __gnu_parallel::adjacent_difference_selector<ip> functionality;
435 for_each_template_random_access(begin_pair, end_pair, bin_op,
437 __gnu_parallel::dummy_reduct(),
438 dummy, dummy, -1, parallelism_tag);
439 return functionality.finish_iterator;
442 return adjacent_difference(begin, end, result, bin_op,
443 __gnu_parallel::sequential_tag());
447 template<typename InputIterator, typename OutputIterator>
448 inline OutputIterator
449 adjacent_difference(InputIterator begin, InputIterator end,
450 OutputIterator result,
451 __gnu_parallel::_Parallelism parallelism_tag)
453 typedef iterator_traits<InputIterator> traits_type;
454 typedef typename traits_type::value_type value_type;
455 return adjacent_difference(begin, end, result, std::minus<value_type>(),
459 template<typename InputIterator, typename OutputIterator>
460 inline OutputIterator
461 adjacent_difference(InputIterator begin, InputIterator end,
462 OutputIterator result)
464 typedef iterator_traits<InputIterator> traits_type;
465 typedef typename traits_type::value_type value_type;
466 return adjacent_difference(begin, end, result, std::minus<value_type>());
469 template<typename InputIterator, typename OutputIterator,
470 typename BinaryOperation>
471 inline OutputIterator
472 adjacent_difference(InputIterator begin, InputIterator end,
473 OutputIterator result, BinaryOperation binary_op,
474 __gnu_parallel::_Parallelism parallelism_tag)
476 typedef iterator_traits<InputIterator> traitsi_type;
477 typedef typename traitsi_type::iterator_category iteratori_category;
479 typedef iterator_traits<OutputIterator> traitso_type;
480 typedef typename traitso_type::iterator_category iteratoro_category;
482 return adjacent_difference_switch(begin, end, result, binary_op,
483 iteratori_category(),
484 iteratoro_category(), parallelism_tag);
487 template<typename InputIterator, typename OutputIterator,
488 typename BinaryOperation>
489 inline OutputIterator
490 adjacent_difference(InputIterator begin, InputIterator end,
491 OutputIterator result, BinaryOperation binary_op)
493 typedef iterator_traits<InputIterator> traitsi_type;
494 typedef typename traitsi_type::iterator_category iteratori_category;
496 typedef iterator_traits<OutputIterator> traitso_type;
497 typedef typename traitso_type::iterator_category iteratoro_category;
499 return adjacent_difference_switch(begin, end, result, binary_op,
500 iteratori_category(),
501 iteratoro_category());
506 #endif /* _GLIBCXX_NUMERIC_H */