Home | History | Annotate | Line # | Download | only in parallel
      1   1.1  mrg // -*- C++ -*-
      2   1.1  mrg 
      3  1.12  mrg // Copyright (C) 2007-2022 Free Software Foundation, Inc.
      4   1.1  mrg //
      5   1.1  mrg // This file is part of the GNU ISO C++ Library.  This library is free
      6   1.1  mrg // software; you can redistribute it and/or modify it under the terms
      7   1.1  mrg // of the GNU General Public License as published by the Free Software
      8   1.1  mrg // Foundation; either version 3, or (at your option) any later
      9   1.1  mrg // version.
     10   1.1  mrg 
     11   1.1  mrg // This library is distributed in the hope that it will be useful, but
     12   1.1  mrg // WITHOUT ANY WARRANTY; without even the implied warranty of
     13   1.1  mrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14   1.1  mrg // General Public License for more details.
     15   1.1  mrg 
     16   1.1  mrg // Under Section 7 of GPL version 3, you are granted additional
     17   1.1  mrg // permissions described in the GCC Runtime Library Exception, version
     18   1.1  mrg // 3.1, as published by the Free Software Foundation.
     19   1.1  mrg 
     20   1.1  mrg // You should have received a copy of the GNU General Public License and
     21   1.1  mrg // a copy of the GCC Runtime Library Exception along with this program;
     22   1.1  mrg // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23   1.1  mrg // <http://www.gnu.org/licenses/>.
     24   1.1  mrg 
     25   1.1  mrg /** @file parallel/merge.h
     26   1.1  mrg  *  @brief Parallel implementation of std::merge().
     27   1.1  mrg  *  This file is a GNU parallel extension to the Standard C++ Library.
     28   1.1  mrg  */
     29   1.1  mrg 
     30   1.1  mrg // Written by Johannes Singler.
     31   1.1  mrg 
     32   1.1  mrg #ifndef _GLIBCXX_PARALLEL_MERGE_H
     33   1.1  mrg #define _GLIBCXX_PARALLEL_MERGE_H 1
     34   1.1  mrg 
     35   1.1  mrg #include <parallel/basic_iterator.h>
     36   1.1  mrg #include <bits/stl_algo.h>
     37   1.1  mrg 
     38   1.1  mrg namespace __gnu_parallel
     39   1.1  mrg {
     40   1.1  mrg   /** @brief Merge routine being able to merge only the @c __max_length
     41   1.1  mrg    * smallest elements.
     42   1.1  mrg    *
     43   1.1  mrg    * The @c __begin iterators are advanced accordingly, they might not
     44   1.1  mrg    * reach @c __end, in contrast to the usual variant.
     45   1.1  mrg    * @param __begin1 Begin iterator of first sequence.
     46   1.1  mrg    * @param __end1 End iterator of first sequence.
     47   1.1  mrg    * @param __begin2 Begin iterator of second sequence.
     48   1.1  mrg    * @param __end2 End iterator of second sequence.
     49   1.1  mrg    * @param __target Target begin iterator.
     50   1.1  mrg    * @param __max_length Maximum number of elements to merge.
     51   1.1  mrg    * @param __comp Comparator.
     52   1.1  mrg    * @return Output end iterator. */
     53   1.1  mrg   template<typename _RAIter1, typename _RAIter2,
     54   1.1  mrg            typename _OutputIterator, typename _DifferenceTp,
     55   1.1  mrg            typename _Compare>
     56   1.1  mrg     _OutputIterator
     57   1.1  mrg     __merge_advance_usual(_RAIter1& __begin1, _RAIter1 __end1,
     58   1.1  mrg 			  _RAIter2& __begin2, _RAIter2 __end2,
     59   1.1  mrg 			  _OutputIterator __target,
     60   1.1  mrg 			  _DifferenceTp __max_length, _Compare __comp)
     61   1.1  mrg     {
     62   1.1  mrg       typedef _DifferenceTp _DifferenceType;
     63   1.1  mrg       while (__begin1 != __end1 && __begin2 != __end2 && __max_length > 0)
     64   1.1  mrg         {
     65   1.1  mrg           // array1[__i1] < array0[i0]
     66   1.1  mrg           if (__comp(*__begin2, *__begin1))
     67   1.1  mrg             *__target++ = *__begin2++;
     68   1.1  mrg           else
     69   1.1  mrg             *__target++ = *__begin1++;
     70   1.1  mrg           --__max_length;
     71   1.1  mrg         }
     72   1.1  mrg 
     73   1.1  mrg       if (__begin1 != __end1)
     74   1.1  mrg         {
     75   1.1  mrg           __target = std::copy(__begin1, __begin1 + __max_length, __target);
     76   1.1  mrg           __begin1 += __max_length;
     77   1.1  mrg         }
     78   1.1  mrg       else
     79   1.1  mrg         {
     80   1.1  mrg           __target = std::copy(__begin2, __begin2 + __max_length, __target);
     81   1.1  mrg           __begin2 += __max_length;
     82   1.1  mrg         }
     83   1.1  mrg       return __target;
     84   1.1  mrg     }
     85   1.1  mrg 
     86   1.1  mrg   /** @brief Merge routine being able to merge only the @c __max_length
     87   1.1  mrg    * smallest elements.
     88   1.1  mrg    *
     89   1.1  mrg    * The @c __begin iterators are advanced accordingly, they might not
     90   1.1  mrg    * reach @c __end, in contrast to the usual variant.
     91   1.1  mrg    * Specially designed code should allow the compiler to generate
     92   1.1  mrg    * conditional moves instead of branches.
     93   1.1  mrg    * @param __begin1 Begin iterator of first sequence.
     94   1.1  mrg    * @param __end1 End iterator of first sequence.
     95   1.1  mrg    * @param __begin2 Begin iterator of second sequence.
     96   1.1  mrg    * @param __end2 End iterator of second sequence.
     97   1.1  mrg    * @param __target Target begin iterator.
     98   1.1  mrg    * @param __max_length Maximum number of elements to merge.
     99   1.1  mrg    * @param __comp Comparator.
    100   1.1  mrg    * @return Output end iterator. */
    101   1.1  mrg   template<typename _RAIter1, typename _RAIter2,
    102   1.1  mrg            typename _OutputIterator, typename _DifferenceTp,
    103   1.1  mrg            typename _Compare>
    104   1.1  mrg     _OutputIterator
    105   1.1  mrg     __merge_advance_movc(_RAIter1& __begin1, _RAIter1 __end1,
    106   1.1  mrg 			 _RAIter2& __begin2, _RAIter2 __end2,
    107   1.1  mrg 			 _OutputIterator __target,
    108   1.1  mrg 			 _DifferenceTp __max_length, _Compare __comp)
    109   1.1  mrg     {
    110   1.1  mrg       typedef _DifferenceTp _DifferenceType;
    111   1.1  mrg       typedef typename std::iterator_traits<_RAIter1>::value_type
    112   1.1  mrg         _ValueType1;
    113   1.1  mrg       typedef typename std::iterator_traits<_RAIter2>::value_type
    114   1.1  mrg         _ValueType2;
    115   1.1  mrg 
    116   1.8  mrg #if _GLIBCXX_PARALLEL_ASSERTIONS
    117   1.1  mrg       _GLIBCXX_PARALLEL_ASSERT(__max_length >= 0);
    118   1.1  mrg #endif
    119   1.1  mrg 
    120   1.1  mrg       while (__begin1 != __end1 && __begin2 != __end2 && __max_length > 0)
    121   1.1  mrg         {
    122   1.1  mrg           _RAIter1 __next1 = __begin1 + 1;
    123   1.1  mrg           _RAIter2 __next2 = __begin2 + 1;
    124   1.1  mrg           _ValueType1 __element1 = *__begin1;
    125   1.1  mrg           _ValueType2 __element2 = *__begin2;
    126   1.1  mrg 
    127   1.1  mrg           if (__comp(__element2, __element1))
    128   1.1  mrg             {
    129   1.1  mrg               __element1 = __element2;
    130   1.1  mrg               __begin2 = __next2;
    131   1.1  mrg             }
    132   1.1  mrg           else
    133   1.1  mrg             __begin1 = __next1;
    134   1.1  mrg 
    135   1.1  mrg           *__target = __element1;
    136   1.1  mrg 
    137   1.1  mrg           ++__target;
    138   1.1  mrg           --__max_length;
    139   1.1  mrg         }
    140   1.1  mrg       if (__begin1 != __end1)
    141   1.1  mrg         {
    142   1.1  mrg           __target = std::copy(__begin1, __begin1 + __max_length, __target);
    143   1.1  mrg           __begin1 += __max_length;
    144   1.1  mrg         }
    145   1.1  mrg       else
    146   1.1  mrg         {
    147   1.1  mrg           __target = std::copy(__begin2, __begin2 + __max_length, __target);
    148   1.1  mrg           __begin2 += __max_length;
    149   1.1  mrg         }
    150   1.1  mrg       return __target;
    151   1.1  mrg     }
    152   1.1  mrg 
    153   1.1  mrg   /** @brief Merge routine being able to merge only the @c __max_length
    154   1.1  mrg    * smallest elements.
    155   1.1  mrg    *
    156   1.1  mrg    *  The @c __begin iterators are advanced accordingly, they might not
    157   1.1  mrg    *  reach @c __end, in contrast to the usual variant.
    158   1.1  mrg    *  Static switch on whether to use the conditional-move variant.
    159   1.1  mrg    *  @param __begin1 Begin iterator of first sequence.
    160   1.1  mrg    *  @param __end1 End iterator of first sequence.
    161   1.1  mrg    *  @param __begin2 Begin iterator of second sequence.
    162   1.1  mrg    *  @param __end2 End iterator of second sequence.
    163   1.1  mrg    *  @param __target Target begin iterator.
    164   1.1  mrg    *  @param __max_length Maximum number of elements to merge.
    165   1.1  mrg    *  @param __comp Comparator.
    166   1.1  mrg    *  @return Output end iterator. */
    167   1.1  mrg   template<typename _RAIter1, typename _RAIter2,
    168   1.1  mrg            typename _OutputIterator, typename _DifferenceTp,
    169   1.1  mrg            typename _Compare>
    170   1.1  mrg     inline _OutputIterator
    171   1.1  mrg     __merge_advance(_RAIter1& __begin1, _RAIter1 __end1,
    172   1.1  mrg 		    _RAIter2& __begin2, _RAIter2 __end2,
    173   1.1  mrg 		    _OutputIterator __target, _DifferenceTp __max_length,
    174   1.1  mrg 		    _Compare __comp)
    175   1.1  mrg     {
    176   1.1  mrg       _GLIBCXX_CALL(__max_length)
    177   1.1  mrg 
    178   1.1  mrg       return __merge_advance_movc(__begin1, __end1, __begin2, __end2,
    179   1.1  mrg 				  __target, __max_length, __comp);
    180   1.1  mrg     }
    181   1.1  mrg 
    182   1.1  mrg   /** @brief Merge routine fallback to sequential in case the
    183   1.1  mrg       iterators of the two input sequences are of different type.
    184   1.1  mrg       *  @param __begin1 Begin iterator of first sequence.
    185   1.1  mrg       *  @param __end1 End iterator of first sequence.
    186   1.1  mrg       *  @param __begin2 Begin iterator of second sequence.
    187   1.1  mrg       *  @param __end2 End iterator of second sequence.
    188   1.1  mrg       *  @param __target Target begin iterator.
    189   1.1  mrg       *  @param __max_length Maximum number of elements to merge.
    190   1.1  mrg       *  @param __comp Comparator.
    191   1.1  mrg       *  @return Output end iterator. */
    192   1.1  mrg   template<typename _RAIter1, typename _RAIter2,
    193   1.1  mrg            typename _RAIter3, typename _Compare>
    194   1.1  mrg     inline _RAIter3
    195   1.1  mrg     __parallel_merge_advance(_RAIter1& __begin1, _RAIter1 __end1,
    196   1.1  mrg 			     _RAIter2& __begin2,
    197   1.1  mrg 			     // different iterators, parallel implementation
    198   1.1  mrg 			     // not available
    199   1.1  mrg 			     _RAIter2 __end2, _RAIter3 __target, typename
    200   1.1  mrg 			     std::iterator_traits<_RAIter1>::
    201   1.1  mrg 			     difference_type __max_length, _Compare __comp)
    202   1.1  mrg     { return __merge_advance(__begin1, __end1, __begin2, __end2, __target,
    203   1.1  mrg 			     __max_length, __comp); }
    204   1.1  mrg 
    205   1.1  mrg   /** @brief Parallel merge routine being able to merge only the @c
    206   1.1  mrg    * __max_length smallest elements.
    207   1.1  mrg    *
    208   1.1  mrg    *  The @c __begin iterators are advanced accordingly, they might not
    209   1.1  mrg    *  reach @c __end, in contrast to the usual variant.
    210   1.1  mrg    *  The functionality is projected onto parallel_multiway_merge.
    211   1.1  mrg    *  @param __begin1 Begin iterator of first sequence.
    212   1.1  mrg    *  @param __end1 End iterator of first sequence.
    213   1.1  mrg    *  @param __begin2 Begin iterator of second sequence.
    214   1.1  mrg    *  @param __end2 End iterator of second sequence.
    215   1.1  mrg    *  @param __target Target begin iterator.
    216   1.1  mrg    *  @param __max_length Maximum number of elements to merge.
    217   1.1  mrg    *  @param __comp Comparator.
    218   1.1  mrg    *  @return Output end iterator.
    219   1.1  mrg    */
    220   1.1  mrg   template<typename _RAIter1, typename _RAIter3,
    221   1.1  mrg            typename _Compare>
    222   1.1  mrg     inline _RAIter3
    223   1.1  mrg     __parallel_merge_advance(_RAIter1& __begin1, _RAIter1 __end1,
    224   1.1  mrg 			     _RAIter1& __begin2, _RAIter1 __end2,
    225   1.1  mrg 			     _RAIter3 __target, typename
    226   1.1  mrg 			     std::iterator_traits<_RAIter1>::
    227   1.1  mrg 			     difference_type __max_length, _Compare __comp)
    228   1.1  mrg     {
    229   1.1  mrg       typedef typename
    230   1.1  mrg           std::iterator_traits<_RAIter1>::value_type _ValueType;
    231   1.1  mrg       typedef typename std::iterator_traits<_RAIter1>::
    232   1.1  mrg         difference_type _DifferenceType1 /* == difference_type2 */;
    233   1.1  mrg       typedef typename std::iterator_traits<_RAIter3>::
    234   1.1  mrg         difference_type _DifferenceType3;
    235   1.1  mrg       typedef typename std::pair<_RAIter1, _RAIter1>
    236   1.1  mrg         _IteratorPair;
    237   1.1  mrg 
    238   1.1  mrg       _IteratorPair __seqs[2] = { std::make_pair(__begin1, __end1),
    239   1.1  mrg 				  std::make_pair(__begin2, __end2) };
    240   1.1  mrg       _RAIter3 __target_end = parallel_multiway_merge
    241   1.1  mrg 	< /* __stable = */ true, /* __sentinels = */ false>
    242   1.1  mrg 	(__seqs, __seqs + 2, __target, multiway_merge_exact_splitting
    243   1.1  mrg 	 < /* __stable = */ true, _IteratorPair*,
    244   1.1  mrg 	 _Compare, _DifferenceType1>, __max_length, __comp,
    245   1.1  mrg 	 omp_get_max_threads());
    246   1.1  mrg 
    247   1.1  mrg       return __target_end;
    248   1.1  mrg     }
    249   1.1  mrg }       //namespace __gnu_parallel
    250   1.1  mrg 
    251   1.1  mrg #endif /* _GLIBCXX_PARALLEL_MERGE_H */
    252