Home | History | Annotate | Download | only in parallel
      1 // -*- C++ -*-
      2 
      3 // Copyright (C) 2007-2013 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/algobase.h
     26  *  @brief Parallel STL function calls corresponding to the
     27  *  stl_algobase.h header.  The functions defined here mainly do case
     28  *  switches and call the actual parallelized versions in other files.
     29  *  Inlining policy: Functions that basically only contain one
     30  *  function call, are declared inline.
     31  *  This file is a GNU parallel extension to the Standard C++ Library.
     32  */
     33 
     34 // Written by Johannes Singler and Felix Putze.
     35 
     36 #ifndef _GLIBCXX_PARALLEL_ALGOBASE_H
     37 #define _GLIBCXX_PARALLEL_ALGOBASE_H 1
     38 
     39 #include <bits/stl_algobase.h>
     40 #include <parallel/base.h>
     41 #include <parallel/algorithmfwd.h>
     42 #include <parallel/find.h>
     43 #include <parallel/find_selectors.h>
     44 
     45 namespace std _GLIBCXX_VISIBILITY(default)
     46 {
     47 namespace __parallel
     48 {
     49   // NB: equal and lexicographical_compare require mismatch.
     50 
     51   // Sequential fallback
     52   template<typename _IIter1, typename _IIter2>
     53     inline pair<_IIter1, _IIter2>
     54     mismatch(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2,
     55              __gnu_parallel::sequential_tag)
     56     { return _GLIBCXX_STD_A::mismatch(__begin1, __end1, __begin2); }
     57 
     58   // Sequential fallback
     59   template<typename _IIter1, typename _IIter2, typename _Predicate>
     60     inline pair<_IIter1, _IIter2>
     61     mismatch(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2,
     62              _Predicate __pred, __gnu_parallel::sequential_tag)
     63     { return _GLIBCXX_STD_A::mismatch(__begin1, __end1, __begin2, __pred); }
     64 
     65   // Sequential fallback for input iterator case
     66   template<typename _IIter1, typename _IIter2,
     67            typename _Predicate, typename _IteratorTag1, typename _IteratorTag2>
     68     inline pair<_IIter1, _IIter2>
     69     __mismatch_switch(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2,
     70                       _Predicate __pred, _IteratorTag1, _IteratorTag2)
     71     { return _GLIBCXX_STD_A::mismatch(__begin1, __end1, __begin2, __pred); }
     72 
     73   // Parallel mismatch for random access iterators
     74   template<typename _RAIter1, typename _RAIter2, typename _Predicate>
     75     pair<_RAIter1, _RAIter2>
     76     __mismatch_switch(_RAIter1 __begin1, _RAIter1 __end1,
     77                       _RAIter2 __begin2, _Predicate __pred,
     78                       random_access_iterator_tag, random_access_iterator_tag)
     79     {
     80       if (_GLIBCXX_PARALLEL_CONDITION(true))
     81         {
     82           _RAIter1 __res =
     83             __gnu_parallel::__find_template(__begin1, __end1, __begin2, __pred,
     84                                             __gnu_parallel::
     85                                             __mismatch_selector()).first;
     86           return make_pair(__res , __begin2 + (__res - __begin1));
     87         }
     88       else
     89         return _GLIBCXX_STD_A::mismatch(__begin1, __end1, __begin2, __pred);
     90     }
     91 
     92   // Public interface
     93   template<typename _IIter1, typename _IIter2>
     94     inline pair<_IIter1, _IIter2>
     95     mismatch(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2)
     96     {
     97       typedef std::iterator_traits<_IIter1> _Iterator1Traits;
     98       typedef std::iterator_traits<_IIter2> _Iterator2Traits;
     99       typedef typename _Iterator1Traits::value_type _ValueType1;
    100       typedef typename _Iterator2Traits::value_type _ValueType2;
    101       typedef typename _Iterator1Traits::iterator_category _IteratorCategory1;
    102       typedef typename _Iterator2Traits::iterator_category _IteratorCategory2;
    103 
    104       typedef __gnu_parallel::_EqualTo<_ValueType1, _ValueType2> _EqualTo;
    105 
    106       return __mismatch_switch(__begin1, __end1, __begin2, _EqualTo(),
    107                                _IteratorCategory1(), _IteratorCategory2());
    108     }
    109 
    110   // Public interface
    111   template<typename _IIter1, typename _IIter2, typename _Predicate>
    112     inline pair<_IIter1, _IIter2>
    113     mismatch(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2,
    114              _Predicate __pred)
    115     {
    116       typedef std::iterator_traits<_IIter1> _Iterator1Traits;
    117       typedef std::iterator_traits<_IIter2> _Iterator2Traits;
    118       typedef typename _Iterator1Traits::iterator_category _IteratorCategory1;
    119       typedef typename _Iterator2Traits::iterator_category _IteratorCategory2;
    120 
    121       return __mismatch_switch(__begin1, __end1, __begin2, __pred,
    122                                _IteratorCategory1(), _IteratorCategory2());
    123     }
    124 
    125   // Sequential fallback
    126   template<typename _IIter1, typename _IIter2>
    127     inline bool
    128     equal(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2,
    129           __gnu_parallel::sequential_tag)
    130     { return _GLIBCXX_STD_A::equal(__begin1, __end1, __begin2); }
    131 
    132   // Sequential fallback
    133   template<typename _IIter1, typename _IIter2, typename _Predicate>
    134     inline bool
    135     equal(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2,
    136           _Predicate __pred, __gnu_parallel::sequential_tag)
    137     { return _GLIBCXX_STD_A::equal(__begin1, __end1, __begin2, __pred); }
    138 
    139   // Public interface
    140   template<typename _IIter1, typename _IIter2>
    141     inline bool
    142     equal(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2)
    143     {
    144       return __gnu_parallel::mismatch(__begin1, __end1, __begin2).first
    145               == __end1;
    146     }
    147 
    148   // Public interface
    149   template<typename _IIter1, typename _IIter2, typename _Predicate>
    150     inline bool
    151     equal(_IIter1 __begin1, _IIter1 __end1, _IIter2 __begin2,
    152           _Predicate __pred)
    153     {
    154       return __gnu_parallel::mismatch(__begin1, __end1, __begin2, __pred).first
    155               == __end1;
    156     }
    157 
    158   // Sequential fallback
    159   template<typename _IIter1, typename _IIter2>
    160     inline bool
    161     lexicographical_compare(_IIter1 __begin1, _IIter1 __end1,
    162                             _IIter2 __begin2, _IIter2 __end2,
    163                             __gnu_parallel::sequential_tag)
    164     { return _GLIBCXX_STD_A::lexicographical_compare(__begin1, __end1,
    165                                                      __begin2, __end2); }
    166 
    167   // Sequential fallback
    168   template<typename _IIter1, typename _IIter2, typename _Predicate>
    169     inline bool
    170     lexicographical_compare(_IIter1 __begin1, _IIter1 __end1,
    171                             _IIter2 __begin2, _IIter2 __end2,
    172                             _Predicate __pred, __gnu_parallel::sequential_tag)
    173     { return _GLIBCXX_STD_A::lexicographical_compare(
    174                __begin1, __end1, __begin2, __end2, __pred); }
    175 
    176   // Sequential fallback for input iterator case
    177   template<typename _IIter1, typename _IIter2,
    178            typename _Predicate, typename _IteratorTag1, typename _IteratorTag2>
    179     inline bool
    180     __lexicographical_compare_switch(_IIter1 __begin1, _IIter1 __end1,
    181                                      _IIter2 __begin2, _IIter2 __end2,
    182                                      _Predicate __pred,
    183                                      _IteratorTag1, _IteratorTag2)
    184     { return _GLIBCXX_STD_A::lexicographical_compare(
    185                __begin1, __end1, __begin2, __end2, __pred); }
    186 
    187   // Parallel lexicographical_compare for random access iterators
    188   // Limitation: Both valuetypes must be the same
    189   template<typename _RAIter1, typename _RAIter2, typename _Predicate>
    190     bool
    191     __lexicographical_compare_switch(_RAIter1 __begin1, _RAIter1 __end1,
    192                                      _RAIter2 __begin2, _RAIter2 __end2,
    193                                      _Predicate __pred,
    194                                      random_access_iterator_tag,
    195                                      random_access_iterator_tag)
    196     {
    197       if (_GLIBCXX_PARALLEL_CONDITION(true))
    198         {
    199           typedef iterator_traits<_RAIter1> _TraitsType1;
    200           typedef typename _TraitsType1::value_type _ValueType1;
    201 
    202           typedef iterator_traits<_RAIter2> _TraitsType2;
    203           typedef typename _TraitsType2::value_type _ValueType2;
    204 
    205           typedef __gnu_parallel::
    206                   _EqualFromLess<_ValueType1, _ValueType2, _Predicate>
    207                   _EqualFromLessCompare;
    208 
    209           // Longer sequence in first place.
    210           if ((__end1 - __begin1) < (__end2 - __begin2))
    211             {
    212               typedef pair<_RAIter1, _RAIter2> _SpotType;
    213               _SpotType __mm = __mismatch_switch(__begin1, __end1, __begin2,
    214                                              _EqualFromLessCompare(__pred),
    215                                              random_access_iterator_tag(),
    216                                              random_access_iterator_tag());
    217 
    218               return (__mm.first == __end1)
    219                         || bool(__pred(*__mm.first, *__mm.second));
    220             }
    221           else
    222             {
    223               typedef pair<_RAIter2, _RAIter1> _SpotType;
    224               _SpotType __mm = __mismatch_switch(__begin2, __end2, __begin1,
    225                                              _EqualFromLessCompare(__pred),
    226                                              random_access_iterator_tag(),
    227                                              random_access_iterator_tag());
    228 
    229               return (__mm.first != __end2)
    230                         && bool(__pred(*__mm.second, *__mm.first));
    231             }
    232         }
    233       else
    234         return _GLIBCXX_STD_A::lexicographical_compare(
    235                  __begin1, __end1, __begin2, __end2, __pred);
    236     }
    237 
    238   // Public interface
    239   template<typename _IIter1, typename _IIter2>
    240     inline bool
    241     lexicographical_compare(_IIter1 __begin1, _IIter1 __end1,
    242                             _IIter2 __begin2, _IIter2 __end2)
    243     {
    244       typedef iterator_traits<_IIter1> _TraitsType1;
    245       typedef typename _TraitsType1::value_type _ValueType1;
    246       typedef typename _TraitsType1::iterator_category _IteratorCategory1;
    247 
    248       typedef iterator_traits<_IIter2> _TraitsType2;
    249       typedef typename _TraitsType2::value_type _ValueType2;
    250       typedef typename _TraitsType2::iterator_category _IteratorCategory2;
    251       typedef __gnu_parallel::_Less<_ValueType1, _ValueType2> _LessType;
    252 
    253       return __lexicographical_compare_switch(
    254                __begin1, __end1, __begin2, __end2, _LessType(),
    255                _IteratorCategory1(), _IteratorCategory2());
    256     }
    257 
    258   // Public interface
    259   template<typename _IIter1, typename _IIter2, typename _Predicate>
    260     inline bool
    261     lexicographical_compare(_IIter1 __begin1, _IIter1 __end1,
    262                             _IIter2 __begin2, _IIter2 __end2,
    263                             _Predicate __pred)
    264     {
    265       typedef iterator_traits<_IIter1> _TraitsType1;
    266       typedef typename _TraitsType1::iterator_category _IteratorCategory1;
    267 
    268       typedef iterator_traits<_IIter2> _TraitsType2;
    269       typedef typename _TraitsType2::iterator_category _IteratorCategory2;
    270 
    271       return __lexicographical_compare_switch(
    272                __begin1, __end1, __begin2, __end2, __pred,
    273                _IteratorCategory1(), _IteratorCategory2());
    274     }
    275 } // end namespace
    276 } // end namespace
    277 
    278 #endif /* _GLIBCXX_PARALLEL_ALGOBASE_H */
    279