(root)/
gcc-13.2.0/
libstdc++-v3/
include/
parallel/
base.h
       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/base.h
      26   *  @brief Sequential helper functions.
      27   *  This file is a GNU parallel extension to the Standard C++ Library.
      28   */
      29  
      30  // Written by Johannes Singler.
      31  
      32  #ifndef _GLIBCXX_PARALLEL_BASE_H
      33  #define _GLIBCXX_PARALLEL_BASE_H 1
      34  
      35  #include <bits/c++config.h>
      36  #include <bits/stl_function.h>
      37  #include <omp.h>
      38  #include <parallel/features.h>
      39  #include <parallel/basic_iterator.h>
      40  #include <parallel/parallel.h>
      41  
      42  // Parallel mode namespaces.
      43  
      44  /**
      45   * @namespace std::__parallel
      46   * @brief GNU parallel code, replaces standard behavior with parallel behavior.
      47   */
      48  namespace std _GLIBCXX_VISIBILITY(default) 
      49  { 
      50    namespace __parallel { } 
      51  }
      52  
      53  /**
      54   * @namespace __gnu_parallel
      55   * @brief GNU parallel code for public use.
      56   */
      57  namespace __gnu_parallel
      58  {
      59    // Import all the parallel versions of components in namespace std.
      60    using namespace std::__parallel;
      61  }
      62  
      63  /**
      64   * @namespace __gnu_sequential
      65   * @brief GNU sequential classes for public use.
      66   */
      67  namespace __gnu_sequential 
      68  { 
      69    // Import whatever is the serial version.
      70  #ifdef _GLIBCXX_PARALLEL
      71    using namespace std::_GLIBCXX_STD_A;
      72  #else
      73    using namespace std;
      74  #endif   
      75  }
      76  
      77  
      78  namespace __gnu_parallel
      79  {
      80    // NB: Including this file cannot produce (unresolved) symbols from
      81    // the OpenMP runtime unless the parallel mode is actually invoked
      82    // and active, which imples that the OpenMP runtime is actually
      83    // going to be linked in.
      84    inline _ThreadIndex
      85    __get_max_threads() 
      86    { 
      87      _ThreadIndex __i = omp_get_max_threads();
      88      return __i > 1 ? __i : 1; 
      89    }
      90  
      91  
      92    inline bool 
      93    __is_parallel(const _Parallelism __p) { return __p != sequential; }
      94  
      95  
      96    /** @brief Calculates the rounded-down logarithm of @c __n for base 2.
      97     *  @param __n Argument.
      98     *  @return Returns 0 for any argument <1.
      99     */
     100    template<typename _Size>
     101      inline _Size
     102      __rd_log2(_Size __n)
     103      {
     104        _Size __k;
     105        for (__k = 0; __n > 1; __n >>= 1)
     106          ++__k;
     107        return __k;
     108      }
     109  
     110    /** @brief Encode two integers into one gnu_parallel::_CASable.
     111     *  @param __a First integer, to be encoded in the most-significant @c
     112     *  _CASable_bits/2 bits.
     113     *  @param __b Second integer, to be encoded in the least-significant
     114     *  @c _CASable_bits/2 bits.
     115     *  @return value encoding @c __a and @c __b.
     116     *  @see __decode2
     117     */
     118    inline _CASable
     119    __encode2(int __a, int __b)     //must all be non-negative, actually
     120    {
     121      return (((_CASable)__a) << (_CASable_bits / 2)) | (((_CASable)__b) << 0);
     122    }
     123  
     124    /** @brief Decode two integers from one gnu_parallel::_CASable.
     125     *  @param __x __gnu_parallel::_CASable to decode integers from.
     126     *  @param __a First integer, to be decoded from the most-significant
     127     *  @c _CASable_bits/2 bits of @c __x.
     128     *  @param __b Second integer, to be encoded in the least-significant
     129     *  @c _CASable_bits/2 bits of @c __x.
     130     *  @see __encode2
     131     */
     132    inline void
     133    __decode2(_CASable __x, int& __a, int& __b)
     134    {
     135      __a = (int)((__x >> (_CASable_bits / 2)) & _CASable_mask);
     136      __b = (int)((__x >>               0 ) & _CASable_mask);
     137    }
     138  
     139    //needed for parallel "numeric", even if "algorithm" not included
     140  
     141    /** @brief Equivalent to std::min. */
     142    template<typename _Tp>
     143      inline const _Tp&
     144      min(const _Tp& __a, const _Tp& __b)
     145      { return (__a < __b) ? __a : __b; }
     146  
     147    /** @brief Equivalent to std::max. */
     148    template<typename _Tp>
     149      inline const _Tp&
     150      max(const _Tp& __a, const _Tp& __b)
     151      { return (__a > __b) ? __a : __b; }
     152  
     153    /** @brief Constructs predicate for equality from strict weak
     154     *  ordering predicate
     155     */
     156    template<typename _T1, typename _T2, typename _Compare>
     157      class _EqualFromLess : public std::binary_function<_T1, _T2, bool>
     158      {
     159      private:
     160        _Compare& _M_comp;
     161  
     162      public:
     163        _EqualFromLess(_Compare& __comp) : _M_comp(__comp) { }
     164  
     165        bool operator()(const _T1& __a, const _T2& __b)
     166        { return !_M_comp(__a, __b) && !_M_comp(__b, __a); }
     167      };
     168  
     169  
     170    /** @brief Similar to std::unary_negate,
     171     *  but giving the argument types explicitly. */
     172    template<typename _Predicate, typename argument_type>
     173      class __unary_negate
     174      : public std::unary_function<argument_type, bool>
     175      {
     176      protected:
     177        _Predicate _M_pred;
     178  
     179      public:
     180        explicit
     181        __unary_negate(const _Predicate& __x) : _M_pred(__x) { }
     182  
     183        bool
     184        operator()(const argument_type& __x)
     185        { return !_M_pred(__x); }
     186      };
     187  
     188    /** @brief Similar to std::binder1st,
     189     *  but giving the argument types explicitly. */
     190    template<typename _Operation, typename _FirstArgumentType,
     191  	   typename _SecondArgumentType, typename _ResultType>
     192      class __binder1st
     193      : public std::unary_function<_SecondArgumentType, _ResultType>
     194      {
     195      protected:
     196        _Operation _M_op;
     197        _FirstArgumentType _M_value;
     198  
     199      public:
     200        __binder1st(const _Operation& __x, const _FirstArgumentType& __y)
     201        : _M_op(__x), _M_value(__y) { }
     202  
     203        _ResultType
     204        operator()(const _SecondArgumentType& __x)
     205        { return _M_op(_M_value, __x); }
     206  
     207        // _GLIBCXX_RESOLVE_LIB_DEFECTS
     208        // 109.  Missing binders for non-const sequence elements
     209        _ResultType
     210        operator()(_SecondArgumentType& __x) const
     211        { return _M_op(_M_value, __x); }
     212      };
     213  
     214    /**
     215     *  @brief Similar to std::binder2nd, but giving the argument types
     216     *  explicitly.
     217     */
     218    template<typename _Operation, typename _FirstArgumentType,
     219  	   typename _SecondArgumentType, typename _ResultType>
     220      class __binder2nd
     221      : public std::unary_function<_FirstArgumentType, _ResultType>
     222      {
     223      protected:
     224        _Operation _M_op;
     225        _SecondArgumentType _M_value;
     226  
     227      public:
     228        __binder2nd(const _Operation& __x, const _SecondArgumentType& __y)
     229        : _M_op(__x), _M_value(__y) { }
     230  
     231        _ResultType
     232        operator()(const _FirstArgumentType& __x) const
     233        { return _M_op(__x, _M_value); }
     234  
     235        // _GLIBCXX_RESOLVE_LIB_DEFECTS
     236        // 109.  Missing binders for non-const sequence elements
     237        _ResultType
     238        operator()(_FirstArgumentType& __x)
     239        { return _M_op(__x, _M_value); }
     240      };
     241  
     242    /** @brief Similar to std::equal_to, but allows two different types. */
     243    template<typename _T1, typename _T2>
     244      struct _EqualTo : std::binary_function<_T1, _T2, bool>
     245      {
     246        bool operator()(const _T1& __t1, const _T2& __t2) const
     247        { return __t1 == __t2; }
     248      };
     249  
     250    /** @brief Similar to std::less, but allows two different types. */
     251    template<typename _T1, typename _T2>
     252      struct _Less : std::binary_function<_T1, _T2, bool>
     253      {
     254        bool
     255        operator()(const _T1& __t1, const _T2& __t2) const
     256        { return __t1 < __t2; }
     257  
     258        bool
     259        operator()(const _T2& __t2, const _T1& __t1) const
     260        { return __t2 < __t1; }
     261      };
     262  
     263    // Partial specialization for one type. Same as std::less.
     264    template<typename _Tp>
     265      struct _Less<_Tp, _Tp>
     266      : public std::less<_Tp> { };
     267  
     268    /** @brief Similar to std::plus, but allows two different types. */
     269    template<typename _Tp1, typename _Tp2, typename _Result
     270  	   = __typeof__(*static_cast<_Tp1*>(0)
     271  			+ *static_cast<_Tp2*>(0))>
     272      struct _Plus : public std::binary_function<_Tp1, _Tp2, _Result>
     273      {
     274        _Result
     275        operator()(const _Tp1& __x, const _Tp2& __y) const
     276        { return __x + __y; }
     277      };
     278  
     279    // Partial specialization for one type. Same as std::plus.
     280    template<typename _Tp>
     281      struct _Plus<_Tp, _Tp, _Tp>
     282      : public std::plus<_Tp> { };
     283  
     284    /** @brief Similar to std::multiplies, but allows two different types. */
     285    template<typename _Tp1, typename _Tp2, typename _Result
     286  	   = __typeof__(*static_cast<_Tp1*>(0)
     287  			* *static_cast<_Tp2*>(0))>
     288      struct _Multiplies : public std::binary_function<_Tp1, _Tp2, _Result>
     289      {
     290        _Result
     291        operator()(const _Tp1& __x, const _Tp2& __y) const
     292        { return __x * __y; }
     293      };
     294  
     295    // Partial specialization for one type. Same as std::multiplies.
     296    template<typename _Tp>
     297      struct _Multiplies<_Tp, _Tp, _Tp>
     298      : public std::multiplies<_Tp> { };
     299  
     300    /** @brief _Iterator associated with __gnu_parallel::_PseudoSequence.
     301     *  If features the usual random-access iterator functionality.
     302     *  @param _Tp Sequence _M_value type.
     303     *  @param _DifferenceTp Sequence difference type.
     304     */
     305    template<typename _Tp, typename _DifferenceTp>
     306      class _PseudoSequenceIterator
     307      {
     308      public:
     309        typedef _DifferenceTp _DifferenceType;
     310  
     311        _PseudoSequenceIterator(const _Tp& __val, _DifferenceType __pos)
     312        : _M_val(__val), _M_pos(__pos) { }
     313  
     314        // Pre-increment operator.
     315        _PseudoSequenceIterator&
     316        operator++()
     317        {
     318  	++_M_pos;
     319  	return *this;
     320        }
     321  
     322        // Post-increment operator.
     323        _PseudoSequenceIterator
     324        operator++(int)
     325        { return _PseudoSequenceIterator(_M_pos++); }
     326  
     327        const _Tp&
     328        operator*() const
     329        { return _M_val; }
     330  
     331        const _Tp&
     332        operator[](_DifferenceType) const
     333        { return _M_val; }
     334  
     335        bool
     336        operator==(const _PseudoSequenceIterator& __i2)
     337        { return _M_pos == __i2._M_pos; }
     338  
     339        bool
     340        operator!=(const _PseudoSequenceIterator& __i2)
     341        { return _M_pos != __i2._M_pos; }
     342  
     343        _DifferenceType
     344        operator-(const _PseudoSequenceIterator& __i2)
     345        { return _M_pos - __i2._M_pos; }
     346  
     347      private:
     348        const _Tp& _M_val;
     349        _DifferenceType _M_pos;
     350      };
     351  
     352    /** @brief Sequence that conceptually consists of multiple copies of
     353        the same element.
     354        *  The copies are not stored explicitly, of course.
     355        *  @param _Tp Sequence _M_value type.
     356        *  @param _DifferenceTp Sequence difference type.
     357        */
     358    template<typename _Tp, typename _DifferenceTp>
     359      class _PseudoSequence
     360      {
     361      public:
     362        typedef _DifferenceTp _DifferenceType;
     363  
     364        // Better cast down to uint64_t, than up to _DifferenceTp.
     365        typedef _PseudoSequenceIterator<_Tp, uint64_t> iterator;
     366  
     367        /** @brief Constructor.
     368         *  @param __val Element of the sequence.
     369         *  @param __count Number of (virtual) copies.
     370         */
     371        _PseudoSequence(const _Tp& __val, _DifferenceType __count)
     372        : _M_val(__val), _M_count(__count)  { }
     373  
     374        /** @brief Begin iterator. */
     375        iterator
     376        begin() const
     377        { return iterator(_M_val, 0); }
     378  
     379        /** @brief End iterator. */
     380        iterator
     381        end() const
     382        { return iterator(_M_val, _M_count); }
     383  
     384      private:
     385        const _Tp& _M_val;
     386        _DifferenceType _M_count;
     387      };
     388  
     389    /** @brief Compute the median of three referenced elements,
     390        according to @c __comp.
     391        *  @param __a First iterator.
     392        *  @param __b Second iterator.
     393        *  @param __c Third iterator.
     394        *  @param __comp Comparator.
     395        */
     396    template<typename _RAIter, typename _Compare>
     397      _RAIter
     398      __median_of_three_iterators(_RAIter __a, _RAIter __b,
     399  				_RAIter __c, _Compare __comp)
     400      {
     401        if (__comp(*__a, *__b))
     402  	if (__comp(*__b, *__c))
     403  	  return __b;
     404  	else
     405  	  if (__comp(*__a, *__c))
     406  	    return __c;
     407  	  else
     408  	    return __a;
     409        else
     410  	{
     411  	  // Just swap __a and __b.
     412  	  if (__comp(*__a, *__c))
     413  	    return __a;
     414  	  else
     415  	    if (__comp(*__b, *__c))
     416  	      return __c;
     417  	    else
     418  	      return __b;
     419  	}
     420      }
     421  
     422  #if _GLIBCXX_PARALLEL_ASSERTIONS && defined(__glibcxx_assert_impl)
     423  # define _GLIBCXX_PARALLEL_ASSERT(_Condition) \
     424    do { __glibcxx_assert_impl(_Condition); } while (false)
     425  #else
     426  # define _GLIBCXX_PARALLEL_ASSERT(_Condition) do { } while (false)
     427  #endif
     428  
     429  } //namespace __gnu_parallel
     430  
     431  #endif /* _GLIBCXX_PARALLEL_BASE_H */