1// -*- C++ -*-
2
3// Copyright (C) 2007-2020 Free Software Foundation, Inc.
4//
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 3, or (at your option) any later
9// version.
10
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.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file parallel/for_each_selectors.h
26 *  @brief Functors representing different tasks to be plugged into the
27 *  generic parallelization methods for embarrassingly parallel functions.
28 *  This file is a GNU parallel extension to the Standard C++ Library.
29 */
30
31// Written by Felix Putze.
32
33#ifndef _GLIBCXX_PARALLEL_FOR_EACH_SELECTORS_H
34#define _GLIBCXX_PARALLEL_FOR_EACH_SELECTORS_H 1
35
36#include <parallel/basic_iterator.h>
37
38namespace __gnu_parallel
39{
40  /** @brief Generic __selector for embarrassingly parallel functions. */
41  template<typename _It>
42    struct __generic_for_each_selector
43    {
44      /** @brief _Iterator on last element processed; needed for some
45       *  algorithms (e. g. std::transform()).
46       */
47      _It _M_finish_iterator;
48    };
49
50  /** @brief std::for_each() selector. */
51  template<typename _It>
52    struct __for_each_selector : public __generic_for_each_selector<_It>
53    {
54      /** @brief Functor execution.
55       *  @param __o Operator.
56       *  @param __i iterator referencing object. */
57      template<typename _Op>
58        bool
59        operator()(_Op& __o, _It __i)
60        {
61          __o(*__i);
62          return true;
63        }
64    };
65
66  /** @brief std::generate() selector. */
67  template<typename _It>
68    struct __generate_selector : public __generic_for_each_selector<_It>
69    {
70      /** @brief Functor execution.
71       *  @param __o Operator.
72       *  @param __i iterator referencing object. */
73      template<typename _Op>
74        bool
75        operator()(_Op& __o, _It __i)
76        {
77          *__i = __o();
78          return true;
79        }
80    };
81
82  /** @brief std::fill() selector. */
83  template<typename _It>
84    struct __fill_selector : public __generic_for_each_selector<_It>
85    {
86      /** @brief Functor execution.
87       *  @param __v Current value.
88       *  @param __i iterator referencing object. */
89      template<typename _ValueType>
90        bool
91        operator()(_ValueType& __v, _It __i)
92        {
93          *__i = __v;
94          return true;
95        }
96    };
97
98  /** @brief std::transform() __selector, one input sequence variant. */
99  template<typename _It>
100    struct __transform1_selector : public __generic_for_each_selector<_It>
101    {
102      /** @brief Functor execution.
103       *  @param __o Operator.
104       *  @param __i iterator referencing object. */
105      template<typename _Op>
106        bool
107        operator()(_Op& __o, _It __i)
108        {
109          *__i.second = __o(*__i.first);
110          return true;
111        }
112    };
113
114  /** @brief std::transform() __selector, two input sequences variant. */
115  template<typename _It>
116    struct __transform2_selector : public __generic_for_each_selector<_It>
117    {
118      /** @brief Functor execution.
119       *  @param __o Operator.
120       *  @param __i iterator referencing object. */
121      template<typename _Op>
122        bool
123        operator()(_Op& __o, _It __i)
124        {
125          *__i._M_third = __o(*__i._M_first, *__i._M_second);
126          return true;
127        }
128    };
129
130  /** @brief std::replace() selector. */
131  template<typename _It, typename _Tp>
132    struct __replace_selector : public __generic_for_each_selector<_It>
133    {
134      /** @brief Value to replace with. */
135      const _Tp& __new_val;
136
137      /** @brief Constructor
138       *  @param __new_val Value to replace with. */
139      explicit
140      __replace_selector(const _Tp &__new_val) : __new_val(__new_val) {}
141
142      /** @brief Functor execution.
143       *  @param __v Current value.
144       *  @param __i iterator referencing object. */
145      bool
146      operator()(_Tp& __v, _It __i)
147      {
148        if (*__i == __v)
149          *__i = __new_val;
150        return true;
151      }
152    };
153
154  /** @brief std::replace() selector. */
155  template<typename _It, typename _Op, typename _Tp>
156    struct __replace_if_selector : public __generic_for_each_selector<_It>
157    {
158      /** @brief Value to replace with. */
159      const _Tp& __new_val;
160
161      /** @brief Constructor.
162       *  @param __new_val Value to replace with. */
163      explicit
164      __replace_if_selector(const _Tp &__new_val) : __new_val(__new_val) { }
165
166      /** @brief Functor execution.
167       *  @param __o Operator.
168       *  @param __i iterator referencing object. */
169      bool
170      operator()(_Op& __o, _It __i)
171      {
172        if (__o(*__i))
173          *__i = __new_val;
174        return true;
175      }
176    };
177
178  /** @brief std::count() selector. */
179  template<typename _It, typename _Diff>
180    struct __count_selector : public __generic_for_each_selector<_It>
181    {
182      /** @brief Functor execution.
183       *  @param __v Current value.
184       *  @param __i iterator referencing object.
185       *  @return 1 if count, 0 if does not count. */
186      template<typename _ValueType>
187        _Diff
188        operator()(_ValueType& __v, _It __i)
189        { return (__v == *__i) ? 1 : 0; }
190    };
191
192  /** @brief std::count_if () selector. */
193  template<typename _It, typename _Diff>
194    struct __count_if_selector : public __generic_for_each_selector<_It>
195    {
196      /** @brief Functor execution.
197       *  @param __o Operator.
198       *  @param __i iterator referencing object.
199       *  @return 1 if count, 0 if does not count. */
200      template<typename _Op>
201        _Diff
202        operator()(_Op& __o, _It __i)
203        { return (__o(*__i)) ? 1 : 0; }
204    };
205
206  /** @brief std::accumulate() selector. */
207  template<typename _It>
208    struct __accumulate_selector : public __generic_for_each_selector<_It>
209    {
210      /** @brief Functor execution.
211       *  @param __o Operator (unused).
212       *  @param __i iterator referencing object.
213       *  @return The current value. */
214      template<typename _Op>
215        typename std::iterator_traits<_It>::value_type
216        operator()(_Op __o, _It __i)
217        { return *__i; }
218    };
219
220  /** @brief std::inner_product() selector. */
221  template<typename _It, typename _It2, typename _Tp>
222    struct __inner_product_selector : public __generic_for_each_selector<_It>
223    {
224      /** @brief Begin iterator of first sequence. */
225      _It  __begin1_iterator;
226
227      /** @brief Begin iterator of second sequence. */
228      _It2 __begin2_iterator;
229
230      /** @brief Constructor.
231       *  @param __b1 Begin iterator of first sequence.
232       *  @param __b2 Begin iterator of second sequence. */
233      explicit
234      __inner_product_selector(_It __b1, _It2 __b2)
235      : __begin1_iterator(__b1), __begin2_iterator(__b2) { }
236
237      /** @brief Functor execution.
238       *  @param __mult Multiplication functor.
239       *  @param __current iterator referencing object.
240       *  @return Inner product elemental __result. */
241      template<typename _Op>
242        _Tp
243        operator()(_Op __mult, _It __current)
244        {
245          typename std::iterator_traits<_It>::difference_type __position
246            = __current - __begin1_iterator;
247          return __mult(*__current, *(__begin2_iterator + __position));
248        }
249    };
250
251  /** @brief Selector that just returns the passed iterator. */
252  template<typename _It>
253    struct __identity_selector : public __generic_for_each_selector<_It>
254    {
255      /** @brief Functor execution.
256       *  @param __o Operator (unused).
257       *  @param __i iterator referencing object.
258       *  @return Passed iterator. */
259      template<typename _Op>
260        _It
261        operator()(_Op __o, _It __i)
262        { return __i; }
263    };
264
265  /** @brief Selector that returns the difference between two adjacent
266   *  __elements.
267   */
268  template<typename _It>
269    struct __adjacent_difference_selector
270    : public __generic_for_each_selector<_It>
271    {
272      template<typename _Op>
273        bool
274        operator()(_Op& __o, _It __i)
275        {
276          typename _It::first_type __go_back_one = __i.first;
277          --__go_back_one;
278          *__i.second = __o(*__i.first, *__go_back_one);
279          return true;
280        }
281    };
282
283  /** @brief Functor doing nothing
284   *
285   *  For some __reduction tasks (this is not a function object, but is
286   *  passed as __selector __dummy parameter.
287   */
288  struct _Nothing
289  {
290    /** @brief Functor execution.
291     *  @param __i iterator referencing object. */
292    template<typename _It>
293      void
294      operator()(_It __i) { }
295  };
296
297  /** @brief Reduction function doing nothing. */
298  struct _DummyReduct
299  {
300    bool
301    operator()(bool, bool) const
302    { return true; }
303  };
304
305  /** @brief Reduction for finding the maximum element, using a comparator. */
306  template<typename _Compare, typename _It>
307    struct __min_element_reduct
308    {
309      _Compare& __comp;
310
311      explicit
312      __min_element_reduct(_Compare &__c) : __comp(__c) { }
313
314      _It
315      operator()(_It __x, _It __y)
316      { return (__comp(*__x, *__y)) ? __x : __y; }
317    };
318
319  /** @brief Reduction for finding the maximum element, using a comparator. */
320  template<typename _Compare, typename _It>
321    struct __max_element_reduct
322    {
323      _Compare& __comp;
324
325      explicit
326      __max_element_reduct(_Compare& __c) : __comp(__c) { }
327
328      _It
329      operator()(_It __x, _It __y)
330      { return (__comp(*__x, *__y)) ? __y : __x; }
331    };
332
333  /** @brief General reduction, using a binary operator. */
334  template<typename _BinOp>
335    struct __accumulate_binop_reduct
336    {
337      _BinOp& __binop;
338
339      explicit
340      __accumulate_binop_reduct(_BinOp& __b) : __binop(__b) { }
341
342      template<typename _Result, typename _Addend>
343        _Result
344        operator()(const _Result& __x, const _Addend& __y)
345        { return __binop(__x, __y); }
346    };
347}
348
349#endif /* _GLIBCXX_PARALLEL_FOR_EACH_SELECTORS_H */
350