1  // -*- C++ -*-
       2  
       3  // Copyright (C) 2007-2023 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  
      38  namespace __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 */