Home | History | Annotate | Download | only in parallel
      1 // -*- C++ -*-
      2 
      3 // Copyright (C) 2007, 2008, 2009 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/tags.h>
     42 #include <parallel/settings.h>
     43 #include <parallel/find.h>
     44 #include <parallel/find_selectors.h>
     45 
     46 namespace std
     47 {
     48 namespace __parallel
     49 {
     50   // NB: equal and lexicographical_compare require mismatch.
     51 
     52   // Sequential fallback
     53   template<typename InputIterator1, typename InputIterator2>
     54     inline pair<InputIterator1, InputIterator2>
     55     mismatch(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2,
     56 	     __gnu_parallel::sequential_tag)
     57     { return _GLIBCXX_STD_P::mismatch(begin1, end1, begin2); }
     58 
     59   // Sequential fallback
     60   template<typename InputIterator1, typename InputIterator2,
     61 	   typename Predicate>
     62     inline pair<InputIterator1, InputIterator2>
     63     mismatch(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2,
     64 	     Predicate pred, __gnu_parallel::sequential_tag)
     65     { return _GLIBCXX_STD_P::mismatch(begin1, end1, begin2, pred); }
     66 
     67   // Sequential fallback for input iterator case
     68   template<typename InputIterator1, typename InputIterator2,
     69 	   typename Predicate, typename IteratorTag1, typename IteratorTag2>
     70     inline pair<InputIterator1, InputIterator2>
     71     mismatch_switch(InputIterator1 begin1, InputIterator1 end1,
     72 		    InputIterator2 begin2, Predicate pred, IteratorTag1,
     73 		    IteratorTag2)
     74     { return _GLIBCXX_STD_P::mismatch(begin1, end1, begin2, pred); }
     75 
     76   // Parallel mismatch for random access iterators
     77   template<typename RandomAccessIterator1, typename RandomAccessIterator2,
     78 	   typename Predicate>
     79     pair<RandomAccessIterator1, RandomAccessIterator2>
     80     mismatch_switch(RandomAccessIterator1 begin1, RandomAccessIterator1 end1,
     81 		    RandomAccessIterator2 begin2, Predicate pred,
     82 		    random_access_iterator_tag, random_access_iterator_tag)
     83     {
     84       if (_GLIBCXX_PARALLEL_CONDITION(true))
     85 	{
     86 	  RandomAccessIterator1 res =
     87 	    __gnu_parallel::find_template(begin1, end1, begin2, pred,
     88 					  __gnu_parallel::
     89 					  mismatch_selector()).first;
     90 	  return make_pair(res , begin2 + (res - begin1));
     91 	}
     92       else
     93 	return _GLIBCXX_STD_P::mismatch(begin1, end1, begin2, pred);
     94     }
     95 
     96   // Public interface
     97   template<typename InputIterator1, typename InputIterator2>
     98     inline pair<InputIterator1, InputIterator2>
     99     mismatch(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2)
    100     {
    101       typedef std::iterator_traits<InputIterator1> iterator1_traits;
    102       typedef std::iterator_traits<InputIterator2> iterator2_traits;
    103       typedef typename iterator1_traits::value_type value1_type;
    104       typedef typename iterator2_traits::value_type value2_type;
    105       typedef typename iterator1_traits::iterator_category iterator1_category;
    106       typedef typename iterator2_traits::iterator_category iterator2_category;
    107 
    108       typedef __gnu_parallel::equal_to<value1_type, value2_type> equal_to_type;
    109 
    110       return mismatch_switch(begin1, end1, begin2, equal_to_type(),
    111 			     iterator1_category(), iterator2_category());
    112     }
    113 
    114   // Public interface
    115   template<typename InputIterator1, typename InputIterator2,
    116 	   typename Predicate>
    117     inline pair<InputIterator1, InputIterator2>
    118     mismatch(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2,
    119 	     Predicate pred)
    120     {
    121       typedef std::iterator_traits<InputIterator1> iterator1_traits;
    122       typedef std::iterator_traits<InputIterator2> iterator2_traits;
    123       typedef typename iterator1_traits::iterator_category iterator1_category;
    124       typedef typename iterator2_traits::iterator_category iterator2_category;
    125 
    126       return mismatch_switch(begin1, end1, begin2, pred, iterator1_category(),
    127 			     iterator2_category());
    128     }
    129 
    130   // Sequential fallback
    131   template<typename InputIterator1, typename InputIterator2>
    132     inline bool
    133     equal(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2,
    134 	  __gnu_parallel::sequential_tag)
    135     { return _GLIBCXX_STD_P::equal(begin1, end1, begin2); }
    136 
    137   // Sequential fallback
    138   template<typename InputIterator1, typename InputIterator2,
    139 	   typename Predicate>
    140     inline bool
    141     equal(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2,
    142 	  Predicate pred, __gnu_parallel::sequential_tag)
    143     { return _GLIBCXX_STD_P::equal(begin1, end1, begin2, pred); }
    144 
    145   // Public interface
    146   template<typename InputIterator1, typename InputIterator2>
    147     inline bool
    148     equal(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2)
    149     { return mismatch(begin1, end1, begin2).first == end1; }
    150 
    151   // Public interface
    152   template<typename InputIterator1, typename InputIterator2,
    153 	   typename Predicate>
    154     inline bool
    155     equal(InputIterator1 begin1, InputIterator1 end1, InputIterator2 begin2,
    156 	  Predicate pred)
    157     { return mismatch(begin1, end1, begin2, pred).first == end1; }
    158 
    159   // Sequential fallback
    160   template<typename InputIterator1, typename InputIterator2>
    161     inline bool
    162     lexicographical_compare(InputIterator1 begin1, InputIterator1 end1,
    163 			    InputIterator2 begin2, InputIterator2 end2,
    164 			    __gnu_parallel::sequential_tag)
    165     { return _GLIBCXX_STD_P::lexicographical_compare(begin1, end1,
    166 						     begin2, end2); }
    167 
    168   // Sequential fallback
    169   template<typename InputIterator1, typename InputIterator2,
    170 	   typename Predicate>
    171     inline bool
    172     lexicographical_compare(InputIterator1 begin1, InputIterator1 end1,
    173 			    InputIterator2 begin2, InputIterator2 end2,
    174 			    Predicate pred, __gnu_parallel::sequential_tag)
    175     { return _GLIBCXX_STD_P::lexicographical_compare(begin1, end1,
    176 						     begin2, end2, pred); }
    177 
    178   // Sequential fallback for input iterator case
    179   template<typename InputIterator1, typename InputIterator2,
    180 	   typename Predicate, typename IteratorTag1, typename IteratorTag2>
    181     inline bool
    182     lexicographical_compare_switch(InputIterator1 begin1, InputIterator1 end1,
    183 				   InputIterator2 begin2, InputIterator2 end2,
    184 				   Predicate pred, IteratorTag1, IteratorTag2)
    185     { return _GLIBCXX_STD_P::lexicographical_compare(begin1, end1,
    186 						     begin2, end2, pred); }
    187 
    188   // Parallel lexicographical_compare for random access iterators
    189   // Limitation: Both valuetypes must be the same
    190   template<typename RandomAccessIterator1, typename RandomAccessIterator2,
    191 	   typename Predicate>
    192     bool
    193     lexicographical_compare_switch(RandomAccessIterator1 begin1,
    194 				   RandomAccessIterator1 end1,
    195 				   RandomAccessIterator2 begin2,
    196 				   RandomAccessIterator2 end2, Predicate pred,
    197 				   random_access_iterator_tag,
    198 				   random_access_iterator_tag)
    199     {
    200       if (_GLIBCXX_PARALLEL_CONDITION(true))
    201 	{
    202 	  typedef iterator_traits<RandomAccessIterator1> traits1_type;
    203 	  typedef typename traits1_type::value_type value1_type;
    204 
    205 	  typedef iterator_traits<RandomAccessIterator2> traits2_type;
    206 	  typedef typename traits2_type::value_type value2_type;
    207 
    208 	  typedef __gnu_parallel::equal_from_less<Predicate, value1_type,
    209 	                                          value2_type> equal_type;
    210 
    211 	  // Longer sequence in first place.
    212 	  if ((end1 - begin1) < (end2 - begin2))
    213 	    {
    214 	      typedef pair<RandomAccessIterator1, RandomAccessIterator2>
    215 		pair_type;
    216 	      pair_type mm = mismatch_switch(begin1, end1, begin2,
    217 					     equal_type(pred),
    218 					     random_access_iterator_tag(),
    219 					     random_access_iterator_tag());
    220 
    221 	      return (mm.first == end1) || bool(pred(*mm.first, *mm.second));
    222 	    }
    223 	  else
    224 	    {
    225 	      typedef pair<RandomAccessIterator2, RandomAccessIterator1>
    226 		pair_type;
    227 	      pair_type mm = mismatch_switch(begin2, end2, begin1,
    228 					     equal_type(pred),
    229 					     random_access_iterator_tag(),
    230 					     random_access_iterator_tag());
    231 
    232 	      return (mm.first != end2) && bool(pred(*mm.second, *mm.first));
    233 	    }
    234 	}
    235       else
    236 	return _GLIBCXX_STD_P::lexicographical_compare(begin1, end1,
    237 						       begin2, end2, pred);
    238     }
    239 
    240   // Public interface
    241   template<typename InputIterator1, typename InputIterator2>
    242     inline bool
    243     lexicographical_compare(InputIterator1 begin1, InputIterator1 end1,
    244 			    InputIterator2 begin2, InputIterator2 end2)
    245     {
    246       typedef iterator_traits<InputIterator1> traits1_type;
    247       typedef typename traits1_type::value_type value1_type;
    248       typedef typename traits1_type::iterator_category iterator1_category;
    249 
    250       typedef iterator_traits<InputIterator2> traits2_type;
    251       typedef typename traits2_type::value_type value2_type;
    252       typedef typename traits2_type::iterator_category iterator2_category;
    253       typedef __gnu_parallel::less<value1_type, value2_type> less_type;
    254 
    255       return lexicographical_compare_switch(begin1, end1, begin2, end2,
    256 					    less_type(), iterator1_category(),
    257 					    iterator2_category());
    258     }
    259 
    260   // Public interface
    261   template<typename InputIterator1, typename InputIterator2,
    262 	   typename Predicate>
    263     inline bool
    264     lexicographical_compare(InputIterator1 begin1, InputIterator1 end1,
    265 			    InputIterator2 begin2, InputIterator2 end2,
    266 			    Predicate pred)
    267     {
    268       typedef iterator_traits<InputIterator1> traits1_type;
    269       typedef typename traits1_type::iterator_category iterator1_category;
    270 
    271       typedef iterator_traits<InputIterator2> traits2_type;
    272       typedef typename traits2_type::iterator_category iterator2_category;
    273 
    274       return lexicographical_compare_switch(begin1, end1, begin2, end2, pred,
    275 					    iterator1_category(),
    276 					    iterator2_category());
    277     }
    278 } // end namespace
    279 } // end namespace
    280 
    281 #endif /* _GLIBCXX_PARALLEL_ALGOBASE_H */
    282